From 42a06270bf1250a9bbffa529ac5c795c78145b39 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 18:26:31 +0200 Subject: [PATCH 01/56] LOCAL: add Gitlab CI jobs Co-authored-by: Anton Maklakov Co-authored-by: Omar Chebib --- .gitlab-ci.yml | 79 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9762dda2ee3a..73ef191f1760 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,24 +1,57 @@ -# -# This is the GitLab CI configuration file for the mainstream QEMU -# project: https://gitlab.com/qemu-project/qemu/-/pipelines -# -# !!! DO NOT ADD ANY NEW CONFIGURATION TO THIS FILE !!! -# -# Only documentation or comments is accepted. -# -# To use a different set of jobs than the mainstream QEMU project, -# you need to set the location of your custom yml file at "custom CI/CD -# configuration path", on your GitLab CI namespace: -# https://docs.gitlab.com/ee/ci/pipelines/settings.html#custom-cicd-configuration-path -# -# ---------------------------------------------------------------------- -# -# QEMU CI jobs are based on templates. Some templates provide -# user-configurable options, modifiable via configuration variables. -# -# See https://qemu-project.gitlab.io/qemu/devel/ci.html#custom-ci-cd-variables -# for more information. -# +stages: + - build + - deploy -include: - - local: '/.gitlab-ci.d/qemu-project.yml' +build-linux: + stage: build + image: $CI_DOCKER_REGISTRY/qemu-build:5 + tags: + - build + - amd64 + artifacts: + paths: + - dist/esp-qemu-*.tar.bz2 + - dist/archive_name_* + expire_in: 1 week + parallel: + matrix: + - PLATFORM: [x86_64-linux-gnu] + TARGET: [riscv32-linux-user, xtensa-softmmu, riscv32-softmmu] + script: + - ./configure --prefix=/opt/qemu --target-list=${TARGET} --extra-cflags=-Werror --disable-capstone --disable-vnc --disable-sdl --disable-gtk --enable-gcrypt --enable-slirp + - ninja -C build install + - find /opt/qemu/share/qemu -maxdepth 1 -mindepth 1 -not -name 'esp*.bin' -exec rm -rf {} \; + - mkdir -p dist + - DIST_DIR=${PWD}/dist + + - VERSION=${CI_COMMIT_TAG:-""} + - VERSION=${VERSION#"esp-v"} # remove prefix in tags like `esp-v7.1.0_20221221` + - VERSION=${VERSION#"esp-"} # remove prefix in tags like `esp-develop-20221221` + - VERSION=${VERSION//"-"/"_"} # replace dashes with underscores in the version + - VERSION=${VERSION:-${CI_COMMIT_SHORT_SHA}} + + - export ARCHIVE_NAME=esp-qemu-${TARGET}-${VERSION}-${PLATFORM}.tar.bz2 + - cd /opt + - tar cjvf ${DIST_DIR}/${ARCHIVE_NAME} qemu + - echo $ARCHIVE_NAME >${DIST_DIR}/archive_name_${TARGET}_${PLATFORM} + +upload_to_http: + image: espressif/scp + stage: deploy + tags: + - deploy + - shiny + when: manual + allow_failure: true + variables: + # don't use "GIT_STRATEGY: none", because we need cleaning old artifacts in 'dist/' that came from previous pipelines + SSH_KEY: "$HTTP_UPLOAD_KEY" # used inside 'espressif/scp' + script: + # List of archives in dist/ + - FILES=$(find dist -name archive_name_\* -exec cat {} \+) + - cd dist + - scp ${FILES} ${HTTP_UPLOAD_DIR} + # Show info + - /bin/ls -l ${FILES} + - sha256sum ${FILES} + - echo -e "\nArchives were published there:\n\n$(for n in ${FILES}; do echo "${HTTP_PUBLIC_DIR}/${n}"; done)\n" From 4f972e517e2584d73bc6a120296056c26f07847d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 20 Jul 2022 20:39:23 +0200 Subject: [PATCH 02/56] LOCAL: add Github actions for Jira sync --- .github/workflows/issue_comment.yml | 20 +++++++++++++++++++ .github/workflows/lockdown.yml | 30 ----------------------------- .github/workflows/new_issues.yml | 20 +++++++++++++++++++ .github/workflows/new_prs.yml | 25 ++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/issue_comment.yml delete mode 100644 .github/workflows/lockdown.yml create mode 100644 .github/workflows/new_issues.yml create mode 100644 .github/workflows/new_prs.yml diff --git a/.github/workflows/issue_comment.yml b/.github/workflows/issue_comment.yml new file mode 100644 index 000000000000..a339e2310b6f --- /dev/null +++ b/.github/workflows/issue_comment.yml @@ -0,0 +1,20 @@ +name: Sync issue comments to JIRA + +# This workflow will be triggered when new issue comment is created (including PR comments) +on: issue_comment + +jobs: + sync_issue_comments_to_jira: + name: Sync Issue Comments to Jira + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Sync issue comments to JIRA + uses: espressif/github-actions/sync_issues_to_jira@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_PASS: ${{ secrets.JIRA_PASS }} + JIRA_PROJECT: QEMU + JIRA_COMPONENT: GitHub + JIRA_URL: ${{ secrets.JIRA_URL }} + JIRA_USER: ${{ secrets.JIRA_USER }} diff --git a/.github/workflows/lockdown.yml b/.github/workflows/lockdown.yml deleted file mode 100644 index d5e1265cffb3..000000000000 --- a/.github/workflows/lockdown.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown - -name: 'Repo Lockdown' - -on: - pull_request_target: - types: opened - -permissions: - pull-requests: write - -jobs: - action: - runs-on: ubuntu-latest - steps: - - uses: dessant/repo-lockdown@v2 - with: - pr-comment: | - Thank you for your interest in the QEMU project. - - This repository is a read-only mirror of the project's repostories hosted - on https://gitlab.com/qemu-project/qemu.git. - The project does not process merge requests filed on GitHub. - - QEMU welcomes contributions of code (either fixing bugs or adding new - functionality). However, we get a lot of patches, and so we have some - guidelines about contributing on the project website: - https://www.qemu.org/contribute/ - lock-pr: true - close-pr: true diff --git a/.github/workflows/new_issues.yml b/.github/workflows/new_issues.yml new file mode 100644 index 000000000000..002e8cb680de --- /dev/null +++ b/.github/workflows/new_issues.yml @@ -0,0 +1,20 @@ +name: Sync issues to Jira + +# This workflow will be triggered when a new issue is opened +on: issues + +jobs: + sync_issues_to_jira: + name: Sync issues to Jira + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Sync GitHub issues to Jira project + uses: espressif/github-actions/sync_issues_to_jira@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_PASS: ${{ secrets.JIRA_PASS }} + JIRA_PROJECT: QEMU + JIRA_COMPONENT: GitHub + JIRA_URL: ${{ secrets.JIRA_URL }} + JIRA_USER: ${{ secrets.JIRA_USER }} diff --git a/.github/workflows/new_prs.yml b/.github/workflows/new_prs.yml new file mode 100644 index 000000000000..3dcfce840c1c --- /dev/null +++ b/.github/workflows/new_prs.yml @@ -0,0 +1,25 @@ +name: Sync remain PRs to Jira + +# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project +# Note that, PRs can also get synced when new PR comment is created +on: + schedule: + - cron: "0 * * * *" + +jobs: + sync_prs_to_jira: + name: Sync PRs to Jira + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Sync PRs to Jira project + uses: espressif/github-actions/sync_issues_to_jira@master + with: + cron_job: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_PASS: ${{ secrets.JIRA_PASS }} + JIRA_PROJECT: QEMU + JIRA_COMPONENT: GitHub + JIRA_URL: ${{ secrets.JIRA_URL }} + JIRA_USER: ${{ secrets.JIRA_USER }} From a9821ff545ec511503e12c1589272bf50c9dfbcb Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 17 May 2021 12:45:36 +0200 Subject: [PATCH 03/56] LOCAL: Revert "tcg: Optimize inline dup_const for MO_64" This reverts commit 666cc794abe7aa2e123a0963934e519d28a7102c. --- include/tcg/tcg.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 5cfaa5393848..333fc437cbb7 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -1190,8 +1190,7 @@ uint64_t dup_const(unsigned vece, uint64_t c); ? ( (VECE) == MO_8 ? 0x0101010101010101ull * (uint8_t)(C) \ : (VECE) == MO_16 ? 0x0001000100010001ull * (uint16_t)(C) \ : (VECE) == MO_32 ? 0x0000000100000001ull * (uint32_t)(C) \ - : (VECE) == MO_64 ? (uint64_t)(C) \ - : (qemu_build_not_reached_always(), 0)) \ + : dup_const(VECE, C)) \ : dup_const(VECE, C)) #if TARGET_LONG_BITS == 64 From 19dd0fda1a5939c1d8e47683e476ca1a27e7b73c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 23 Jul 2021 16:39:57 +0200 Subject: [PATCH 04/56] xtensa: don't send window registers to GDB GDB considers window registers as pseudo registers, meaning that they are calculated by GDB using the values of AR registers and windowbase. This patch removes the window registers from the total number of registers that QEMU will send to GDB, making the number of registers match the one that GDB expects to see. --- target/xtensa/gdbstub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/xtensa/gdbstub.c b/target/xtensa/gdbstub.c index 4b3bfb7e59c4..484144500487 100644 --- a/target/xtensa/gdbstub.c +++ b/target/xtensa/gdbstub.c @@ -49,7 +49,8 @@ void xtensa_count_regs(const XtensaConfig *config, for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) { if (config->gdb_regmap.reg[i].type != xtRegisterTypeTieState && config->gdb_regmap.reg[i].type != xtRegisterTypeMapped && - config->gdb_regmap.reg[i].type != xtRegisterTypeUnmapped) { + config->gdb_regmap.reg[i].type != xtRegisterTypeUnmapped && + config->gdb_regmap.reg[i].type != xtRegisterTypeWindow) { ++*n_regs; if (count_core_regs) { if ((config->gdb_regmap.reg[i].flags & From fe84285898150dcc8c08bfce23721d6ed3153c7a Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 25 Jul 2021 17:56:35 +0200 Subject: [PATCH 05/56] LOCAL: target/xtensa: allow tweaking the list of registers sent to GDB This commit introduces two environment variables which can be used to adjust the list of registers sent from QEMU to GDB: * If QEMU_XTENSA_CORE_REGS_ONLY is set, only non-privileged registers will be sent to GDB. This behavior is compatible with Espressif builds of GDB up to esp-2021r1. * If QEMU_XTENSA_COUNT_WINDOW_REGS is set, QEMU will send window registers (a0-a15) to GDB. Enable this if you don't have a build of GDB which considers a0-a15 to be "raw" registers. --- target/xtensa/gdbstub.c | 8 +++++++- target/xtensa/helper.c | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/target/xtensa/gdbstub.c b/target/xtensa/gdbstub.c index 484144500487..91e1465ade26 100644 --- a/target/xtensa/gdbstub.c +++ b/target/xtensa/gdbstub.c @@ -46,11 +46,17 @@ void xtensa_count_regs(const XtensaConfig *config, unsigned i; bool count_core_regs = true; + /* Espressif local: allow changing the behavior here based on QEMU_XTENSA_COUNT_WINDOW_REGS + * environment variable. + */ + const char* count_window_regs_env = getenv("QEMU_XTENSA_COUNT_WINDOW_REGS"); + bool count_window_regs = count_window_regs_env != NULL && strcmp(count_window_regs_env, "0") != 0; + for (i = 0; config->gdb_regmap.reg[i].targno >= 0; ++i) { if (config->gdb_regmap.reg[i].type != xtRegisterTypeTieState && config->gdb_regmap.reg[i].type != xtRegisterTypeMapped && config->gdb_regmap.reg[i].type != xtRegisterTypeUnmapped && - config->gdb_regmap.reg[i].type != xtRegisterTypeWindow) { + (config->gdb_regmap.reg[i].type != xtRegisterTypeWindow || count_window_regs)) { ++*n_regs; if (count_core_regs) { if ((config->gdb_regmap.reg[i].flags & diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c index dbeb97a953cc..57de5eac3777 100644 --- a/target/xtensa/helper.c +++ b/target/xtensa/helper.c @@ -185,6 +185,15 @@ static void xtensa_core_class_init(ObjectClass *oc, void *data) * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay. */ cc->gdb_num_core_regs = config->gdb_regmap.num_regs; + + /* Espressif local: allow changing the behavior here using + * QEMU_XTENSA_CORE_REGS_ONLY environment variable, to support different + * GDB builds + */ + const char* core_regs_only = getenv("QEMU_XTENSA_CORE_REGS_ONLY"); + if (core_regs_only != NULL && strcmp(core_regs_only, "0") != 0) { + cc->gdb_num_core_regs = config->gdb_regmap.num_core_regs; + } } void xtensa_register_core(XtensaConfigList *node) From c960a17cdddee0cf50685b9f119392de4395995c Mon Sep 17 00:00:00 2001 From: Martin Johnson Date: Wed, 28 Apr 2021 15:33:30 +1200 Subject: [PATCH 06/56] hw/block: correct DIO mode for Gigadevice SPI NOR flash --- hw/block/m25p80.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index dc5ffbc4ff52..6815553df083 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -171,6 +171,8 @@ typedef struct FlashPartInfo { #define SPANSION_CONTINUOUS_READ_MODE_CMD_LEN 1 #define WINBOND_CONTINUOUS_READ_MODE_CMD_LEN 1 +#define GIGADEVICE_CONTINUOUS_READ_MODE_CMD_LEN 1 + static const FlashPartInfo known_devices[] = { /* Atmel -- some are (confusingly) marketed as "DataFlash" */ @@ -445,6 +447,7 @@ typedef enum { MAN_WINBOND, MAN_SST, MAN_ISSI, + MAN_GIGADEVICE, MAN_GENERIC, } Manufacturer; @@ -529,6 +532,8 @@ static inline Manufacturer get_man(Flash *s) return MAN_SST; case 0x9D: return MAN_ISSI; + case 0xC8: + return MAN_GIGADEVICE; default: return MAN_GENERIC; } @@ -1014,6 +1019,9 @@ static void decode_dio_read_cmd(Flash *s) case MAN_WINBOND: s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN; break; + case MAN_GIGADEVICE: + s->needed_bytes += GIGADEVICE_CONTINUOUS_READ_MODE_CMD_LEN; + break; case MAN_SPANSION: s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN; s->needed_bytes += extract32(s->spansion_cr2v, @@ -1061,6 +1069,7 @@ static void decode_qio_read_cmd(Flash *s) /* Dummy cycles modeled with bytes writes instead of bits */ switch (get_man(s)) { case MAN_WINBOND: + case MAN_GIGADEVICE: s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN; s->needed_bytes += 4; break; From 1c1c4e98621af0cf18dc733e826814d502ff750c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 Jun 2021 18:59:59 +0200 Subject: [PATCH 07/56] hw/net: opencores_eth: fix handling of DP83848C PHYSTS register DP83848C PHY emulated by opencores_eth has several vendor-specific MII registers at 0x10-0x1d. Reading these registers resulted in an out-of-bounds access to the regs array. Part of this commit adds bounds checking. Since the PHYSTS vendor-specific register is accessed by some of the embedded DP83848C drivers, the rest of the commit adds simple emulation of this register, setting the bits depending on the link status. --- hw/net/opencores_eth.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c index 0b3dc3146e61..ff62b2667310 100644 --- a/hw/net/opencores_eth.c +++ b/hw/net/opencores_eth.c @@ -57,11 +57,20 @@ #define SET_REGFIELD(s, reg, field, data) \ SET_FIELD((s)->regs[reg], reg ## _ ## field, data) -/* PHY MII registers */ +/* DP83848C PHY MII registers. + * Registers 0x0-0xf are standard, 0x10-0x1d are vendor-specific. + */ enum { - MII_REG_MAX = 16, + MII_PHYSTS = 0x10, + MII_REG_MAX = 0x1e }; +/* DP83848C PHYSTS register bits */ +#define MII_PHYSTS_LINK (1 << 0) +#define MII_PHYSTS_SPEED (1 << 1) +#define MII_PHYSTS_DUPLEX (1 << 2) +#define MII_PHYSTS_ANC (1 << 4) /* auto-negotiation complete */ + typedef struct Mii { uint16_t regs[MII_REG_MAX]; bool link_ok; @@ -73,9 +82,12 @@ static void mii_set_link(Mii *s, bool link_ok) s->regs[MII_BMSR] |= MII_BMSR_LINK_ST; s->regs[MII_ANLPAR] |= MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD | MII_ANLPAR_10 | MII_ANLPAR_CSMACD; + s->regs[MII_PHYSTS] = MII_PHYSTS_LINK | MII_PHYSTS_SPEED | + MII_PHYSTS_DUPLEX | MII_PHYSTS_ANC; } else { s->regs[MII_BMSR] &= ~MII_BMSR_LINK_ST; s->regs[MII_ANLPAR] &= 0x01ff; + s->regs[MII_PHYSTS] = 0; } s->link_ok = link_ok; } @@ -114,6 +126,7 @@ static void mii_write_host(Mii *s, unsigned idx, uint16_t v) [MII_BMSR] = mii_ro, [MII_PHYID1] = mii_ro, [MII_PHYID2] = mii_ro, + [MII_PHYSTS] = mii_ro, }; if (idx < MII_REG_MAX) { @@ -128,8 +141,11 @@ static void mii_write_host(Mii *s, unsigned idx, uint16_t v) static uint16_t mii_read_host(Mii *s, unsigned idx) { - trace_open_eth_mii_read(idx, s->regs[idx]); - return s->regs[idx]; + if (idx < MII_REG_MAX) { + trace_open_eth_mii_read(idx, s->regs[idx]); + return s->regs[idx]; + } + return 0; } /* OpenCores Ethernet registers */ From f5dfe00d6f214b7773c2b268296fecfe7fbef497 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 8 Aug 2019 17:21:51 +0200 Subject: [PATCH 08/56] target/xtensa: add stubs for "DFP Accelerator" instructions --- target/xtensa/translate.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 0cf3075649d1..0c5c080cf044 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -2671,6 +2671,12 @@ static void translate_wur(DisasContext *dc, const OpcodeArg arg[], tcg_gen_mov_i32(cpu_UR[par[0]], arg[0].in); } +static void translate_xur_f64(DisasContext *dc, const OpcodeArg arg[], + const uint32_t par[]) +{ + /* no-op */ +} + static void translate_xor(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { @@ -5445,6 +5451,24 @@ static const XtensaOpcodeOps core_ops[] = { .name = "wur.expstate", .translate = translate_wur, .par = (const uint32_t[]){EXPSTATE}, + }, { + .name = "wur.f64r_lo", + .translate = translate_xur_f64, + }, { + .name = "wur.f64r_hi", + .translate = translate_xur_f64, + }, { + .name = "wur.f64s", + .translate = translate_xur_f64, + }, { + .name = "rur.f64r_lo", + .translate = translate_xur_f64, + }, { + .name = "rur.f64r_hi", + .translate = translate_xur_f64, + }, { + .name = "rur.f64s", + .translate = translate_xur_f64, }, { .name = "wur.threadptr", .translate = translate_wur, From 82063f9cb4710adcd12d7fa2642499d9d36c871e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:34:12 +0200 Subject: [PATCH 09/56] target/xtensa: add ESP32 core configuration --- target/xtensa/core-esp32.c | 40 + target/xtensa/core-esp32/core-isa.h | 655 + target/xtensa/core-esp32/gdb-config.inc.c | 290 + target/xtensa/core-esp32/xtensa-modules.inc.c | 19196 ++++++++++++++++ target/xtensa/cores.list | 1 + 5 files changed, 20182 insertions(+) create mode 100644 target/xtensa/core-esp32.c create mode 100644 target/xtensa/core-esp32/core-isa.h create mode 100644 target/xtensa/core-esp32/gdb-config.inc.c create mode 100644 target/xtensa/core-esp32/xtensa-modules.inc.c diff --git a/target/xtensa/core-esp32.c b/target/xtensa/core-esp32.c new file mode 100644 index 000000000000..20f5644cd650 --- /dev/null +++ b/target/xtensa/core-esp32.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/gdbstub.h" +#include "qemu-common.h" +#include "qemu/host-utils.h" + +#include "core-esp32/core-isa.h" +#include "overlay_tool.h" + +#define xtensa_modules xtensa_modules_esp32 +#include "core-esp32/xtensa-modules.inc.c" + +static const XtensaOpcodeTranslators* esp32_opcode_translators[] = { + &xtensa_core_opcodes, + &xtensa_fpu_opcodes, + NULL +}; + +static XtensaConfig xtensa_core_esp32 __attribute__((unused)) = { + .name = "esp32", + .gdb_regmap = { + .reg = { +#include "core-esp32/gdb-config.inc.c" + } + }, + .isa_internal = &xtensa_modules, + .clock_freq_khz = 40000, + .opcode_translators = esp32_opcode_translators, + DEFAULT_SECTIONS +}; + +REGISTER_CORE(xtensa_core_esp32) diff --git a/target/xtensa/core-esp32/core-isa.h b/target/xtensa/core-esp32/core-isa.h new file mode 100644 index 000000000000..f3f4e45f001f --- /dev/null +++ b/target/xtensa/core-esp32/core-isa.h @@ -0,0 +1,655 @@ +/* + * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa + * processor CORE configuration + * + * See , which includes this file, for more details. + */ + +/* Xtensa processor core configuration information. + + Copyright (c) 1999-2016 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 3 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_LOOP_BUFFER_SIZE 256 /* zero-ov. loop instr buffer size */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_DEPBITS 0 /* DEPBITS instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 1 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 0 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ +/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 1 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 1 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 1 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 1 /* processor ID register */ +#define XCHAL_HAVE_EXTERN_REGS 1 /* WER/RER instructions */ +#define XCHAL_HAVE_MX 0 /* MX core (Tensilica internal) */ +#define XCHAL_HAVE_MP_INTERRUPTS 0 /* interrupt distributor port */ +#define XCHAL_HAVE_MP_RUNSTALL 0 /* core RunStall control port */ +#define XCHAL_HAVE_PSO 0 /* Power Shut-Off */ +#define XCHAL_HAVE_PSO_CDM 0 /* core/debug/mem pwr domains */ +#define XCHAL_HAVE_PSO_FULL_RETENTION 0 /* all regs preserved on PSO */ +#define XCHAL_HAVE_THREADPTR 1 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 8 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 1 /* MAC16 package */ + +#define XCHAL_HAVE_FUSION 0 /* Fusion*/ +#define XCHAL_HAVE_FUSION_FP 0 /* Fusion FP option */ +#define XCHAL_HAVE_FUSION_LOW_POWER 0 /* Fusion Low Power option */ +#define XCHAL_HAVE_FUSION_AES 0 /* Fusion BLE/Wifi AES-128 CCM option */ +#define XCHAL_HAVE_FUSION_CONVENC 0 /* Fusion Conv Encode option */ +#define XCHAL_HAVE_FUSION_LFSR_CRC 0 /* Fusion LFSR-CRC option */ +#define XCHAL_HAVE_FUSION_BITOPS 0 /* Fusion Bit Operations Support option */ +#define XCHAL_HAVE_FUSION_AVS 0 /* Fusion AVS option */ +#define XCHAL_HAVE_FUSION_16BIT_BASEBAND 0 /* Fusion 16-bit Baseband option */ +#define XCHAL_HAVE_FUSION_VITERBI 0 /* Fusion Viterbi option */ +#define XCHAL_HAVE_FUSION_SOFTDEMAP 0 /* Fusion Soft Bit Demap option */ +#define XCHAL_HAVE_HIFIPRO 0 /* HiFiPro Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4 0 /* HiFi4 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI4_VFPU 0 /* HiFi4 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI3 0 /* HiFi3 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI3_VFPU 0 /* HiFi3 Audio Engine VFPU option */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ +#define XCHAL_HAVE_HIFI2EP 0 /* HiFi2EP */ +#define XCHAL_HAVE_HIFI_MINI 0 + + +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector or user floating-point pkg */ +#define XCHAL_HAVE_USER_DPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_USER_SPFPU 0 /* user DP floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* single prec floating point */ +#define XCHAL_HAVE_FP_DIV 1 /* FP with DIV instructions */ +#define XCHAL_HAVE_FP_RECIP 1 /* FP with RECIP instructions */ +#define XCHAL_HAVE_FP_SQRT 1 /* FP with SQRT instructions */ +#define XCHAL_HAVE_FP_RSQRT 1 /* FP with RSQRT instructions */ +#define XCHAL_HAVE_DFP 0 /* double precision FP pkg */ +#define XCHAL_HAVE_DFP_DIV 0 /* DFP with DIV instructions */ +#define XCHAL_HAVE_DFP_RECIP 0 /* DFP with RECIP instructions*/ +#define XCHAL_HAVE_DFP_SQRT 0 /* DFP with SQRT instructions */ +#define XCHAL_HAVE_DFP_RSQRT 0 /* DFP with RSQRT instructions*/ +#define XCHAL_HAVE_DFP_ACCEL 1 /* double precision FP acceleration pkg */ +#define XCHAL_HAVE_DFP_accel XCHAL_HAVE_DFP_ACCEL /* for backward compatibility */ + +#define XCHAL_HAVE_DFPU_SINGLE_ONLY 1 /* DFPU Coprocessor, single precision only */ +#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE 0 /* DFPU Coprocessor, single and double precision */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ +#define XCHAL_HAVE_PDX4 0 /* PDX4 */ +#define XCHAL_HAVE_CONNXD2 0 /* ConnX D2 pkg */ +#define XCHAL_HAVE_CONNXD2_DUALLSFLIX 0 /* ConnX D2 & Dual LoadStore Flix */ +#define XCHAL_HAVE_BBE16 0 /* ConnX BBE16 pkg */ +#define XCHAL_HAVE_BBE16_RSQRT 0 /* BBE16 & vector recip sqrt */ +#define XCHAL_HAVE_BBE16_VECDIV 0 /* BBE16 & vector divide */ +#define XCHAL_HAVE_BBE16_DESPREAD 0 /* BBE16 & despread */ +#define XCHAL_HAVE_BBENEP 0 /* ConnX BBENEP pkgs */ +#define XCHAL_HAVE_BSP3 0 /* ConnX BSP3 pkg */ +#define XCHAL_HAVE_BSP3_TRANSPOSE 0 /* BSP3 & transpose32x32 */ +#define XCHAL_HAVE_SSP16 0 /* ConnX SSP16 pkg */ +#define XCHAL_HAVE_SSP16_VITERBI 0 /* SSP16 & viterbi */ +#define XCHAL_HAVE_TURBO16 0 /* ConnX Turbo16 pkg */ +#define XCHAL_HAVE_BBP16 0 /* ConnX BBP16 pkg */ +#define XCHAL_HAVE_FLIX3 0 /* basic 3-way FLIX option */ +#define XCHAL_HAVE_GRIVPEP 0 /* GRIVPEP is General Release of IVPEP */ +#define XCHAL_HAVE_GRIVPEP_HISTOGRAM 0 /* Histogram option on GRIVPEP */ + + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_LOADSTORE_UNITS 1 /* load/store units */ +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 4 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 4 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 4 /* data width in bytes */ +#define XCHAL_DATA_PIPE_DELAY 2 /* d-side pipeline delay + (1 = 5-stage, 2 = 7-stage) */ +#define XCHAL_CLOCK_GATING_GLOBAL 1 /* global clock gating */ +#define XCHAL_CLOCK_GATING_FUNCUNIT 1 /* funct. unit clock gating */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 0 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 0 /* unaligned stores cause exc.*/ +#define XCHAL_UNALIGNED_LOAD_HW 1 /* unaligned loads work in hw */ +#define XCHAL_UNALIGNED_STORE_HW 1 /* unaligned stores work in hw*/ + +#define XCHAL_SW_VERSION 1100003 /* sw version of this header */ + +#define XCHAL_CORE_ID "esp32_v3_49_prod" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x0005FE96 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC2BCFFFE /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x1CC5FE96 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX6.0.3" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2600 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 3 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION 260003 /* major*100+minor */ +#define XCHAL_HW_REL_LX6 1 +#define XCHAL_HW_REL_LX6_0 1 +#define XCHAL_HW_REL_LX6_0_3 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2600 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 3 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 260003 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2600 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 3 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 260003 /* latest targeted hw */ + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 4 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 4 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 2 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 2 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 0 /* I-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE 0 /* D-cache size in bytes or 0 */ + +#define XCHAL_DCACHE_IS_WRITEBACK 0 /* writeback feature */ +#define XCHAL_DCACHE_IS_COHERENT 0 /* MP coherence feature */ + +#define XCHAL_HAVE_PREFETCH 0 /* PREFCTL register */ +#define XCHAL_HAVE_PREFETCH_L1 0 /* prefetch to L1 dcache */ +#define XCHAL_PREFETCH_CASTOUT_LINES 0 /* dcache pref. castout bufsz */ +#define XCHAL_PREFETCH_ENTRIES 0 /* cache prefetch entries */ +#define XCHAL_PREFETCH_BLOCK_ENTRIES 0 /* prefetch block streams */ +#define XCHAL_HAVE_CACHE_BLOCKOPS 0 /* block prefetch for caches */ +#define XCHAL_HAVE_ICACHE_TEST 0 /* Icache test instructions */ +#define XCHAL_HAVE_DCACHE_TEST 0 /* Dcache test instructions */ +#define XCHAL_HAVE_ICACHE_DYN_WAYS 0 /* Icache dynamic way support */ +#define XCHAL_HAVE_DCACHE_DYN_WAYS 0 /* Dcache dynamic way support */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */ +#define XCHAL_HAVE_AXI 0 /* AXI bus */ + +#define XCHAL_HAVE_PIF_WR_RESP 0 /* pif write response */ +#define XCHAL_HAVE_PIF_REQ_ATTR 0 /* pif attribute */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 0 +#define XCHAL_DCACHE_SETWIDTH 0 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 1 +#define XCHAL_DCACHE_WAYS 1 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 0 +#define XCHAL_DCACHE_LINE_LOCKABLE 0 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 + +/* Cache access size in bytes (affects operation of SICW instruction): */ +#define XCHAL_ICACHE_ACCESS_SIZE 1 +#define XCHAL_DCACHE_ACCESS_SIZE 1 + +#define XCHAL_DCACHE_BANKS 0 /* number of banks */ + +/* Number of encoded cache attr bits (see for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_INSTROM 1 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 2 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 1 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 2 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 1 /* number of core XLMI ports */ + +/* Instruction ROM 0: */ +#define XCHAL_INSTROM0_VADDR 0x40800000 /* virtual address */ +#define XCHAL_INSTROM0_PADDR 0x40800000 /* physical address */ +#define XCHAL_INSTROM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTROM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Instruction RAM 0: */ +#define XCHAL_INSTRAM0_VADDR 0x40000000 /* virtual address */ +#define XCHAL_INSTRAM0_PADDR 0x40000000 /* physical address */ +#define XCHAL_INSTRAM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTRAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Instruction RAM 1: */ +#define XCHAL_INSTRAM1_VADDR 0x40400000 /* virtual address */ +#define XCHAL_INSTRAM1_PADDR 0x40400000 /* physical address */ +#define XCHAL_INSTRAM1_SIZE 4194304 /* size in bytes */ +#define XCHAL_INSTRAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +/* Data ROM 0: */ +#define XCHAL_DATAROM0_VADDR 0x3F400000 /* virtual address */ +#define XCHAL_DATAROM0_PADDR 0x3F400000 /* physical address */ +#define XCHAL_DATAROM0_SIZE 4194304 /* size in bytes */ +#define XCHAL_DATAROM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATAROM0_BANKS 1 /* number of banks */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x3FF80000 /* virtual address */ +#define XCHAL_DATARAM0_PADDR 0x3FF80000 /* physical address */ +#define XCHAL_DATARAM0_SIZE 524288 /* size in bytes */ +#define XCHAL_DATARAM0_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM0_BANKS 1 /* number of banks */ + +/* Data RAM 1: */ +#define XCHAL_DATARAM1_VADDR 0x3F800000 /* virtual address */ +#define XCHAL_DATARAM1_PADDR 0x3F800000 /* physical address */ +#define XCHAL_DATARAM1_SIZE 4194304 /* size in bytes */ +#define XCHAL_DATARAM1_ECC_PARITY 0 /* ECC/parity type, 0=none */ +#define XCHAL_DATARAM1_BANKS 1 /* number of banks */ + +/* XLMI Port 0: */ +#define XCHAL_XLMI0_VADDR 0x3FF00000 /* virtual address */ +#define XCHAL_XLMI0_PADDR 0x3FF00000 /* physical address */ +#define XCHAL_XLMI0_SIZE 524288 /* size in bytes */ +#define XCHAL_XLMI0_ECC_PARITY 0 /* ECC/parity type, 0=none */ + +#define XCHAL_HAVE_IMEM_LOADSTORE 1 /* can load/store to IROM/IRAM*/ + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 32 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 26 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 6 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_EXCM_LEVEL 3 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x000637FF +#define XCHAL_INTLEVEL2_MASK 0x00380000 +#define XCHAL_INTLEVEL3_MASK 0x28C08800 +#define XCHAL_INTLEVEL4_MASK 0x53000000 +#define XCHAL_INTLEVEL5_MASK 0x84010000 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00004000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000637FF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x003E37FF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x28FEBFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x7BFEBFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0xFFFFBFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0xFFFFBFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0xFFFFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_INT9_LEVEL 1 +#define XCHAL_INT10_LEVEL 1 +#define XCHAL_INT11_LEVEL 3 +#define XCHAL_INT12_LEVEL 1 +#define XCHAL_INT13_LEVEL 1 +#define XCHAL_INT14_LEVEL 7 +#define XCHAL_INT15_LEVEL 3 +#define XCHAL_INT16_LEVEL 5 +#define XCHAL_INT17_LEVEL 1 +#define XCHAL_INT18_LEVEL 1 +#define XCHAL_INT19_LEVEL 2 +#define XCHAL_INT20_LEVEL 2 +#define XCHAL_INT21_LEVEL 2 +#define XCHAL_INT22_LEVEL 3 +#define XCHAL_INT23_LEVEL 3 +#define XCHAL_INT24_LEVEL 4 +#define XCHAL_INT25_LEVEL 4 +#define XCHAL_INT26_LEVEL 5 +#define XCHAL_INT27_LEVEL 3 +#define XCHAL_INT28_LEVEL 4 +#define XCHAL_INT29_LEVEL 3 +#define XCHAL_INT30_LEVEL 4 +#define XCHAL_INT31_LEVEL 5 +#define XCHAL_DEBUGLEVEL 6 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 7 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_PROFILING +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT25_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT26_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT27_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT28_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT29_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT30_TYPE XTHAL_INTTYPE_EXTERN_EDGE +#define XCHAL_INT31_TYPE XTHAL_INTTYPE_EXTERN_LEVEL + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0x00000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x20000080 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x50400400 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x8FBE333F +#define XCHAL_INTTYPE_MASK_TIMER 0x00018040 +#define XCHAL_INTTYPE_MASK_NMI 0x00004000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 +#define XCHAL_INTTYPE_MASK_PROFILING 0x00000800 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 6 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 15 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 16 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 14 /* non-maskable interrupt */ +#define XCHAL_PROFILING_INTERRUPT 11 /* profiling interrupt */ + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL7_NUM 14 +/* (There are many interrupts each at level(s) 1, 2, 3, 4, 5.) */ + + +/* + * External interrupt mapping. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 8 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 9 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 10 /* (intlevel 1) */ +#define XCHAL_EXTINT9_NUM 12 /* (intlevel 1) */ +#define XCHAL_EXTINT10_NUM 13 /* (intlevel 1) */ +#define XCHAL_EXTINT11_NUM 14 /* (intlevel 7) */ +#define XCHAL_EXTINT12_NUM 17 /* (intlevel 1) */ +#define XCHAL_EXTINT13_NUM 18 /* (intlevel 1) */ +#define XCHAL_EXTINT14_NUM 19 /* (intlevel 2) */ +#define XCHAL_EXTINT15_NUM 20 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 21 /* (intlevel 2) */ +#define XCHAL_EXTINT17_NUM 22 /* (intlevel 3) */ +#define XCHAL_EXTINT18_NUM 23 /* (intlevel 3) */ +#define XCHAL_EXTINT19_NUM 24 /* (intlevel 4) */ +#define XCHAL_EXTINT20_NUM 25 /* (intlevel 4) */ +#define XCHAL_EXTINT21_NUM 26 /* (intlevel 5) */ +#define XCHAL_EXTINT22_NUM 27 /* (intlevel 3) */ +#define XCHAL_EXTINT23_NUM 28 /* (intlevel 4) */ +#define XCHAL_EXTINT24_NUM 30 /* (intlevel 4) */ +#define XCHAL_EXTINT25_NUM 31 /* (intlevel 5) */ +/* EXTERNAL BInterrupt pin numbers mapped to each core interrupt number: */ +#define XCHAL_INT0_EXTNUM 0 /* (intlevel 1) */ +#define XCHAL_INT1_EXTNUM 1 /* (intlevel 1) */ +#define XCHAL_INT2_EXTNUM 2 /* (intlevel 1) */ +#define XCHAL_INT3_EXTNUM 3 /* (intlevel 1) */ +#define XCHAL_INT4_EXTNUM 4 /* (intlevel 1) */ +#define XCHAL_INT5_EXTNUM 5 /* (intlevel 1) */ +#define XCHAL_INT8_EXTNUM 6 /* (intlevel 1) */ +#define XCHAL_INT9_EXTNUM 7 /* (intlevel 1) */ +#define XCHAL_INT10_EXTNUM 8 /* (intlevel 1) */ +#define XCHAL_INT12_EXTNUM 9 /* (intlevel 1) */ +#define XCHAL_INT13_EXTNUM 10 /* (intlevel 1) */ +#define XCHAL_INT14_EXTNUM 11 /* (intlevel 7) */ +#define XCHAL_INT17_EXTNUM 12 /* (intlevel 1) */ +#define XCHAL_INT18_EXTNUM 13 /* (intlevel 1) */ +#define XCHAL_INT19_EXTNUM 14 /* (intlevel 2) */ +#define XCHAL_INT20_EXTNUM 15 /* (intlevel 2) */ +#define XCHAL_INT21_EXTNUM 16 /* (intlevel 2) */ +#define XCHAL_INT22_EXTNUM 17 /* (intlevel 3) */ +#define XCHAL_INT23_EXTNUM 18 /* (intlevel 3) */ +#define XCHAL_INT24_EXTNUM 19 /* (intlevel 4) */ +#define XCHAL_INT25_EXTNUM 20 /* (intlevel 4) */ +#define XCHAL_INT26_EXTNUM 21 /* (intlevel 5) */ +#define XCHAL_INT27_EXTNUM 22 /* (intlevel 3) */ +#define XCHAL_INT28_EXTNUM 23 /* (intlevel 4) */ +#define XCHAL_INT30_EXTNUM 24 /* (intlevel 4) */ +#define XCHAL_INT31_EXTNUM 25 /* (intlevel 5) */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (old) + 2 == XEA2 (new) + 0 == XEAX (extern) or TX */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_HALT 0 /* halt architecture option */ +#define XCHAL_HAVE_BOOTLOADER 0 /* boot loader (for TX) */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 1 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 1 /* relocatable vectors */ +#define XCHAL_VECBASE_RESET_VADDR 0x40000000 /* VECBASE reset value */ +#define XCHAL_VECBASE_RESET_PADDR 0x40000000 +#define XCHAL_RESET_VECBASE_OVERLAP 0 + +#define XCHAL_RESET_VECTOR0_VADDR 0x50000000 +#define XCHAL_RESET_VECTOR0_PADDR 0x50000000 +#define XCHAL_RESET_VECTOR1_VADDR 0x40000400 +#define XCHAL_RESET_VECTOR1_PADDR 0x40000400 +#define XCHAL_RESET_VECTOR_VADDR 0x40000400 +#define XCHAL_RESET_VECTOR_PADDR 0x40000400 +#define XCHAL_USER_VECOFS 0x00000340 +#define XCHAL_USER_VECTOR_VADDR 0x40000340 +#define XCHAL_USER_VECTOR_PADDR 0x40000340 +#define XCHAL_KERNEL_VECOFS 0x00000300 +#define XCHAL_KERNEL_VECTOR_VADDR 0x40000300 +#define XCHAL_KERNEL_VECTOR_PADDR 0x40000300 +#define XCHAL_DOUBLEEXC_VECOFS 0x000003C0 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x400003C0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x400003C0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x40000000 +#define XCHAL_WINDOW_VECTORS_PADDR 0x40000000 +#define XCHAL_INTLEVEL2_VECOFS 0x00000180 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x40000180 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x40000180 +#define XCHAL_INTLEVEL3_VECOFS 0x000001C0 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x400001C0 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x400001C0 +#define XCHAL_INTLEVEL4_VECOFS 0x00000200 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x40000200 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x40000200 +#define XCHAL_INTLEVEL5_VECOFS 0x00000240 +#define XCHAL_INTLEVEL5_VECTOR_VADDR 0x40000240 +#define XCHAL_INTLEVEL5_VECTOR_PADDR 0x40000240 +#define XCHAL_INTLEVEL6_VECOFS 0x00000280 +#define XCHAL_INTLEVEL6_VECTOR_VADDR 0x40000280 +#define XCHAL_INTLEVEL6_VECTOR_PADDR 0x40000280 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL6_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL6_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL6_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x000002C0 +#define XCHAL_NMI_VECTOR_VADDR 0x400002C0 +#define XCHAL_NMI_VECTOR_PADDR 0x400002C0 +#define XCHAL_INTLEVEL7_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL7_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL7_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG MODULE + ----------------------------------------------------------------------*/ + +/* Misc */ +#define XCHAL_HAVE_DEBUG_ERI 1 /* ERI to debug module */ +#define XCHAL_HAVE_DEBUG_APB 1 /* APB to debug module */ +#define XCHAL_HAVE_DEBUG_JTAG 1 /* JTAG to debug module */ + +/* On-Chip Debug (OCD) */ +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 0 /* faster OCD option (to LX4) */ +#define XCHAL_HAVE_OCD_LS32DDR 1 /* L32DDR/S32DDR (faster OCD) */ + +/* TRAX (in core) */ +#define XCHAL_HAVE_TRAX 1 /* TRAX in debug module */ +#define XCHAL_TRAX_MEM_SIZE 16384 /* TRAX memory size in bytes */ +#define XCHAL_TRAX_MEM_SHAREABLE 1 /* start/end regs; ready sig. */ +#define XCHAL_TRAX_ATB_WIDTH 32 /* ATB width (bits), 0=no ATB */ +#define XCHAL_TRAX_TIME_WIDTH 0 /* timestamp bitwidth, 0=none */ + +/* Perf counters */ +#define XCHAL_NUM_PERF_COUNTERS 2 /* performance counters */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_SPANNING_WAY 0 /* TLB spanning way number */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ +/* If none of the above last 4 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/target/xtensa/core-esp32/gdb-config.inc.c b/target/xtensa/core-esp32/gdb-config.inc.c new file mode 100644 index 000000000000..cf4d7c94cb02 --- /dev/null +++ b/target/xtensa/core-esp32/gdb-config.inc.c @@ -0,0 +1,290 @@ +/* Configuration for the Xtensa architecture for GDB, the GNU debugger. + + Copyright (c) 2003-2016 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + XTREG( 0, 0,32, 4, 4,0x0020,0x0006,-2, 9,0x0100,pc, 0,0,0,0,0,0) + XTREG( 1, 4,32, 4, 4,0x0100,0x0006,-2, 1,0x0002,ar0, 0,0,0,0,0,0) + XTREG( 2, 8,32, 4, 4,0x0101,0x0006,-2, 1,0x0002,ar1, 0,0,0,0,0,0) + XTREG( 3, 12,32, 4, 4,0x0102,0x0006,-2, 1,0x0002,ar2, 0,0,0,0,0,0) + XTREG( 4, 16,32, 4, 4,0x0103,0x0006,-2, 1,0x0002,ar3, 0,0,0,0,0,0) + XTREG( 5, 20,32, 4, 4,0x0104,0x0006,-2, 1,0x0002,ar4, 0,0,0,0,0,0) + XTREG( 6, 24,32, 4, 4,0x0105,0x0006,-2, 1,0x0002,ar5, 0,0,0,0,0,0) + XTREG( 7, 28,32, 4, 4,0x0106,0x0006,-2, 1,0x0002,ar6, 0,0,0,0,0,0) + XTREG( 8, 32,32, 4, 4,0x0107,0x0006,-2, 1,0x0002,ar7, 0,0,0,0,0,0) + XTREG( 9, 36,32, 4, 4,0x0108,0x0006,-2, 1,0x0002,ar8, 0,0,0,0,0,0) + XTREG( 10, 40,32, 4, 4,0x0109,0x0006,-2, 1,0x0002,ar9, 0,0,0,0,0,0) + XTREG( 11, 44,32, 4, 4,0x010a,0x0006,-2, 1,0x0002,ar10, 0,0,0,0,0,0) + XTREG( 12, 48,32, 4, 4,0x010b,0x0006,-2, 1,0x0002,ar11, 0,0,0,0,0,0) + XTREG( 13, 52,32, 4, 4,0x010c,0x0006,-2, 1,0x0002,ar12, 0,0,0,0,0,0) + XTREG( 14, 56,32, 4, 4,0x010d,0x0006,-2, 1,0x0002,ar13, 0,0,0,0,0,0) + XTREG( 15, 60,32, 4, 4,0x010e,0x0006,-2, 1,0x0002,ar14, 0,0,0,0,0,0) + XTREG( 16, 64,32, 4, 4,0x010f,0x0006,-2, 1,0x0002,ar15, 0,0,0,0,0,0) + XTREG( 17, 68,32, 4, 4,0x0110,0x0006,-2, 1,0x0002,ar16, 0,0,0,0,0,0) + XTREG( 18, 72,32, 4, 4,0x0111,0x0006,-2, 1,0x0002,ar17, 0,0,0,0,0,0) + XTREG( 19, 76,32, 4, 4,0x0112,0x0006,-2, 1,0x0002,ar18, 0,0,0,0,0,0) + XTREG( 20, 80,32, 4, 4,0x0113,0x0006,-2, 1,0x0002,ar19, 0,0,0,0,0,0) + XTREG( 21, 84,32, 4, 4,0x0114,0x0006,-2, 1,0x0002,ar20, 0,0,0,0,0,0) + XTREG( 22, 88,32, 4, 4,0x0115,0x0006,-2, 1,0x0002,ar21, 0,0,0,0,0,0) + XTREG( 23, 92,32, 4, 4,0x0116,0x0006,-2, 1,0x0002,ar22, 0,0,0,0,0,0) + XTREG( 24, 96,32, 4, 4,0x0117,0x0006,-2, 1,0x0002,ar23, 0,0,0,0,0,0) + XTREG( 25,100,32, 4, 4,0x0118,0x0006,-2, 1,0x0002,ar24, 0,0,0,0,0,0) + XTREG( 26,104,32, 4, 4,0x0119,0x0006,-2, 1,0x0002,ar25, 0,0,0,0,0,0) + XTREG( 27,108,32, 4, 4,0x011a,0x0006,-2, 1,0x0002,ar26, 0,0,0,0,0,0) + XTREG( 28,112,32, 4, 4,0x011b,0x0006,-2, 1,0x0002,ar27, 0,0,0,0,0,0) + XTREG( 29,116,32, 4, 4,0x011c,0x0006,-2, 1,0x0002,ar28, 0,0,0,0,0,0) + XTREG( 30,120,32, 4, 4,0x011d,0x0006,-2, 1,0x0002,ar29, 0,0,0,0,0,0) + XTREG( 31,124,32, 4, 4,0x011e,0x0006,-2, 1,0x0002,ar30, 0,0,0,0,0,0) + XTREG( 32,128,32, 4, 4,0x011f,0x0006,-2, 1,0x0002,ar31, 0,0,0,0,0,0) + XTREG( 33,132,32, 4, 4,0x0120,0x0006,-2, 1,0x0002,ar32, 0,0,0,0,0,0) + XTREG( 34,136,32, 4, 4,0x0121,0x0006,-2, 1,0x0002,ar33, 0,0,0,0,0,0) + XTREG( 35,140,32, 4, 4,0x0122,0x0006,-2, 1,0x0002,ar34, 0,0,0,0,0,0) + XTREG( 36,144,32, 4, 4,0x0123,0x0006,-2, 1,0x0002,ar35, 0,0,0,0,0,0) + XTREG( 37,148,32, 4, 4,0x0124,0x0006,-2, 1,0x0002,ar36, 0,0,0,0,0,0) + XTREG( 38,152,32, 4, 4,0x0125,0x0006,-2, 1,0x0002,ar37, 0,0,0,0,0,0) + XTREG( 39,156,32, 4, 4,0x0126,0x0006,-2, 1,0x0002,ar38, 0,0,0,0,0,0) + XTREG( 40,160,32, 4, 4,0x0127,0x0006,-2, 1,0x0002,ar39, 0,0,0,0,0,0) + XTREG( 41,164,32, 4, 4,0x0128,0x0006,-2, 1,0x0002,ar40, 0,0,0,0,0,0) + XTREG( 42,168,32, 4, 4,0x0129,0x0006,-2, 1,0x0002,ar41, 0,0,0,0,0,0) + XTREG( 43,172,32, 4, 4,0x012a,0x0006,-2, 1,0x0002,ar42, 0,0,0,0,0,0) + XTREG( 44,176,32, 4, 4,0x012b,0x0006,-2, 1,0x0002,ar43, 0,0,0,0,0,0) + XTREG( 45,180,32, 4, 4,0x012c,0x0006,-2, 1,0x0002,ar44, 0,0,0,0,0,0) + XTREG( 46,184,32, 4, 4,0x012d,0x0006,-2, 1,0x0002,ar45, 0,0,0,0,0,0) + XTREG( 47,188,32, 4, 4,0x012e,0x0006,-2, 1,0x0002,ar46, 0,0,0,0,0,0) + XTREG( 48,192,32, 4, 4,0x012f,0x0006,-2, 1,0x0002,ar47, 0,0,0,0,0,0) + XTREG( 49,196,32, 4, 4,0x0130,0x0006,-2, 1,0x0002,ar48, 0,0,0,0,0,0) + XTREG( 50,200,32, 4, 4,0x0131,0x0006,-2, 1,0x0002,ar49, 0,0,0,0,0,0) + XTREG( 51,204,32, 4, 4,0x0132,0x0006,-2, 1,0x0002,ar50, 0,0,0,0,0,0) + XTREG( 52,208,32, 4, 4,0x0133,0x0006,-2, 1,0x0002,ar51, 0,0,0,0,0,0) + XTREG( 53,212,32, 4, 4,0x0134,0x0006,-2, 1,0x0002,ar52, 0,0,0,0,0,0) + XTREG( 54,216,32, 4, 4,0x0135,0x0006,-2, 1,0x0002,ar53, 0,0,0,0,0,0) + XTREG( 55,220,32, 4, 4,0x0136,0x0006,-2, 1,0x0002,ar54, 0,0,0,0,0,0) + XTREG( 56,224,32, 4, 4,0x0137,0x0006,-2, 1,0x0002,ar55, 0,0,0,0,0,0) + XTREG( 57,228,32, 4, 4,0x0138,0x0006,-2, 1,0x0002,ar56, 0,0,0,0,0,0) + XTREG( 58,232,32, 4, 4,0x0139,0x0006,-2, 1,0x0002,ar57, 0,0,0,0,0,0) + XTREG( 59,236,32, 4, 4,0x013a,0x0006,-2, 1,0x0002,ar58, 0,0,0,0,0,0) + XTREG( 60,240,32, 4, 4,0x013b,0x0006,-2, 1,0x0002,ar59, 0,0,0,0,0,0) + XTREG( 61,244,32, 4, 4,0x013c,0x0006,-2, 1,0x0002,ar60, 0,0,0,0,0,0) + XTREG( 62,248,32, 4, 4,0x013d,0x0006,-2, 1,0x0002,ar61, 0,0,0,0,0,0) + XTREG( 63,252,32, 4, 4,0x013e,0x0006,-2, 1,0x0002,ar62, 0,0,0,0,0,0) + XTREG( 64,256,32, 4, 4,0x013f,0x0006,-2, 1,0x0002,ar63, 0,0,0,0,0,0) + XTREG( 65,260,32, 4, 4,0x0200,0x0006,-2, 2,0x1100,lbeg, 0,0,0,0,0,0) + XTREG( 66,264,32, 4, 4,0x0201,0x0006,-2, 2,0x1100,lend, 0,0,0,0,0,0) + XTREG( 67,268,32, 4, 4,0x0202,0x0006,-2, 2,0x1100,lcount, 0,0,0,0,0,0) + XTREG( 68,272, 6, 4, 4,0x0203,0x0006,-2, 2,0x1100,sar, 0,0,0,0,0,0) + XTREG( 69,276, 4, 4, 4,0x0248,0x0006,-2, 2,0x1002,windowbase, 0,0,0,0,0,0) + XTREG( 70,280,16, 4, 4,0x0249,0x0006,-2, 2,0x1002,windowstart, 0,0,0,0,0,0) + XTREG( 71,284,32, 4, 4,0x02b0,0x0002,-2, 2,0x1000,configid0, 0,0,0,0,0,0) + XTREG( 72,288,32, 4, 4,0x02d0,0x0002,-2, 2,0x1000,configid1, 0,0,0,0,0,0) + XTREG( 73,292,19, 4, 4,0x02e6,0x0006,-2, 2,0x1100,ps, 0,0,0,0,0,0) + XTREG( 74,296,32, 4, 4,0x03e7,0x0006,-2, 3,0x0110,threadptr, 0,0,0,0,0,0) + XTREG( 75,300,16, 4, 4,0x0204,0x0006,-1, 2,0x1100,br, 0,0,0,0,0,0) + XTREG( 76,304,32, 4, 4,0x020c,0x0006,-1, 2,0x1100,scompare1, 0,0,0,0,0,0) + XTREG( 77,308,32, 4, 4,0x0210,0x0006,-1, 2,0x1100,acclo, 0,0,0,0,0,0) + XTREG( 78,312, 8, 4, 4,0x0211,0x0006,-1, 2,0x1100,acchi, 0,0,0,0,0,0) + XTREG( 79,316,32, 4, 4,0x0220,0x0006,-1, 2,0x1100,m0, 0,0,0,0,0,0) + XTREG( 80,320,32, 4, 4,0x0221,0x0006,-1, 2,0x1100,m1, 0,0,0,0,0,0) + XTREG( 81,324,32, 4, 4,0x0222,0x0006,-1, 2,0x1100,m2, 0,0,0,0,0,0) + XTREG( 82,328,32, 4, 4,0x0223,0x0006,-1, 2,0x1100,m3, 0,0,0,0,0,0) + XTREG( 83,332,32, 4, 4,0x03e6,0x000e,-1, 3,0x0110,expstate, 0,0,0,0,0,0) + XTREG( 84,336,32, 4, 4,0x03ea,0x0006,-1, 3,0x0100,f64r_lo, 0,0,0,0,0,0) + XTREG( 85,340,32, 4, 4,0x03eb,0x0006,-1, 3,0x0100,f64r_hi, 0,0,0,0,0,0) + XTREG( 86,344,32, 4, 4,0x03ec,0x0006,-1, 3,0x0110,f64s, 0,0,0,0,0,0) + XTREG( 87,348,32, 4, 4,0x0030,0x0006, 0, 4,0x0401,f0, + "03:03:44:00","03:03:04:00",0,0,0,0) + XTREG( 88,352,32, 4, 4,0x0031,0x0006, 0, 4,0x0401,f1, + "03:13:44:00","03:13:04:00",0,0,0,0) + XTREG( 89,356,32, 4, 4,0x0032,0x0006, 0, 4,0x0401,f2, + "03:23:44:00","03:23:04:00",0,0,0,0) + XTREG( 90,360,32, 4, 4,0x0033,0x0006, 0, 4,0x0401,f3, + "03:33:44:00","03:33:04:00",0,0,0,0) + XTREG( 91,364,32, 4, 4,0x0034,0x0006, 0, 4,0x0401,f4, + "03:43:44:00","03:43:04:00",0,0,0,0) + XTREG( 92,368,32, 4, 4,0x0035,0x0006, 0, 4,0x0401,f5, + "03:53:44:00","03:53:04:00",0,0,0,0) + XTREG( 93,372,32, 4, 4,0x0036,0x0006, 0, 4,0x0401,f6, + "03:63:44:00","03:63:04:00",0,0,0,0) + XTREG( 94,376,32, 4, 4,0x0037,0x0006, 0, 4,0x0401,f7, + "03:73:44:00","03:73:04:00",0,0,0,0) + XTREG( 95,380,32, 4, 4,0x0038,0x0006, 0, 4,0x0401,f8, + "03:83:44:00","03:83:04:00",0,0,0,0) + XTREG( 96,384,32, 4, 4,0x0039,0x0006, 0, 4,0x0401,f9, + "03:93:44:00","03:93:04:00",0,0,0,0) + XTREG( 97,388,32, 4, 4,0x003a,0x0006, 0, 4,0x0401,f10, + "03:a3:44:00","03:a3:04:00",0,0,0,0) + XTREG( 98,392,32, 4, 4,0x003b,0x0006, 0, 4,0x0401,f11, + "03:b3:44:00","03:b3:04:00",0,0,0,0) + XTREG( 99,396,32, 4, 4,0x003c,0x0006, 0, 4,0x0401,f12, + "03:c3:44:00","03:c3:04:00",0,0,0,0) + XTREG(100,400,32, 4, 4,0x003d,0x0006, 0, 4,0x0401,f13, + "03:d3:44:00","03:d3:04:00",0,0,0,0) + XTREG(101,404,32, 4, 4,0x003e,0x0006, 0, 4,0x0401,f14, + "03:e3:44:00","03:e3:04:00",0,0,0,0) + XTREG(102,408,32, 4, 4,0x003f,0x0006, 0, 4,0x0401,f15, + "03:f3:44:00","03:f3:04:00",0,0,0,0) + XTREG(103,412,32, 4, 4,0x03e8,0x0006, 0, 3,0x0100,fcr, 0,0,0,0,0,0) + XTREG(104,416,32, 4, 4,0x03e9,0x0006, 0, 3,0x0100,fsr, 0,0,0,0,0,0) + XTREG(105,420,32, 4, 4,0x0259,0x000d,-2, 2,0x1000,mmid, 0,0,0,0,0,0) + XTREG(106,424, 2, 4, 4,0x0260,0x0007,-2, 2,0x1000,ibreakenable,0,0,0,0,0,0) + XTREG(107,428, 1, 4, 4,0x0261,0x0007,-2, 2,0x1000,memctl, 0,0,0,0,0,0) + XTREG(108,432, 6, 4, 4,0x0263,0x0007,-2, 2,0x1000,atomctl, 0,0,0,0,0,0) + XTREG(109,436,32, 4, 4,0x0268,0x0007,-2, 2,0x1000,ddr, 0,0,0,0,0,0) + XTREG(110,440,32, 4, 4,0x0280,0x0007,-2, 2,0x1000,ibreaka0, 0,0,0,0,0,0) + XTREG(111,444,32, 4, 4,0x0281,0x0007,-2, 2,0x1000,ibreaka1, 0,0,0,0,0,0) + XTREG(112,448,32, 4, 4,0x0290,0x0007,-2, 2,0x1000,dbreaka0, 0,0,0,0,0,0) + XTREG(113,452,32, 4, 4,0x0291,0x0007,-2, 2,0x1000,dbreaka1, 0,0,0,0,0,0) + XTREG(114,456,32, 4, 4,0x02a0,0x0007,-2, 2,0x1000,dbreakc0, 0,0,0,0,0,0) + XTREG(115,460,32, 4, 4,0x02a1,0x0007,-2, 2,0x1000,dbreakc1, 0,0,0,0,0,0) + XTREG(116,464,32, 4, 4,0x02b1,0x0007,-2, 2,0x1000,epc1, 0,0,0,0,0,0) + XTREG(117,468,32, 4, 4,0x02b2,0x0007,-2, 2,0x1000,epc2, 0,0,0,0,0,0) + XTREG(118,472,32, 4, 4,0x02b3,0x0007,-2, 2,0x1000,epc3, 0,0,0,0,0,0) + XTREG(119,476,32, 4, 4,0x02b4,0x0007,-2, 2,0x1000,epc4, 0,0,0,0,0,0) + XTREG(120,480,32, 4, 4,0x02b5,0x0007,-2, 2,0x1000,epc5, 0,0,0,0,0,0) + XTREG(121,484,32, 4, 4,0x02b6,0x0007,-2, 2,0x1000,epc6, 0,0,0,0,0,0) + XTREG(122,488,32, 4, 4,0x02b7,0x0007,-2, 2,0x1000,epc7, 0,0,0,0,0,0) + XTREG(123,492,32, 4, 4,0x02c0,0x0007,-2, 2,0x1000,depc, 0,0,0,0,0,0) + XTREG(124,496,19, 4, 4,0x02c2,0x0007,-2, 2,0x1000,eps2, 0,0,0,0,0,0) + XTREG(125,500,19, 4, 4,0x02c3,0x0007,-2, 2,0x1000,eps3, 0,0,0,0,0,0) + XTREG(126,504,19, 4, 4,0x02c4,0x0007,-2, 2,0x1000,eps4, 0,0,0,0,0,0) + XTREG(127,508,19, 4, 4,0x02c5,0x0007,-2, 2,0x1000,eps5, 0,0,0,0,0,0) + XTREG(128,512,19, 4, 4,0x02c6,0x0007,-2, 2,0x1000,eps6, 0,0,0,0,0,0) + XTREG(129,516,19, 4, 4,0x02c7,0x0007,-2, 2,0x1000,eps7, 0,0,0,0,0,0) + XTREG(130,520,32, 4, 4,0x02d1,0x0007,-2, 2,0x1000,excsave1, 0,0,0,0,0,0) + XTREG(131,524,32, 4, 4,0x02d2,0x0007,-2, 2,0x1000,excsave2, 0,0,0,0,0,0) + XTREG(132,528,32, 4, 4,0x02d3,0x0007,-2, 2,0x1000,excsave3, 0,0,0,0,0,0) + XTREG(133,532,32, 4, 4,0x02d4,0x0007,-2, 2,0x1000,excsave4, 0,0,0,0,0,0) + XTREG(134,536,32, 4, 4,0x02d5,0x0007,-2, 2,0x1000,excsave5, 0,0,0,0,0,0) + XTREG(135,540,32, 4, 4,0x02d6,0x0007,-2, 2,0x1000,excsave6, 0,0,0,0,0,0) + XTREG(136,544,32, 4, 4,0x02d7,0x0007,-2, 2,0x1000,excsave7, 0,0,0,0,0,0) + XTREG(137,548, 8, 4, 4,0x02e0,0x0007,-2, 2,0x1000,cpenable, 0,0,0,0,0,0) + XTREG(138,552,32, 4, 4,0x02e2,0x000b,-2, 2,0x1000,interrupt, 0,0,0,0,0,0) + XTREG(139,556,32, 4, 4,0x02e2,0x000d,-2, 2,0x1000,intset, 0,0,0,0,0,0) + XTREG(140,560,32, 4, 4,0x02e3,0x000d,-2, 2,0x1000,intclear, 0,0,0,0,0,0) + XTREG(141,564,32, 4, 4,0x02e4,0x0007,-2, 2,0x1000,intenable, 0,0,0,0,0,0) + XTREG(142,568,32, 4, 4,0x02e7,0x0007,-2, 2,0x1000,vecbase, 0,0,0,0,0,0) + XTREG(143,572, 6, 4, 4,0x02e8,0x0007,-2, 2,0x1000,exccause, 0,0,0,0,0,0) + XTREG(144,576,12, 4, 4,0x02e9,0x0003,-2, 2,0x1000,debugcause, 0,0,0,0,0,0) + XTREG(145,580,32, 4, 4,0x02ea,0x000f,-2, 2,0x1000,ccount, 0,0,0,0,0,0) + XTREG(146,584,32, 4, 4,0x02eb,0x0003,-2, 2,0x1000,prid, 0,0,0,0,0,0) + XTREG(147,588,32, 4, 4,0x02ec,0x000f,-2, 2,0x1000,icount, 0,0,0,0,0,0) + XTREG(148,592, 4, 4, 4,0x02ed,0x0007,-2, 2,0x1000,icountlevel, 0,0,0,0,0,0) + XTREG(149,596,32, 4, 4,0x02ee,0x0007,-2, 2,0x1000,excvaddr, 0,0,0,0,0,0) + XTREG(150,600,32, 4, 4,0x02f0,0x000f,-2, 2,0x1000,ccompare0, 0,0,0,0,0,0) + XTREG(151,604,32, 4, 4,0x02f1,0x000f,-2, 2,0x1000,ccompare1, 0,0,0,0,0,0) + XTREG(152,608,32, 4, 4,0x02f2,0x000f,-2, 2,0x1000,ccompare2, 0,0,0,0,0,0) + XTREG(153,612,32, 4, 4,0x02f4,0x0007,-2, 2,0x1000,misc0, 0,0,0,0,0,0) + XTREG(154,616,32, 4, 4,0x02f5,0x0007,-2, 2,0x1000,misc1, 0,0,0,0,0,0) + XTREG(155,620,32, 4, 4,0x02f6,0x0007,-2, 2,0x1000,misc2, 0,0,0,0,0,0) + XTREG(156,624,32, 4, 4,0x02f7,0x0007,-2, 2,0x1000,misc3, 0,0,0,0,0,0) + XTREG(157,628,32, 4, 4,0x0000,0x0006,-2, 8,0x0100,a0, 0,0,0,0,0,0) + XTREG(158,632,32, 4, 4,0x0001,0x0006,-2, 8,0x0100,a1, 0,0,0,0,0,0) + XTREG(159,636,32, 4, 4,0x0002,0x0006,-2, 8,0x0100,a2, 0,0,0,0,0,0) + XTREG(160,640,32, 4, 4,0x0003,0x0006,-2, 8,0x0100,a3, 0,0,0,0,0,0) + XTREG(161,644,32, 4, 4,0x0004,0x0006,-2, 8,0x0100,a4, 0,0,0,0,0,0) + XTREG(162,648,32, 4, 4,0x0005,0x0006,-2, 8,0x0100,a5, 0,0,0,0,0,0) + XTREG(163,652,32, 4, 4,0x0006,0x0006,-2, 8,0x0100,a6, 0,0,0,0,0,0) + XTREG(164,656,32, 4, 4,0x0007,0x0006,-2, 8,0x0100,a7, 0,0,0,0,0,0) + XTREG(165,660,32, 4, 4,0x0008,0x0006,-2, 8,0x0100,a8, 0,0,0,0,0,0) + XTREG(166,664,32, 4, 4,0x0009,0x0006,-2, 8,0x0100,a9, 0,0,0,0,0,0) + XTREG(167,668,32, 4, 4,0x000a,0x0006,-2, 8,0x0100,a10, 0,0,0,0,0,0) + XTREG(168,672,32, 4, 4,0x000b,0x0006,-2, 8,0x0100,a11, 0,0,0,0,0,0) + XTREG(169,676,32, 4, 4,0x000c,0x0006,-2, 8,0x0100,a12, 0,0,0,0,0,0) + XTREG(170,680,32, 4, 4,0x000d,0x0006,-2, 8,0x0100,a13, 0,0,0,0,0,0) + XTREG(171,684,32, 4, 4,0x000e,0x0006,-2, 8,0x0100,a14, 0,0,0,0,0,0) + XTREG(172,688,32, 4, 4,0x000f,0x0006,-2, 8,0x0100,a15, 0,0,0,0,0,0) + XTREG(173,692, 1, 1, 1,0x0010,0x0006,-2, 6,0x1010,b0, + 0,0,&xtensa_mask0,0,0,0) + XTREG(174,693, 1, 1, 1,0x0011,0x0006,-2, 6,0x1010,b1, + 0,0,&xtensa_mask1,0,0,0) + XTREG(175,694, 1, 1, 1,0x0012,0x0006,-2, 6,0x1010,b2, + 0,0,&xtensa_mask2,0,0,0) + XTREG(176,695, 1, 1, 1,0x0013,0x0006,-2, 6,0x1010,b3, + 0,0,&xtensa_mask3,0,0,0) + XTREG(177,696, 1, 1, 1,0x0014,0x0006,-2, 6,0x1010,b4, + 0,0,&xtensa_mask4,0,0,0) + XTREG(178,697, 1, 1, 1,0x0015,0x0006,-2, 6,0x1010,b5, + 0,0,&xtensa_mask5,0,0,0) + XTREG(179,698, 1, 1, 1,0x0016,0x0006,-2, 6,0x1010,b6, + 0,0,&xtensa_mask6,0,0,0) + XTREG(180,699, 1, 1, 1,0x0017,0x0006,-2, 6,0x1010,b7, + 0,0,&xtensa_mask7,0,0,0) + XTREG(181,700, 1, 1, 1,0x0018,0x0006,-2, 6,0x1010,b8, + 0,0,&xtensa_mask8,0,0,0) + XTREG(182,701, 1, 1, 1,0x0019,0x0006,-2, 6,0x1010,b9, + 0,0,&xtensa_mask9,0,0,0) + XTREG(183,702, 1, 1, 1,0x001a,0x0006,-2, 6,0x1010,b10, + 0,0,&xtensa_mask10,0,0,0) + XTREG(184,703, 1, 1, 1,0x001b,0x0006,-2, 6,0x1010,b11, + 0,0,&xtensa_mask11,0,0,0) + XTREG(185,704, 1, 1, 1,0x001c,0x0006,-2, 6,0x1010,b12, + 0,0,&xtensa_mask12,0,0,0) + XTREG(186,705, 1, 1, 1,0x001d,0x0006,-2, 6,0x1010,b13, + 0,0,&xtensa_mask13,0,0,0) + XTREG(187,706, 1, 1, 1,0x001e,0x0006,-2, 6,0x1010,b14, + 0,0,&xtensa_mask14,0,0,0) + XTREG(188,707, 1, 1, 1,0x001f,0x0006,-2, 6,0x1010,b15, + 0,0,&xtensa_mask15,0,0,0) + XTREG(189,708, 4, 4, 4,0x2008,0x0006,-2, 6,0x1010,psintlevel, + 0,0,&xtensa_mask16,0,0,0) + XTREG(190,712, 1, 4, 4,0x2009,0x0006,-2, 6,0x1010,psum, + 0,0,&xtensa_mask17,0,0,0) + XTREG(191,716, 1, 4, 4,0x200a,0x0006,-2, 6,0x1010,pswoe, + 0,0,&xtensa_mask18,0,0,0) + XTREG(192,720, 1, 4, 4,0x200b,0x0006,-2, 6,0x1010,psexcm, + 0,0,&xtensa_mask19,0,0,0) + XTREG(193,724, 2, 4, 4,0x200c,0x0006,-2, 6,0x1010,pscallinc, + 0,0,&xtensa_mask20,0,0,0) + XTREG(194,728, 4, 4, 4,0x200d,0x0006,-2, 6,0x1010,psowb, + 0,0,&xtensa_mask21,0,0,0) + XTREG(195,732,40, 8, 4,0x200e,0x0006,-2, 6,0x1010,acc, + 0,0,&xtensa_mask22,0,0,0) + XTREG(196,740, 4, 4, 4,0x2013,0x0006,-2, 6,0x1010,dbnum, + 0,0,&xtensa_mask23,0,0,0) + XTREG(197,744,64, 8, 4,0x2015,0x0006,-2, 5,0x1010,f64r, + 0,0,&xtensa_mask24,0,0,0) + XTREG(198,752, 2, 4, 4,0x2016,0x0006, 0, 5,0x1010,roundmode, + 0,0,&xtensa_mask25,0,0,0) + XTREG(199,756, 1, 4, 4,0x2017,0x0006, 0, 5,0x1010,invalidenable, + 0,0,&xtensa_mask26,0,0,0) + XTREG(200,760, 1, 4, 4,0x2018,0x0006, 0, 5,0x1010,divzeroenable, + 0,0,&xtensa_mask27,0,0,0) + XTREG(201,764, 1, 4, 4,0x2019,0x0006, 0, 5,0x1010,overflowenable, + 0,0,&xtensa_mask28,0,0,0) + XTREG(202,768, 1, 4, 4,0x201a,0x0006, 0, 5,0x1010,underflowenable, + 0,0,&xtensa_mask29,0,0,0) + XTREG(203,772, 1, 4, 4,0x201b,0x0006, 0, 5,0x1010,inexactenable, + 0,0,&xtensa_mask30,0,0,0) + XTREG(204,776, 1, 4, 4,0x201c,0x0006, 0, 5,0x1010,invalidflag, + 0,0,&xtensa_mask31,0,0,0) + XTREG(205,780, 1, 4, 4,0x201d,0x0006, 0, 5,0x1010,divzeroflag, + 0,0,&xtensa_mask32,0,0,0) + XTREG(206,784, 1, 4, 4,0x201e,0x0006, 0, 5,0x1010,overflowflag, + 0,0,&xtensa_mask33,0,0,0) + XTREG(207,788, 1, 4, 4,0x201f,0x0006, 0, 5,0x1010,underflowflag, + 0,0,&xtensa_mask34,0,0,0) + XTREG(208,792, 1, 4, 4,0x2020,0x0006, 0, 5,0x1010,inexactflag, + 0,0,&xtensa_mask35,0,0,0) + XTREG(209,796,20, 4, 4,0x2021,0x0006, 0, 5,0x1010,fpreserved20, + 0,0,&xtensa_mask36,0,0,0) + XTREG(210,800,20, 4, 4,0x2022,0x0006, 0, 5,0x1010,fpreserved20a, + 0,0,&xtensa_mask37,0,0,0) + XTREG(211,804, 5, 4, 4,0x2023,0x0006, 0, 5,0x1010,fpreserved5, + 0,0,&xtensa_mask38,0,0,0) + XTREG_END diff --git a/target/xtensa/core-esp32/xtensa-modules.inc.c b/target/xtensa/core-esp32/xtensa-modules.inc.c new file mode 100644 index 000000000000..1b9d1b905589 --- /dev/null +++ b/target/xtensa/core-esp32/xtensa-modules.inc.c @@ -0,0 +1,19196 @@ +/* Xtensa configuration-specific ISA information. + + Copyright (c) 2003-2016 Tensilica Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "xtensa-isa.h" +#include "xtensa-isa-internal.h" + + +/* Sysregs. */ + +static xtensa_sysreg_internal sysregs[] = { + { "LBEG", 0, 0 }, + { "LEND", 1, 0 }, + { "LCOUNT", 2, 0 }, + { "BR", 4, 0 }, + { "ACCLO", 16, 0 }, + { "ACCHI", 17, 0 }, + { "M0", 32, 0 }, + { "M1", 33, 0 }, + { "M2", 34, 0 }, + { "M3", 35, 0 }, + { "MMID", 89, 0 }, + { "DDR", 104, 0 }, + { "CONFIGID0", 176, 0 }, + { "CONFIGID1", 208, 0 }, + { "INTERRUPT", 226, 0 }, + { "INTCLEAR", 227, 0 }, + { "CCOUNT", 234, 0 }, + { "PRID", 235, 0 }, + { "ICOUNT", 236, 0 }, + { "CCOMPARE0", 240, 0 }, + { "CCOMPARE1", 241, 0 }, + { "CCOMPARE2", 242, 0 }, + { "VECBASE", 231, 0 }, + { "EPC1", 177, 0 }, + { "EPC2", 178, 0 }, + { "EPC3", 179, 0 }, + { "EPC4", 180, 0 }, + { "EPC5", 181, 0 }, + { "EPC6", 182, 0 }, + { "EPC7", 183, 0 }, + { "EXCSAVE1", 209, 0 }, + { "EXCSAVE2", 210, 0 }, + { "EXCSAVE3", 211, 0 }, + { "EXCSAVE4", 212, 0 }, + { "EXCSAVE5", 213, 0 }, + { "EXCSAVE6", 214, 0 }, + { "EXCSAVE7", 215, 0 }, + { "EPS2", 194, 0 }, + { "EPS3", 195, 0 }, + { "EPS4", 196, 0 }, + { "EPS5", 197, 0 }, + { "EPS6", 198, 0 }, + { "EPS7", 199, 0 }, + { "EXCCAUSE", 232, 0 }, + { "DEPC", 192, 0 }, + { "EXCVADDR", 238, 0 }, + { "WINDOWBASE", 72, 0 }, + { "WINDOWSTART", 73, 0 }, + { "MEMCTL", 97, 0 }, + { "SAR", 3, 0 }, + { "PS", 230, 0 }, + { "MISC0", 244, 0 }, + { "MISC1", 245, 0 }, + { "MISC2", 246, 0 }, + { "MISC3", 247, 0 }, + { "INTENABLE", 228, 0 }, + { "DBREAKA0", 144, 0 }, + { "DBREAKC0", 160, 0 }, + { "DBREAKA1", 145, 0 }, + { "DBREAKC1", 161, 0 }, + { "IBREAKA0", 128, 0 }, + { "IBREAKA1", 129, 0 }, + { "IBREAKENABLE", 96, 0 }, + { "ICOUNTLEVEL", 237, 0 }, + { "DEBUGCAUSE", 233, 0 }, + { "CPENABLE", 224, 0 }, + { "SCOMPARE1", 12, 0 }, + { "ATOMCTL", 99, 0 }, + { "THREADPTR", 231, 1 }, + { "F64R_LO", 234, 1 }, + { "F64R_HI", 235, 1 }, + { "F64S", 236, 1 }, + { "FCR", 232, 1 }, + { "FSR", 233, 1 }, + { "EXPSTATE", 230, 1 } +}; + +#define NUM_SYSREGS 75 +#define MAX_SPECIAL_REG 247 +#define MAX_USER_REG 236 + + +/* Processor states. */ + +static xtensa_state_internal states[] = { + { "LCOUNT", 32, 0 }, + { "PC", 32, 0 }, + { "ICOUNT", 32, 0 }, + { "DDR", 32, 0 }, + { "INTERRUPT", 32, 0 }, + { "CCOUNT", 32, 0 }, + { "XTSYNC", 1, 0 }, + { "VECBASE", 22, 0 }, + { "EPC1", 32, 0 }, + { "EPC2", 32, 0 }, + { "EPC3", 32, 0 }, + { "EPC4", 32, 0 }, + { "EPC5", 32, 0 }, + { "EPC6", 32, 0 }, + { "EPC7", 32, 0 }, + { "EXCSAVE1", 32, 0 }, + { "EXCSAVE2", 32, 0 }, + { "EXCSAVE3", 32, 0 }, + { "EXCSAVE4", 32, 0 }, + { "EXCSAVE5", 32, 0 }, + { "EXCSAVE6", 32, 0 }, + { "EXCSAVE7", 32, 0 }, + { "EPS2", 13, 0 }, + { "EPS3", 13, 0 }, + { "EPS4", 13, 0 }, + { "EPS5", 13, 0 }, + { "EPS6", 13, 0 }, + { "EPS7", 13, 0 }, + { "EXCCAUSE", 6, 0 }, + { "PSINTLEVEL", 4, 0 }, + { "PSUM", 1, 0 }, + { "PSWOE", 1, 0 }, + { "PSEXCM", 1, 0 }, + { "DEPC", 32, 0 }, + { "EXCVADDR", 32, 0 }, + { "WindowBase", 4, 0 }, + { "WindowStart", 16, 0 }, + { "PSCALLINC", 2, 0 }, + { "PSOWB", 4, 0 }, + { "LBEG", 32, 0 }, + { "LEND", 32, 0 }, + { "MEMCTL", 1, 0 }, + { "SAR", 6, 0 }, + { "THREADPTR", 32, 0 }, + { "MISC0", 32, 0 }, + { "MISC1", 32, 0 }, + { "MISC2", 32, 0 }, + { "MISC3", 32, 0 }, + { "ACC", 40, 0 }, + { "InOCDMode", 1, 0 }, + { "INTENABLE", 32, 0 }, + { "DBREAKA0", 32, 0 }, + { "DBREAKC0", 8, 0 }, + { "DBREAKA1", 32, 0 }, + { "DBREAKC1", 8, 0 }, + { "IBREAKA0", 32, 0 }, + { "IBREAKA1", 32, 0 }, + { "IBREAKENABLE", 2, 0 }, + { "ICOUNTLEVEL", 4, 0 }, + { "DEBUGCAUSE", 6, 0 }, + { "DBNUM", 4, 0 }, + { "CCOMPARE0", 32, 0 }, + { "CCOMPARE1", 32, 0 }, + { "CCOMPARE2", 32, 0 }, + { "CPENABLE", 8, 0 }, + { "SCOMPARE1", 32, 0 }, + { "ATOMCTL", 6, 0 }, + { "ERI_RAW_INTERLOCK", 1, 0 }, + { "F64R", 64, 0 }, + { "F64S", 32, 0 }, + { "RoundMode", 2, 0 }, + { "InvalidEnable", 1, 0 }, + { "DivZeroEnable", 1, 0 }, + { "OverflowEnable", 1, 0 }, + { "UnderflowEnable", 1, 0 }, + { "InexactEnable", 1, 0 }, + { "InvalidFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "DivZeroFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "OverflowFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "UnderflowFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "InexactFlag", 1, XTENSA_STATE_IS_SHARED_OR }, + { "FPreserved20", 20, 0 }, + { "FPreserved20a", 20, 0 }, + { "FPreserved5", 5, 0 }, + { "FPreserved7", 7, 0 }, + { "EXPSTATE", 32, XTENSA_STATE_IS_EXPORTED } +}; + +#define NUM_STATES 86 + +enum xtensa_state_id { + STATE_LCOUNT, + STATE_PC, + STATE_ICOUNT, + STATE_DDR, + STATE_INTERRUPT, + STATE_CCOUNT, + STATE_XTSYNC, + STATE_VECBASE, + STATE_EPC1, + STATE_EPC2, + STATE_EPC3, + STATE_EPC4, + STATE_EPC5, + STATE_EPC6, + STATE_EPC7, + STATE_EXCSAVE1, + STATE_EXCSAVE2, + STATE_EXCSAVE3, + STATE_EXCSAVE4, + STATE_EXCSAVE5, + STATE_EXCSAVE6, + STATE_EXCSAVE7, + STATE_EPS2, + STATE_EPS3, + STATE_EPS4, + STATE_EPS5, + STATE_EPS6, + STATE_EPS7, + STATE_EXCCAUSE, + STATE_PSINTLEVEL, + STATE_PSUM, + STATE_PSWOE, + STATE_PSEXCM, + STATE_DEPC, + STATE_EXCVADDR, + STATE_WindowBase, + STATE_WindowStart, + STATE_PSCALLINC, + STATE_PSOWB, + STATE_LBEG, + STATE_LEND, + STATE_MEMCTL, + STATE_SAR, + STATE_THREADPTR, + STATE_MISC0, + STATE_MISC1, + STATE_MISC2, + STATE_MISC3, + STATE_ACC, + STATE_InOCDMode, + STATE_INTENABLE, + STATE_DBREAKA0, + STATE_DBREAKC0, + STATE_DBREAKA1, + STATE_DBREAKC1, + STATE_IBREAKA0, + STATE_IBREAKA1, + STATE_IBREAKENABLE, + STATE_ICOUNTLEVEL, + STATE_DEBUGCAUSE, + STATE_DBNUM, + STATE_CCOMPARE0, + STATE_CCOMPARE1, + STATE_CCOMPARE2, + STATE_CPENABLE, + STATE_SCOMPARE1, + STATE_ATOMCTL, + STATE_ERI_RAW_INTERLOCK, + STATE_F64R, + STATE_F64S, + STATE_RoundMode, + STATE_InvalidEnable, + STATE_DivZeroEnable, + STATE_OverflowEnable, + STATE_UnderflowEnable, + STATE_InexactEnable, + STATE_InvalidFlag, + STATE_DivZeroFlag, + STATE_OverflowFlag, + STATE_UnderflowFlag, + STATE_InexactFlag, + STATE_FPreserved20, + STATE_FPreserved20a, + STATE_FPreserved5, + STATE_FPreserved7, + STATE_EXPSTATE +}; + + +/* Field definitions. */ + +static unsigned +Field_r_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_op0_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_op2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + return tie_t; +} + +static void +Field_op2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_op1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_op1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_t_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_s_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_n_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_n_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_m_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_m_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_sr_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sr_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_st_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_st_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_thi3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_thi3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_t3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_tlo_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_tlo_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_w_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 18) >> 30); + return tie_t; +} + +static void +Field_w_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x3000) | (tie_t << 12); +} + +static unsigned +Field_r3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_rhi_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_rhi_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_dfp_fld_op2_3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 8) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_op2_3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800000) | (tie_t << 23); +} + +static unsigned +Field_dfp_fld_op1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 12) >> 28); + return tie_t; +} + +static void +Field_dfp_fld_op1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0000) | (tie_t << 16); +} + +static unsigned +Field_dfp_fld_op2_3_2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 8) >> 30); + return tie_t; +} + +static void +Field_dfp_fld_op2_3_2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00000) | (tie_t << 22); +} + +static unsigned +Field_dfp_fld_r_3_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_r_3_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dfp_fld_op2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 8) >> 28); + return tie_t; +} + +static void +Field_dfp_fld_op2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00000) | (tie_t << 20); +} + +static unsigned +Field_dfp_fld_op2_3_1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 8) >> 29); + return tie_t; +} + +static void +Field_dfp_fld_op2_3_1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00000) | (tie_t << 21); +} + +static unsigned +Field_dfp_fld_s_3_1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dfp_fld_s_3_1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_dfp_fld_r_3_1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_dfp_fld_r_3_1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_s3to1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s3to1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_op0_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_t_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_r_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_op0_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 28) >> 28); + return tie_t; +} + +static void +Field_op0_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf) | (tie_t << 0); +} + +static unsigned +Field_z_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_z_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_i_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_i_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_s_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_t_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_t_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); +} + +static unsigned +Field_bbi4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_bbi4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_bbi_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_bbi_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_imm12_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 12) | ((insn[0] << 8) >> 20); + return tie_t; +} + +static void +Field_imm12_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 20) >> 20; + insn[0] = (insn[0] & ~0xfff000) | (tie_t << 12); +} + +static unsigned +Field_imm8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + return tie_t; +} + +static void +Field_imm8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); +} + +static unsigned +Field_s_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_s_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_imm12b_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 8) | ((insn[0] << 8) >> 24); + return tie_t; +} + +static void +Field_imm12b_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 24) >> 24; + insn[0] = (insn[0] & ~0xff0000) | (tie_t << 16); + tie_t = (val << 20) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_imm16_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 16) | ((insn[0] << 8) >> 16); + return tie_t; +} + +static void +Field_imm16_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 16) >> 16; + insn[0] = (insn[0] & ~0xffff00) | (tie_t << 8); +} + +static unsigned +Field_offset_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 8) >> 14); + return tie_t; +} + +static void +Field_offset_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc0) | (tie_t << 6); +} + +static unsigned +Field_r_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_r_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_sa4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + return tie_t; +} + +static void +Field_sa4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_sae4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + return tie_t; +} + +static void +Field_sae4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_sae_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 15) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sae_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10000) | (tie_t << 16); +} + +static unsigned +Field_sal_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_sal_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_sargt_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sargt_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_sas4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + return tie_t; +} + +static void +Field_sas4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); +} + +static unsigned +Field_sas_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 27) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sas_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x10) | (tie_t << 4); +} + +static unsigned +Field_sr_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sr_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_sr_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + return tie_t; +} + +static void +Field_sr_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_st_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_st_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_st_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 20) >> 28); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_st_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 24) >> 28; + insn[0] = (insn[0] & ~0xf00) | (tie_t << 8); +} + +static unsigned +Field_imm4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm4_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm4_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm4_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm4_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_mn_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_mn_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); + tie_t = (val << 28) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_i_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_i_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_imm6lo_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6lo_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm6lo_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6lo_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm6hi_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_imm6hi_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm6hi_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + return tie_t; +} + +static void +Field_imm6hi_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm7lo_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7lo_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm7lo_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7lo_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); +} + +static unsigned +Field_imm7hi_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_imm7hi_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_imm7hi_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + return tie_t; +} + +static void +Field_imm7hi_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_z_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_z_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_imm6_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm6_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 26) >> 30); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm6_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 26) >> 30; + insn[0] = (insn[0] & ~0x30) | (tie_t << 4); +} + +static unsigned +Field_imm7_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_imm7_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 25) >> 29); + tie_t = (tie_t << 4) | ((insn[0] << 16) >> 28); + return tie_t; +} + +static void +Field_imm7_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf000) | (tie_t << 12); + tie_t = (val << 25) >> 29; + insn[0] = (insn[0] & ~0x70) | (tie_t << 4); +} + +static unsigned +Field_rbit2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_rbit2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_tbit2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_tbit2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_y_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 25) >> 31); + return tie_t; +} + +static void +Field_y_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x40) | (tie_t << 6); +} + +static unsigned +Field_x_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 17) >> 31); + return tie_t; +} + +static void +Field_x_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x4000) | (tie_t << 14); +} + +static unsigned +Field_t2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_t2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_t2_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_t2_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_t2_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 24) >> 29); + return tie_t; +} + +static void +Field_t2_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe0) | (tie_t << 5); +} + +static unsigned +Field_s2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_s2_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s2_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_s2_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s2_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_r2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_r2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_r2_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_r2_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_r2_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_r2_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_t4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_t4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_t4_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_t4_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_t4_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 24) >> 30); + return tie_t; +} + +static void +Field_t4_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc0) | (tie_t << 6); +} + +static unsigned +Field_s4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_s4_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_s4_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 20) >> 30); + return tie_t; +} + +static void +Field_s4_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc00) | (tie_t << 10); +} + +static unsigned +Field_r4_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_r4_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_r4_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_r4_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_r4_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 16) >> 30); + return tie_t; +} + +static void +Field_r4_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0xc000) | (tie_t << 14); +} + +static unsigned +Field_t8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_t8_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t8_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_t8_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 24) >> 31); + return tie_t; +} + +static void +Field_t8_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x80) | (tie_t << 7); +} + +static unsigned +Field_s8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_s8_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_s8_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 20) >> 31); + return tie_t; +} + +static void +Field_s8_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x800) | (tie_t << 11); +} + +static unsigned +Field_r8_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r8_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_r8_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r8_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_r8_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_r8_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_xt_wbr15_imm_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 15) | ((insn[0] << 8) >> 17); + return tie_t; +} + +static void +Field_xt_wbr15_imm_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 17) >> 17; + insn[0] = (insn[0] & ~0xfffe00) | (tie_t << 9); +} + +static unsigned +Field_xt_wbr18_imm_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 18) | ((insn[0] << 8) >> 14); + return tie_t; +} + +static void +Field_xt_wbr18_imm_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 14) >> 14; + insn[0] = (insn[0] & ~0xffffc0) | (tie_t << 6); +} + +static unsigned +Field_dfp_fld_r_0_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_r_0_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dfp_fld_r_0_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_r_0_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dfp_fld_r_0_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 19) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_r_0_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x1000) | (tie_t << 12); +} + +static unsigned +Field_dfp_fld_r_2_1_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dfp_fld_r_2_1_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dfp_fld_r_2_1_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dfp_fld_r_2_1_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dfp_fld_r_2_1_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 17) >> 30); + return tie_t; +} + +static void +Field_dfp_fld_r_2_1_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x6000) | (tie_t << 13); +} + +static unsigned +Field_dfp_fld_r_3_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_r_3_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dfp_fld_r_3_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 16) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_r_3_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x8000) | (tie_t << 15); +} + +static unsigned +Field_dfp_fld_r_3_1_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_dfp_fld_r_3_1_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_dfp_fld_r_3_1_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 16) >> 29); + return tie_t; +} + +static void +Field_dfp_fld_r_3_1_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe000) | (tie_t << 13); +} + +static unsigned +Field_dfp_fld_s_0_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_s_0_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_dfp_fld_s_0_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_s_0_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_dfp_fld_s_0_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_s_0_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_dfp_fld_s_3_1_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dfp_fld_s_3_1_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_dfp_fld_s_3_1_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_dfp_fld_s_3_1_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_dfp_fld_op2_0_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 11) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_op2_0_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x100000) | (tie_t << 20); +} + +static unsigned +Field_dfp_fld_op2_1_0_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 2) | ((insn[0] << 10) >> 30); + return tie_t; +} + +static void +Field_dfp_fld_op2_1_0_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 30) >> 30; + insn[0] = (insn[0] & ~0x300000) | (tie_t << 20); +} + +static unsigned +Field_dfp_fld_op2_2_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 9) >> 31); + return tie_t; +} + +static void +Field_dfp_fld_op2_2_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 31) >> 31; + insn[0] = (insn[0] & ~0x400000) | (tie_t << 22); +} + +static unsigned +Field_bitindex_Slot_inst_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_bitindex_Slot_inst_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_bitindex_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_bitindex_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_bitindex_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 1) | ((insn[0] << 23) >> 31); + tie_t = (tie_t << 4) | ((insn[0] << 24) >> 28); + return tie_t; +} + +static void +Field_bitindex_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 28) >> 28; + insn[0] = (insn[0] & ~0xf0) | (tie_t << 4); + tie_t = (val << 27) >> 31; + insn[0] = (insn[0] & ~0x100) | (tie_t << 8); +} + +static unsigned +Field_s3to1_Slot_inst16a_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s3to1_Slot_inst16a_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static unsigned +Field_s3to1_Slot_inst16b_get (const xtensa_insnbuf insn) +{ + unsigned tie_t = 0; + tie_t = (tie_t << 3) | ((insn[0] << 20) >> 29); + return tie_t; +} + +static void +Field_s3to1_Slot_inst16b_set (xtensa_insnbuf insn, uint32 val) +{ + uint32 tie_t; + tie_t = (val << 29) >> 29; + insn[0] = (insn[0] & ~0xe00) | (tie_t << 9); +} + +static void +Implicit_Field_set (xtensa_insnbuf insn ATTRIBUTE_UNUSED, + uint32 val ATTRIBUTE_UNUSED) +{ + /* Do nothing. */ +} + +static unsigned +Implicit_Field_ar0_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_ar4_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 4; +} + +static unsigned +Implicit_Field_ar8_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 8; +} + +static unsigned +Implicit_Field_ar12_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 12; +} + +static unsigned +Implicit_Field_mr0_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_mr1_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 1; +} + +static unsigned +Implicit_Field_mr2_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 2; +} + +static unsigned +Implicit_Field_mr3_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 3; +} + +static unsigned +Implicit_Field_bt16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_bs16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_br16_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +static unsigned +Implicit_Field_brall_get (const xtensa_insnbuf insn ATTRIBUTE_UNUSED) +{ + return 0; +} + +enum xtensa_field_id { + FIELD_t, + FIELD_bbi4, + FIELD_bbi, + FIELD_imm12, + FIELD_imm8, + FIELD_s, + FIELD_imm12b, + FIELD_imm16, + FIELD_m, + FIELD_n, + FIELD_offset, + FIELD_op0, + FIELD_op1, + FIELD_op2, + FIELD_r, + FIELD_sa4, + FIELD_sae4, + FIELD_sae, + FIELD_sal, + FIELD_sargt, + FIELD_sas4, + FIELD_sas, + FIELD_sr, + FIELD_st, + FIELD_thi3, + FIELD_imm4, + FIELD_mn, + FIELD_i, + FIELD_imm6lo, + FIELD_imm6hi, + FIELD_imm7lo, + FIELD_imm7hi, + FIELD_z, + FIELD_imm6, + FIELD_imm7, + FIELD_r3, + FIELD_rbit2, + FIELD_rhi, + FIELD_t3, + FIELD_tbit2, + FIELD_tlo, + FIELD_w, + FIELD_y, + FIELD_x, + FIELD_t2, + FIELD_s2, + FIELD_r2, + FIELD_t4, + FIELD_s4, + FIELD_r4, + FIELD_t8, + FIELD_s8, + FIELD_r8, + FIELD_xt_wbr15_imm, + FIELD_xt_wbr18_imm, + FIELD_dfp_fld_op1, + FIELD_dfp_fld_op2, + FIELD_dfp_fld_r_0, + FIELD_dfp_fld_r_2_1, + FIELD_dfp_fld_r_3, + FIELD_dfp_fld_r_3_1, + FIELD_dfp_fld_s_0, + FIELD_dfp_fld_s_3_1, + FIELD_dfp_fld_op2_0, + FIELD_dfp_fld_op2_1_0, + FIELD_dfp_fld_op2_2, + FIELD_dfp_fld_op2_3, + FIELD_dfp_fld_op2_3_2, + FIELD_dfp_fld_op2_3_1, + FIELD_bitindex, + FIELD_s3to1, + FIELD__ar0, + FIELD__ar4, + FIELD__ar8, + FIELD__ar12, + FIELD__mr0, + FIELD__mr1, + FIELD__mr2, + FIELD__mr3, + FIELD__bt16, + FIELD__bs16, + FIELD__br16, + FIELD__brall +}; + + +/* Functional units. */ + +#define funcUnits 0 + + +/* Register files. */ + +enum xtensa_regfile_id { + REGFILE_AR, + REGFILE_MR, + REGFILE_BR, + REGFILE_FR, + REGFILE_BR2, + REGFILE_BR4, + REGFILE_BR8, + REGFILE_BR16 +}; + +static xtensa_regfile_internal regfiles[] = { + { "AR", "a", REGFILE_AR, 32, 64 }, + { "MR", "m", REGFILE_MR, 32, 4 }, + { "BR", "b", REGFILE_BR, 1, 16 }, + { "FR", "f", REGFILE_FR, 32, 16 }, + { "BR2", "b", REGFILE_BR, 2, 8 }, + { "BR4", "b", REGFILE_BR, 4, 4 }, + { "BR8", "b", REGFILE_BR, 8, 2 }, + { "BR16", "b", REGFILE_BR, 16, 1 } +}; + + +/* Interfaces. */ + +static xtensa_interface_internal interfaces[] = { + { "ERI_RD_Out", 14, 0, 0, 'o' }, + { "ERI_RD_In", 32, 0, 1, 'i' }, + { "ERI_RD_Rdy", 1, 0, 0, 'i' }, + { "ERI_WR_Out", 46, 0, 2, 'o' }, + { "ERI_WR_In", 1, 0, 3, 'i' }, + { "IMPWIRE", 32, 0, 4, 'i' } +}; + +enum xtensa_interface_id { + INTERFACE_ERI_RD_Out, + INTERFACE_ERI_RD_In, + INTERFACE_ERI_RD_Rdy, + INTERFACE_ERI_WR_Out, + INTERFACE_ERI_WR_In, + INTERFACE_IMPWIRE +}; + + +/* Constant tables. */ + +/* constant table ai4c */ +static const unsigned CONST_TBL_ai4c_0[] = { + 0xffffffff, + 0x1, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0x9, + 0xa, + 0xb, + 0xc, + 0xd, + 0xe, + 0xf, + 0 +}; + +/* constant table b4c */ +static const unsigned CONST_TBL_b4c_0[] = { + 0xffffffff, + 0x1, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0xa, + 0xc, + 0x10, + 0x20, + 0x40, + 0x80, + 0x100, + 0 +}; + +/* constant table b4cu */ +static const unsigned CONST_TBL_b4cu_0[] = { + 0x8000, + 0x10000, + 0x2, + 0x3, + 0x4, + 0x5, + 0x6, + 0x7, + 0x8, + 0xa, + 0xc, + 0x10, + 0x20, + 0x40, + 0x80, + 0x100, + 0 +}; + +/* constant table RECIP_Data8 */ +static const unsigned CONST_TBL_RECIP_Data8_0[] = { + 0xff & 0xff, + 0xfd & 0xff, + 0xfb & 0xff, + 0xf9 & 0xff, + 0xf7 & 0xff, + 0xf5 & 0xff, + 0xf4 & 0xff, + 0xf2 & 0xff, + 0xf0 & 0xff, + 0xee & 0xff, + 0xed & 0xff, + 0xeb & 0xff, + 0xe9 & 0xff, + 0xe8 & 0xff, + 0xe6 & 0xff, + 0xe4 & 0xff, + 0xe3 & 0xff, + 0xe1 & 0xff, + 0xe0 & 0xff, + 0xde & 0xff, + 0xdd & 0xff, + 0xdb & 0xff, + 0xda & 0xff, + 0xd8 & 0xff, + 0xd7 & 0xff, + 0xd5 & 0xff, + 0xd4 & 0xff, + 0xd3 & 0xff, + 0xd1 & 0xff, + 0xd0 & 0xff, + 0xcf & 0xff, + 0xcd & 0xff, + 0xcc & 0xff, + 0xcb & 0xff, + 0xca & 0xff, + 0xc8 & 0xff, + 0xc7 & 0xff, + 0xc6 & 0xff, + 0xc5 & 0xff, + 0xc4 & 0xff, + 0xc2 & 0xff, + 0xc1 & 0xff, + 0xc0 & 0xff, + 0xbf & 0xff, + 0xbe & 0xff, + 0xbd & 0xff, + 0xbc & 0xff, + 0xbb & 0xff, + 0xba & 0xff, + 0xb9 & 0xff, + 0xb8 & 0xff, + 0xb7 & 0xff, + 0xb6 & 0xff, + 0xb5 & 0xff, + 0xb4 & 0xff, + 0xb3 & 0xff, + 0xb2 & 0xff, + 0xb1 & 0xff, + 0xb0 & 0xff, + 0xaf & 0xff, + 0xae & 0xff, + 0xad & 0xff, + 0xac & 0xff, + 0xab & 0xff, + 0xaa & 0xff, + 0xa9 & 0xff, + 0xa8 & 0xff, + 0xa8 & 0xff, + 0xa7 & 0xff, + 0xa6 & 0xff, + 0xa5 & 0xff, + 0xa4 & 0xff, + 0xa3 & 0xff, + 0xa3 & 0xff, + 0xa2 & 0xff, + 0xa1 & 0xff, + 0xa0 & 0xff, + 0x9f & 0xff, + 0x9f & 0xff, + 0x9e & 0xff, + 0x9d & 0xff, + 0x9c & 0xff, + 0x9c & 0xff, + 0x9b & 0xff, + 0x9a & 0xff, + 0x99 & 0xff, + 0x99 & 0xff, + 0x98 & 0xff, + 0x97 & 0xff, + 0x97 & 0xff, + 0x96 & 0xff, + 0x95 & 0xff, + 0x95 & 0xff, + 0x94 & 0xff, + 0x93 & 0xff, + 0x93 & 0xff, + 0x92 & 0xff, + 0x91 & 0xff, + 0x91 & 0xff, + 0x90 & 0xff, + 0x8f & 0xff, + 0x8f & 0xff, + 0x8e & 0xff, + 0x8e & 0xff, + 0x8d & 0xff, + 0x8c & 0xff, + 0x8c & 0xff, + 0x8b & 0xff, + 0x8b & 0xff, + 0x8a & 0xff, + 0x89 & 0xff, + 0x89 & 0xff, + 0x88 & 0xff, + 0x88 & 0xff, + 0x87 & 0xff, + 0x87 & 0xff, + 0x86 & 0xff, + 0x85 & 0xff, + 0x85 & 0xff, + 0x84 & 0xff, + 0x84 & 0xff, + 0x83 & 0xff, + 0x83 & 0xff, + 0x82 & 0xff, + 0x82 & 0xff, + 0x81 & 0xff, + 0x81 & 0xff, + 0x81 & 0xff, + 0 +}; + +/* constant table RSQRT_Data8 */ +static const unsigned CONST_TBL_RSQRT_Data8_0[] = { + 0xb4 & 0xff, + 0xb3 & 0xff, + 0xb2 & 0xff, + 0xb0 & 0xff, + 0xaf & 0xff, + 0xae & 0xff, + 0xac & 0xff, + 0xab & 0xff, + 0xaa & 0xff, + 0xa9 & 0xff, + 0xa8 & 0xff, + 0xa7 & 0xff, + 0xa6 & 0xff, + 0xa5 & 0xff, + 0xa3 & 0xff, + 0xa2 & 0xff, + 0xa1 & 0xff, + 0xa0 & 0xff, + 0x9f & 0xff, + 0x9e & 0xff, + 0x9e & 0xff, + 0x9d & 0xff, + 0x9c & 0xff, + 0x9b & 0xff, + 0x9a & 0xff, + 0x99 & 0xff, + 0x98 & 0xff, + 0x97 & 0xff, + 0x97 & 0xff, + 0x96 & 0xff, + 0x95 & 0xff, + 0x94 & 0xff, + 0x93 & 0xff, + 0x93 & 0xff, + 0x92 & 0xff, + 0x91 & 0xff, + 0x90 & 0xff, + 0x90 & 0xff, + 0x8f & 0xff, + 0x8e & 0xff, + 0x8e & 0xff, + 0x8d & 0xff, + 0x8c & 0xff, + 0x8c & 0xff, + 0x8b & 0xff, + 0x8a & 0xff, + 0x8a & 0xff, + 0x89 & 0xff, + 0x89 & 0xff, + 0x88 & 0xff, + 0x87 & 0xff, + 0x87 & 0xff, + 0x86 & 0xff, + 0x86 & 0xff, + 0x85 & 0xff, + 0x84 & 0xff, + 0x84 & 0xff, + 0x83 & 0xff, + 0x83 & 0xff, + 0x82 & 0xff, + 0x82 & 0xff, + 0x81 & 0xff, + 0x81 & 0xff, + 0x80 & 0xff, + 0xff & 0xff, + 0xfd & 0xff, + 0xfb & 0xff, + 0xf9 & 0xff, + 0xf7 & 0xff, + 0xf6 & 0xff, + 0xf4 & 0xff, + 0xf2 & 0xff, + 0xf1 & 0xff, + 0xef & 0xff, + 0xed & 0xff, + 0xec & 0xff, + 0xea & 0xff, + 0xe9 & 0xff, + 0xe7 & 0xff, + 0xe6 & 0xff, + 0xe4 & 0xff, + 0xe3 & 0xff, + 0xe1 & 0xff, + 0xe0 & 0xff, + 0xdf & 0xff, + 0xdd & 0xff, + 0xdc & 0xff, + 0xdb & 0xff, + 0xda & 0xff, + 0xd8 & 0xff, + 0xd7 & 0xff, + 0xd6 & 0xff, + 0xd5 & 0xff, + 0xd4 & 0xff, + 0xd3 & 0xff, + 0xd2 & 0xff, + 0xd0 & 0xff, + 0xcf & 0xff, + 0xce & 0xff, + 0xcd & 0xff, + 0xcc & 0xff, + 0xcb & 0xff, + 0xca & 0xff, + 0xc9 & 0xff, + 0xc8 & 0xff, + 0xc7 & 0xff, + 0xc6 & 0xff, + 0xc6 & 0xff, + 0xc5 & 0xff, + 0xc4 & 0xff, + 0xc3 & 0xff, + 0xc2 & 0xff, + 0xc1 & 0xff, + 0xc0 & 0xff, + 0xbf & 0xff, + 0xbf & 0xff, + 0xbe & 0xff, + 0xbd & 0xff, + 0xbc & 0xff, + 0xbb & 0xff, + 0xbb & 0xff, + 0xba & 0xff, + 0xb9 & 0xff, + 0xb8 & 0xff, + 0xb8 & 0xff, + 0xb7 & 0xff, + 0xb6 & 0xff, + 0xb5 & 0xff, + 0 +}; + +/* constant table RECIP_Data10_2 */ +static const unsigned CONST_TBL_RECIP_Data10_2_0[] = { + 0x3fc & 0x3ff, + 0x3f4 & 0x3ff, + 0x3ec & 0x3ff, + 0x3e5 & 0x3ff, + 0x3dd & 0x3ff, + 0x3d6 & 0x3ff, + 0x3cf & 0x3ff, + 0x3c7 & 0x3ff, + 0x3c0 & 0x3ff, + 0x3b9 & 0x3ff, + 0x3b2 & 0x3ff, + 0x3ac & 0x3ff, + 0x3a5 & 0x3ff, + 0x39e & 0x3ff, + 0x398 & 0x3ff, + 0x391 & 0x3ff, + 0x38b & 0x3ff, + 0x385 & 0x3ff, + 0x37f & 0x3ff, + 0x378 & 0x3ff, + 0x373 & 0x3ff, + 0x36c & 0x3ff, + 0x367 & 0x3ff, + 0x361 & 0x3ff, + 0x35c & 0x3ff, + 0x356 & 0x3ff, + 0x350 & 0x3ff, + 0x34b & 0x3ff, + 0x345 & 0x3ff, + 0x340 & 0x3ff, + 0x33b & 0x3ff, + 0x335 & 0x3ff, + 0x330 & 0x3ff, + 0x32c & 0x3ff, + 0x327 & 0x3ff, + 0x322 & 0x3ff, + 0x31c & 0x3ff, + 0x318 & 0x3ff, + 0x314 & 0x3ff, + 0x30e & 0x3ff, + 0x30a & 0x3ff, + 0x306 & 0x3ff, + 0x300 & 0x3ff, + 0x2fc & 0x3ff, + 0x2f8 & 0x3ff, + 0x2f4 & 0x3ff, + 0x2f0 & 0x3ff, + 0x2ea & 0x3ff, + 0x2e6 & 0x3ff, + 0x2e2 & 0x3ff, + 0x2de & 0x3ff, + 0x2da & 0x3ff, + 0x2d6 & 0x3ff, + 0x2d2 & 0x3ff, + 0x2ce & 0x3ff, + 0x2ca & 0x3ff, + 0x2c6 & 0x3ff, + 0x2c2 & 0x3ff, + 0x2be & 0x3ff, + 0x2ba & 0x3ff, + 0x2b8 & 0x3ff, + 0x2b4 & 0x3ff, + 0x2b0 & 0x3ff, + 0x2ac & 0x3ff, + 0x2a8 & 0x3ff, + 0x2a6 & 0x3ff, + 0x2a2 & 0x3ff, + 0x29e & 0x3ff, + 0x29c & 0x3ff, + 0x298 & 0x3ff, + 0x294 & 0x3ff, + 0x290 & 0x3ff, + 0x28e & 0x3ff, + 0x28a & 0x3ff, + 0x288 & 0x3ff, + 0x284 & 0x3ff, + 0x280 & 0x3ff, + 0x27e & 0x3ff, + 0x27a & 0x3ff, + 0x278 & 0x3ff, + 0x274 & 0x3ff, + 0x272 & 0x3ff, + 0x26e & 0x3ff, + 0x26c & 0x3ff, + 0x268 & 0x3ff, + 0x266 & 0x3ff, + 0x264 & 0x3ff, + 0x260 & 0x3ff, + 0x25e & 0x3ff, + 0x25a & 0x3ff, + 0x258 & 0x3ff, + 0x254 & 0x3ff, + 0x252 & 0x3ff, + 0x250 & 0x3ff, + 0x24c & 0x3ff, + 0x24a & 0x3ff, + 0x248 & 0x3ff, + 0x246 & 0x3ff, + 0x242 & 0x3ff, + 0x240 & 0x3ff, + 0x23e & 0x3ff, + 0x23c & 0x3ff, + 0x238 & 0x3ff, + 0x236 & 0x3ff, + 0x234 & 0x3ff, + 0x232 & 0x3ff, + 0x230 & 0x3ff, + 0x22c & 0x3ff, + 0x22a & 0x3ff, + 0x228 & 0x3ff, + 0x226 & 0x3ff, + 0x224 & 0x3ff, + 0x220 & 0x3ff, + 0x21e & 0x3ff, + 0x21c & 0x3ff, + 0x21a & 0x3ff, + 0x218 & 0x3ff, + 0x216 & 0x3ff, + 0x214 & 0x3ff, + 0x212 & 0x3ff, + 0x210 & 0x3ff, + 0x20e & 0x3ff, + 0x20c & 0x3ff, + 0x208 & 0x3ff, + 0x208 & 0x3ff, + 0x204 & 0x3ff, + 0x204 & 0x3ff, + 0x201 & 0x3ff, + 0 +}; + +/* constant table RSQRT_10b_256 */ +static const unsigned CONST_TBL_RSQRT_10b_256_0[] = { + 0x1a5 & 0x3ff, + 0x1a0 & 0x3ff, + 0x19a & 0x3ff, + 0x195 & 0x3ff, + 0x18f & 0x3ff, + 0x18a & 0x3ff, + 0x185 & 0x3ff, + 0x180 & 0x3ff, + 0x17a & 0x3ff, + 0x175 & 0x3ff, + 0x170 & 0x3ff, + 0x16b & 0x3ff, + 0x166 & 0x3ff, + 0x161 & 0x3ff, + 0x15d & 0x3ff, + 0x158 & 0x3ff, + 0x153 & 0x3ff, + 0x14e & 0x3ff, + 0x14a & 0x3ff, + 0x145 & 0x3ff, + 0x140 & 0x3ff, + 0x13c & 0x3ff, + 0x138 & 0x3ff, + 0x133 & 0x3ff, + 0x12f & 0x3ff, + 0x12a & 0x3ff, + 0x126 & 0x3ff, + 0x122 & 0x3ff, + 0x11e & 0x3ff, + 0x11a & 0x3ff, + 0x115 & 0x3ff, + 0x111 & 0x3ff, + 0x10d & 0x3ff, + 0x109 & 0x3ff, + 0x105 & 0x3ff, + 0x101 & 0x3ff, + 0xfd & 0x3ff, + 0xfa & 0x3ff, + 0xf6 & 0x3ff, + 0xf2 & 0x3ff, + 0xee & 0x3ff, + 0xea & 0x3ff, + 0xe7 & 0x3ff, + 0xe3 & 0x3ff, + 0xdf & 0x3ff, + 0xdc & 0x3ff, + 0xd8 & 0x3ff, + 0xd5 & 0x3ff, + 0xd1 & 0x3ff, + 0xce & 0x3ff, + 0xca & 0x3ff, + 0xc7 & 0x3ff, + 0xc3 & 0x3ff, + 0xc0 & 0x3ff, + 0xbd & 0x3ff, + 0xb9 & 0x3ff, + 0xb6 & 0x3ff, + 0xb3 & 0x3ff, + 0xb0 & 0x3ff, + 0xad & 0x3ff, + 0xa9 & 0x3ff, + 0xa6 & 0x3ff, + 0xa3 & 0x3ff, + 0xa0 & 0x3ff, + 0x9d & 0x3ff, + 0x9a & 0x3ff, + 0x97 & 0x3ff, + 0x94 & 0x3ff, + 0x91 & 0x3ff, + 0x8e & 0x3ff, + 0x8b & 0x3ff, + 0x88 & 0x3ff, + 0x85 & 0x3ff, + 0x82 & 0x3ff, + 0x7f & 0x3ff, + 0x7d & 0x3ff, + 0x7a & 0x3ff, + 0x77 & 0x3ff, + 0x74 & 0x3ff, + 0x71 & 0x3ff, + 0x6f & 0x3ff, + 0x6c & 0x3ff, + 0x69 & 0x3ff, + 0x67 & 0x3ff, + 0x64 & 0x3ff, + 0x61 & 0x3ff, + 0x5f & 0x3ff, + 0x5c & 0x3ff, + 0x5a & 0x3ff, + 0x57 & 0x3ff, + 0x54 & 0x3ff, + 0x52 & 0x3ff, + 0x4f & 0x3ff, + 0x4d & 0x3ff, + 0x4a & 0x3ff, + 0x48 & 0x3ff, + 0x45 & 0x3ff, + 0x43 & 0x3ff, + 0x41 & 0x3ff, + 0x3e & 0x3ff, + 0x3c & 0x3ff, + 0x3a & 0x3ff, + 0x37 & 0x3ff, + 0x35 & 0x3ff, + 0x33 & 0x3ff, + 0x30 & 0x3ff, + 0x2e & 0x3ff, + 0x2c & 0x3ff, + 0x29 & 0x3ff, + 0x27 & 0x3ff, + 0x25 & 0x3ff, + 0x23 & 0x3ff, + 0x20 & 0x3ff, + 0x1e & 0x3ff, + 0x1c & 0x3ff, + 0x1a & 0x3ff, + 0x18 & 0x3ff, + 0x16 & 0x3ff, + 0x14 & 0x3ff, + 0x11 & 0x3ff, + 0xf & 0x3ff, + 0xd & 0x3ff, + 0xb & 0x3ff, + 0x9 & 0x3ff, + 0x7 & 0x3ff, + 0x5 & 0x3ff, + 0x3 & 0x3ff, + 0x1 & 0x3ff, + 0x3fc & 0x3ff, + 0x3f4 & 0x3ff, + 0x3ec & 0x3ff, + 0x3e5 & 0x3ff, + 0x3dd & 0x3ff, + 0x3d5 & 0x3ff, + 0x3ce & 0x3ff, + 0x3c7 & 0x3ff, + 0x3bf & 0x3ff, + 0x3b8 & 0x3ff, + 0x3b1 & 0x3ff, + 0x3aa & 0x3ff, + 0x3a3 & 0x3ff, + 0x39c & 0x3ff, + 0x395 & 0x3ff, + 0x38e & 0x3ff, + 0x388 & 0x3ff, + 0x381 & 0x3ff, + 0x37a & 0x3ff, + 0x374 & 0x3ff, + 0x36d & 0x3ff, + 0x367 & 0x3ff, + 0x361 & 0x3ff, + 0x35a & 0x3ff, + 0x354 & 0x3ff, + 0x34e & 0x3ff, + 0x348 & 0x3ff, + 0x342 & 0x3ff, + 0x33c & 0x3ff, + 0x336 & 0x3ff, + 0x330 & 0x3ff, + 0x32b & 0x3ff, + 0x325 & 0x3ff, + 0x31f & 0x3ff, + 0x31a & 0x3ff, + 0x314 & 0x3ff, + 0x30f & 0x3ff, + 0x309 & 0x3ff, + 0x304 & 0x3ff, + 0x2fe & 0x3ff, + 0x2f9 & 0x3ff, + 0x2f4 & 0x3ff, + 0x2ee & 0x3ff, + 0x2e9 & 0x3ff, + 0x2e4 & 0x3ff, + 0x2df & 0x3ff, + 0x2da & 0x3ff, + 0x2d5 & 0x3ff, + 0x2d0 & 0x3ff, + 0x2cb & 0x3ff, + 0x2c6 & 0x3ff, + 0x2c1 & 0x3ff, + 0x2bd & 0x3ff, + 0x2b8 & 0x3ff, + 0x2b3 & 0x3ff, + 0x2ae & 0x3ff, + 0x2aa & 0x3ff, + 0x2a5 & 0x3ff, + 0x2a1 & 0x3ff, + 0x29c & 0x3ff, + 0x298 & 0x3ff, + 0x293 & 0x3ff, + 0x28f & 0x3ff, + 0x28a & 0x3ff, + 0x286 & 0x3ff, + 0x282 & 0x3ff, + 0x27d & 0x3ff, + 0x279 & 0x3ff, + 0x275 & 0x3ff, + 0x271 & 0x3ff, + 0x26d & 0x3ff, + 0x268 & 0x3ff, + 0x264 & 0x3ff, + 0x260 & 0x3ff, + 0x25c & 0x3ff, + 0x258 & 0x3ff, + 0x254 & 0x3ff, + 0x250 & 0x3ff, + 0x24c & 0x3ff, + 0x249 & 0x3ff, + 0x245 & 0x3ff, + 0x241 & 0x3ff, + 0x23d & 0x3ff, + 0x239 & 0x3ff, + 0x235 & 0x3ff, + 0x232 & 0x3ff, + 0x22e & 0x3ff, + 0x22a & 0x3ff, + 0x227 & 0x3ff, + 0x223 & 0x3ff, + 0x220 & 0x3ff, + 0x21c & 0x3ff, + 0x218 & 0x3ff, + 0x215 & 0x3ff, + 0x211 & 0x3ff, + 0x20e & 0x3ff, + 0x20a & 0x3ff, + 0x207 & 0x3ff, + 0x204 & 0x3ff, + 0x200 & 0x3ff, + 0x1fd & 0x3ff, + 0x1f9 & 0x3ff, + 0x1f6 & 0x3ff, + 0x1f3 & 0x3ff, + 0x1f0 & 0x3ff, + 0x1ec & 0x3ff, + 0x1e9 & 0x3ff, + 0x1e6 & 0x3ff, + 0x1e3 & 0x3ff, + 0x1df & 0x3ff, + 0x1dc & 0x3ff, + 0x1d9 & 0x3ff, + 0x1d6 & 0x3ff, + 0x1d3 & 0x3ff, + 0x1d0 & 0x3ff, + 0x1cd & 0x3ff, + 0x1ca & 0x3ff, + 0x1c7 & 0x3ff, + 0x1c4 & 0x3ff, + 0x1c1 & 0x3ff, + 0x1be & 0x3ff, + 0x1bb & 0x3ff, + 0x1b8 & 0x3ff, + 0x1b5 & 0x3ff, + 0x1b2 & 0x3ff, + 0x1af & 0x3ff, + 0x1ac & 0x3ff, + 0x1aa & 0x3ff, + 0 +}; + +/* constant table RECIP_10b_256 */ +static const unsigned CONST_TBL_RECIP_10b_256_0[] = { + 0x3fc & 0x3ff, + 0x3f4 & 0x3ff, + 0x3ec & 0x3ff, + 0x3e4 & 0x3ff, + 0x3dd & 0x3ff, + 0x3d5 & 0x3ff, + 0x3cd & 0x3ff, + 0x3c6 & 0x3ff, + 0x3be & 0x3ff, + 0x3b7 & 0x3ff, + 0x3af & 0x3ff, + 0x3a8 & 0x3ff, + 0x3a1 & 0x3ff, + 0x399 & 0x3ff, + 0x392 & 0x3ff, + 0x38b & 0x3ff, + 0x384 & 0x3ff, + 0x37d & 0x3ff, + 0x376 & 0x3ff, + 0x36f & 0x3ff, + 0x368 & 0x3ff, + 0x361 & 0x3ff, + 0x35b & 0x3ff, + 0x354 & 0x3ff, + 0x34d & 0x3ff, + 0x346 & 0x3ff, + 0x340 & 0x3ff, + 0x339 & 0x3ff, + 0x333 & 0x3ff, + 0x32c & 0x3ff, + 0x326 & 0x3ff, + 0x320 & 0x3ff, + 0x319 & 0x3ff, + 0x313 & 0x3ff, + 0x30d & 0x3ff, + 0x307 & 0x3ff, + 0x300 & 0x3ff, + 0x2fa & 0x3ff, + 0x2f4 & 0x3ff, + 0x2ee & 0x3ff, + 0x2e8 & 0x3ff, + 0x2e2 & 0x3ff, + 0x2dc & 0x3ff, + 0x2d7 & 0x3ff, + 0x2d1 & 0x3ff, + 0x2cb & 0x3ff, + 0x2c5 & 0x3ff, + 0x2bf & 0x3ff, + 0x2ba & 0x3ff, + 0x2b4 & 0x3ff, + 0x2af & 0x3ff, + 0x2a9 & 0x3ff, + 0x2a3 & 0x3ff, + 0x29e & 0x3ff, + 0x299 & 0x3ff, + 0x293 & 0x3ff, + 0x28e & 0x3ff, + 0x288 & 0x3ff, + 0x283 & 0x3ff, + 0x27e & 0x3ff, + 0x279 & 0x3ff, + 0x273 & 0x3ff, + 0x26e & 0x3ff, + 0x269 & 0x3ff, + 0x264 & 0x3ff, + 0x25f & 0x3ff, + 0x25a & 0x3ff, + 0x255 & 0x3ff, + 0x250 & 0x3ff, + 0x24b & 0x3ff, + 0x246 & 0x3ff, + 0x241 & 0x3ff, + 0x23c & 0x3ff, + 0x237 & 0x3ff, + 0x232 & 0x3ff, + 0x22e & 0x3ff, + 0x229 & 0x3ff, + 0x224 & 0x3ff, + 0x21f & 0x3ff, + 0x21b & 0x3ff, + 0x216 & 0x3ff, + 0x211 & 0x3ff, + 0x20d & 0x3ff, + 0x208 & 0x3ff, + 0x204 & 0x3ff, + 0x1ff & 0x3ff, + 0x1fb & 0x3ff, + 0x1f6 & 0x3ff, + 0x1f2 & 0x3ff, + 0x1ed & 0x3ff, + 0x1e9 & 0x3ff, + 0x1e5 & 0x3ff, + 0x1e0 & 0x3ff, + 0x1dc & 0x3ff, + 0x1d8 & 0x3ff, + 0x1d4 & 0x3ff, + 0x1cf & 0x3ff, + 0x1cb & 0x3ff, + 0x1c7 & 0x3ff, + 0x1c3 & 0x3ff, + 0x1bf & 0x3ff, + 0x1bb & 0x3ff, + 0x1b6 & 0x3ff, + 0x1b2 & 0x3ff, + 0x1ae & 0x3ff, + 0x1aa & 0x3ff, + 0x1a6 & 0x3ff, + 0x1a2 & 0x3ff, + 0x19e & 0x3ff, + 0x19a & 0x3ff, + 0x197 & 0x3ff, + 0x193 & 0x3ff, + 0x18f & 0x3ff, + 0x18b & 0x3ff, + 0x187 & 0x3ff, + 0x183 & 0x3ff, + 0x17f & 0x3ff, + 0x17c & 0x3ff, + 0x178 & 0x3ff, + 0x174 & 0x3ff, + 0x171 & 0x3ff, + 0x16d & 0x3ff, + 0x169 & 0x3ff, + 0x166 & 0x3ff, + 0x162 & 0x3ff, + 0x15e & 0x3ff, + 0x15b & 0x3ff, + 0x157 & 0x3ff, + 0x154 & 0x3ff, + 0x150 & 0x3ff, + 0x14d & 0x3ff, + 0x149 & 0x3ff, + 0x146 & 0x3ff, + 0x142 & 0x3ff, + 0x13f & 0x3ff, + 0x13b & 0x3ff, + 0x138 & 0x3ff, + 0x134 & 0x3ff, + 0x131 & 0x3ff, + 0x12e & 0x3ff, + 0x12a & 0x3ff, + 0x127 & 0x3ff, + 0x124 & 0x3ff, + 0x120 & 0x3ff, + 0x11d & 0x3ff, + 0x11a & 0x3ff, + 0x117 & 0x3ff, + 0x113 & 0x3ff, + 0x110 & 0x3ff, + 0x10d & 0x3ff, + 0x10a & 0x3ff, + 0x107 & 0x3ff, + 0x103 & 0x3ff, + 0x100 & 0x3ff, + 0xfd & 0x3ff, + 0xfa & 0x3ff, + 0xf7 & 0x3ff, + 0xf4 & 0x3ff, + 0xf1 & 0x3ff, + 0xee & 0x3ff, + 0xeb & 0x3ff, + 0xe8 & 0x3ff, + 0xe5 & 0x3ff, + 0xe2 & 0x3ff, + 0xdf & 0x3ff, + 0xdc & 0x3ff, + 0xd9 & 0x3ff, + 0xd6 & 0x3ff, + 0xd3 & 0x3ff, + 0xd0 & 0x3ff, + 0xcd & 0x3ff, + 0xca & 0x3ff, + 0xc8 & 0x3ff, + 0xc5 & 0x3ff, + 0xc2 & 0x3ff, + 0xbf & 0x3ff, + 0xbc & 0x3ff, + 0xb9 & 0x3ff, + 0xb7 & 0x3ff, + 0xb4 & 0x3ff, + 0xb1 & 0x3ff, + 0xae & 0x3ff, + 0xac & 0x3ff, + 0xa9 & 0x3ff, + 0xa6 & 0x3ff, + 0xa4 & 0x3ff, + 0xa1 & 0x3ff, + 0x9e & 0x3ff, + 0x9c & 0x3ff, + 0x99 & 0x3ff, + 0x96 & 0x3ff, + 0x94 & 0x3ff, + 0x91 & 0x3ff, + 0x8e & 0x3ff, + 0x8c & 0x3ff, + 0x89 & 0x3ff, + 0x87 & 0x3ff, + 0x84 & 0x3ff, + 0x82 & 0x3ff, + 0x7f & 0x3ff, + 0x7c & 0x3ff, + 0x7a & 0x3ff, + 0x77 & 0x3ff, + 0x75 & 0x3ff, + 0x73 & 0x3ff, + 0x70 & 0x3ff, + 0x6e & 0x3ff, + 0x6b & 0x3ff, + 0x69 & 0x3ff, + 0x66 & 0x3ff, + 0x64 & 0x3ff, + 0x61 & 0x3ff, + 0x5f & 0x3ff, + 0x5d & 0x3ff, + 0x5a & 0x3ff, + 0x58 & 0x3ff, + 0x56 & 0x3ff, + 0x53 & 0x3ff, + 0x51 & 0x3ff, + 0x4f & 0x3ff, + 0x4c & 0x3ff, + 0x4a & 0x3ff, + 0x48 & 0x3ff, + 0x45 & 0x3ff, + 0x43 & 0x3ff, + 0x41 & 0x3ff, + 0x3f & 0x3ff, + 0x3c & 0x3ff, + 0x3a & 0x3ff, + 0x38 & 0x3ff, + 0x36 & 0x3ff, + 0x33 & 0x3ff, + 0x31 & 0x3ff, + 0x2f & 0x3ff, + 0x2d & 0x3ff, + 0x2b & 0x3ff, + 0x29 & 0x3ff, + 0x26 & 0x3ff, + 0x24 & 0x3ff, + 0x22 & 0x3ff, + 0x20 & 0x3ff, + 0x1e & 0x3ff, + 0x1c & 0x3ff, + 0x1a & 0x3ff, + 0x18 & 0x3ff, + 0x15 & 0x3ff, + 0x13 & 0x3ff, + 0x11 & 0x3ff, + 0xf & 0x3ff, + 0xd & 0x3ff, + 0xb & 0x3ff, + 0x9 & 0x3ff, + 0x7 & 0x3ff, + 0x5 & 0x3ff, + 0x3 & 0x3ff, + 0x1 & 0x3ff, + 0 +}; + + +/* Instruction operands. */ + +static int +OperandSem_opnd_sem_MR_0_decode (uint32 *valp) +{ + *valp += 2; + return 0; +} + +static int +OperandSem_opnd_sem_MR_0_encode (uint32 *valp) +{ + int error; + error = ((*valp & ~0x3) != 0) || ((*valp & 0x2) == 0); + *valp = *valp & 1; + return error; +} + +static int +OperandSem_opnd_sem_soffsetx4_decode (uint32 *valp) +{ + unsigned soffsetx4_out_0; + unsigned soffsetx4_in_0; + soffsetx4_in_0 = *valp & 0x3ffff; + soffsetx4_out_0 = 0x4 + ((((int) soffsetx4_in_0 << 14) >> 14) << 2); + *valp = soffsetx4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_soffsetx4_encode (uint32 *valp) +{ + unsigned soffsetx4_in_0; + unsigned soffsetx4_out_0; + soffsetx4_out_0 = *valp; + soffsetx4_in_0 = ((soffsetx4_out_0 - 0x4) >> 2) & 0x3ffff; + *valp = soffsetx4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm12x8_decode (uint32 *valp) +{ + unsigned uimm12x8_out_0; + unsigned uimm12x8_in_0; + uimm12x8_in_0 = *valp & 0xfff; + uimm12x8_out_0 = uimm12x8_in_0 << 3; + *valp = uimm12x8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm12x8_encode (uint32 *valp) +{ + unsigned uimm12x8_in_0; + unsigned uimm12x8_out_0; + uimm12x8_out_0 = *valp; + uimm12x8_in_0 = ((uimm12x8_out_0 >> 3) & 0xfff); + *valp = uimm12x8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm4_decode (uint32 *valp) +{ + unsigned simm4_out_0; + unsigned simm4_in_0; + simm4_in_0 = *valp & 0xf; + simm4_out_0 = ((int) simm4_in_0 << 28) >> 28; + *valp = simm4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm4_encode (uint32 *valp) +{ + unsigned simm4_in_0; + unsigned simm4_out_0; + simm4_out_0 = *valp; + simm4_in_0 = (simm4_out_0 & 0xf); + *valp = simm4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_AR_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_encode (uint32 *valp) +{ + int error; + error = (*valp >= 64); + return error; +} + +static int +OperandSem_opnd_sem_AR_0_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_0_encode (uint32 *valp) +{ + int error; + error = (*valp >= 64); + return error; +} + +static int +OperandSem_opnd_sem_AR_1_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_1_encode (uint32 *valp) +{ + int error; + error = (*valp >= 64); + return error; +} + +static int +OperandSem_opnd_sem_AR_2_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_2_encode (uint32 *valp) +{ + int error; + error = (*valp >= 64); + return error; +} + +static int +OperandSem_opnd_sem_AR_3_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_3_encode (uint32 *valp) +{ + int error; + error = (*valp >= 64); + return error; +} + +static int +OperandSem_opnd_sem_AR_4_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_AR_4_encode (uint32 *valp) +{ + int error; + error = (*valp >= 64); + return error; +} + +static int +OperandSem_opnd_sem_immrx4_decode (uint32 *valp) +{ + unsigned immrx4_out_0; + unsigned immrx4_in_0; + immrx4_in_0 = *valp & 0xf; + immrx4_out_0 = (((0xfffffff) << 4) | immrx4_in_0) << 2; + *valp = immrx4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_immrx4_encode (uint32 *valp) +{ + unsigned immrx4_in_0; + unsigned immrx4_out_0; + immrx4_out_0 = *valp; + immrx4_in_0 = ((immrx4_out_0 >> 2) & 0xf); + *valp = immrx4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_lsi4x4_decode (uint32 *valp) +{ + unsigned lsi4x4_out_0; + unsigned lsi4x4_in_0; + lsi4x4_in_0 = *valp & 0xf; + lsi4x4_out_0 = lsi4x4_in_0 << 2; + *valp = lsi4x4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_lsi4x4_encode (uint32 *valp) +{ + unsigned lsi4x4_in_0; + unsigned lsi4x4_out_0; + lsi4x4_out_0 = *valp; + lsi4x4_in_0 = ((lsi4x4_out_0 >> 2) & 0xf); + *valp = lsi4x4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm7_decode (uint32 *valp) +{ + unsigned simm7_out_0; + unsigned simm7_in_0; + simm7_in_0 = *valp & 0x7f; + simm7_out_0 = ((((-((((simm7_in_0 >> 6) & 1)) & (((simm7_in_0 >> 5) & 1)))) & 0x1ffffff)) << 7) | simm7_in_0; + *valp = simm7_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm7_encode (uint32 *valp) +{ + unsigned simm7_in_0; + unsigned simm7_out_0; + simm7_out_0 = *valp; + simm7_in_0 = (simm7_out_0 & 0x7f); + *valp = simm7_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm6_decode (uint32 *valp) +{ + unsigned uimm6_out_0; + unsigned uimm6_in_0; + uimm6_in_0 = *valp & 0x3f; + uimm6_out_0 = 0x4 + (((0) << 6) | uimm6_in_0); + *valp = uimm6_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm6_encode (uint32 *valp) +{ + unsigned uimm6_in_0; + unsigned uimm6_out_0; + uimm6_out_0 = *valp; + uimm6_in_0 = (uimm6_out_0 - 0x4) & 0x3f; + *valp = uimm6_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_ai4const_decode (uint32 *valp) +{ + unsigned ai4const_out_0; + unsigned ai4const_in_0; + ai4const_in_0 = *valp & 0xf; + ai4const_out_0 = CONST_TBL_ai4c_0[ai4const_in_0 & 0xf]; + *valp = ai4const_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_ai4const_encode (uint32 *valp) +{ + unsigned ai4const_in_0; + unsigned ai4const_out_0; + ai4const_out_0 = *valp; + switch (ai4const_out_0) + { + case 0xffffffff: ai4const_in_0 = 0; break; + case 0x1: ai4const_in_0 = 0x1; break; + case 0x2: ai4const_in_0 = 0x2; break; + case 0x3: ai4const_in_0 = 0x3; break; + case 0x4: ai4const_in_0 = 0x4; break; + case 0x5: ai4const_in_0 = 0x5; break; + case 0x6: ai4const_in_0 = 0x6; break; + case 0x7: ai4const_in_0 = 0x7; break; + case 0x8: ai4const_in_0 = 0x8; break; + case 0x9: ai4const_in_0 = 0x9; break; + case 0xa: ai4const_in_0 = 0xa; break; + case 0xb: ai4const_in_0 = 0xb; break; + case 0xc: ai4const_in_0 = 0xc; break; + case 0xd: ai4const_in_0 = 0xd; break; + case 0xe: ai4const_in_0 = 0xe; break; + default: ai4const_in_0 = 0xf; break; + } + *valp = ai4const_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_b4const_decode (uint32 *valp) +{ + unsigned b4const_out_0; + unsigned b4const_in_0; + b4const_in_0 = *valp & 0xf; + b4const_out_0 = CONST_TBL_b4c_0[b4const_in_0 & 0xf]; + *valp = b4const_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_b4const_encode (uint32 *valp) +{ + unsigned b4const_in_0; + unsigned b4const_out_0; + b4const_out_0 = *valp; + switch (b4const_out_0) + { + case 0xffffffff: b4const_in_0 = 0; break; + case 0x1: b4const_in_0 = 0x1; break; + case 0x2: b4const_in_0 = 0x2; break; + case 0x3: b4const_in_0 = 0x3; break; + case 0x4: b4const_in_0 = 0x4; break; + case 0x5: b4const_in_0 = 0x5; break; + case 0x6: b4const_in_0 = 0x6; break; + case 0x7: b4const_in_0 = 0x7; break; + case 0x8: b4const_in_0 = 0x8; break; + case 0xa: b4const_in_0 = 0x9; break; + case 0xc: b4const_in_0 = 0xa; break; + case 0x10: b4const_in_0 = 0xb; break; + case 0x20: b4const_in_0 = 0xc; break; + case 0x40: b4const_in_0 = 0xd; break; + case 0x80: b4const_in_0 = 0xe; break; + default: b4const_in_0 = 0xf; break; + } + *valp = b4const_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_b4constu_decode (uint32 *valp) +{ + unsigned b4constu_out_0; + unsigned b4constu_in_0; + b4constu_in_0 = *valp & 0xf; + b4constu_out_0 = CONST_TBL_b4cu_0[b4constu_in_0 & 0xf]; + *valp = b4constu_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_b4constu_encode (uint32 *valp) +{ + unsigned b4constu_in_0; + unsigned b4constu_out_0; + b4constu_out_0 = *valp; + switch (b4constu_out_0) + { + case 0x8000: b4constu_in_0 = 0; break; + case 0x10000: b4constu_in_0 = 0x1; break; + case 0x2: b4constu_in_0 = 0x2; break; + case 0x3: b4constu_in_0 = 0x3; break; + case 0x4: b4constu_in_0 = 0x4; break; + case 0x5: b4constu_in_0 = 0x5; break; + case 0x6: b4constu_in_0 = 0x6; break; + case 0x7: b4constu_in_0 = 0x7; break; + case 0x8: b4constu_in_0 = 0x8; break; + case 0xa: b4constu_in_0 = 0x9; break; + case 0xc: b4constu_in_0 = 0xa; break; + case 0x10: b4constu_in_0 = 0xb; break; + case 0x20: b4constu_in_0 = 0xc; break; + case 0x40: b4constu_in_0 = 0xd; break; + case 0x80: b4constu_in_0 = 0xe; break; + default: b4constu_in_0 = 0xf; break; + } + *valp = b4constu_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8_decode (uint32 *valp) +{ + unsigned uimm8_out_0; + unsigned uimm8_in_0; + uimm8_in_0 = *valp & 0xff; + uimm8_out_0 = uimm8_in_0; + *valp = uimm8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8_encode (uint32 *valp) +{ + unsigned uimm8_in_0; + unsigned uimm8_out_0; + uimm8_out_0 = *valp; + uimm8_in_0 = (uimm8_out_0 & 0xff); + *valp = uimm8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8x2_decode (uint32 *valp) +{ + unsigned uimm8x2_out_0; + unsigned uimm8x2_in_0; + uimm8x2_in_0 = *valp & 0xff; + uimm8x2_out_0 = uimm8x2_in_0 << 1; + *valp = uimm8x2_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8x2_encode (uint32 *valp) +{ + unsigned uimm8x2_in_0; + unsigned uimm8x2_out_0; + uimm8x2_out_0 = *valp; + uimm8x2_in_0 = ((uimm8x2_out_0 >> 1) & 0xff); + *valp = uimm8x2_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8x4_decode (uint32 *valp) +{ + unsigned uimm8x4_out_0; + unsigned uimm8x4_in_0; + uimm8x4_in_0 = *valp & 0xff; + uimm8x4_out_0 = uimm8x4_in_0 << 2; + *valp = uimm8x4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm8x4_encode (uint32 *valp) +{ + unsigned uimm8x4_in_0; + unsigned uimm8x4_out_0; + uimm8x4_out_0 = *valp; + uimm8x4_in_0 = ((uimm8x4_out_0 >> 2) & 0xff); + *valp = uimm8x4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm4x16_decode (uint32 *valp) +{ + unsigned uimm4x16_out_0; + unsigned uimm4x16_in_0; + uimm4x16_in_0 = *valp & 0xf; + uimm4x16_out_0 = uimm4x16_in_0 << 4; + *valp = uimm4x16_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm4x16_encode (uint32 *valp) +{ + unsigned uimm4x16_in_0; + unsigned uimm4x16_out_0; + uimm4x16_out_0 = *valp; + uimm4x16_in_0 = ((uimm4x16_out_0 >> 4) & 0xf); + *valp = uimm4x16_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm8_decode (uint32 *valp) +{ + unsigned simm8_out_0; + unsigned simm8_in_0; + simm8_in_0 = *valp & 0xff; + simm8_out_0 = ((int) simm8_in_0 << 24) >> 24; + *valp = simm8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm8_encode (uint32 *valp) +{ + unsigned simm8_in_0; + unsigned simm8_out_0; + simm8_out_0 = *valp; + simm8_in_0 = (simm8_out_0 & 0xff); + *valp = simm8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm8x256_decode (uint32 *valp) +{ + unsigned simm8x256_out_0; + unsigned simm8x256_in_0; + simm8x256_in_0 = *valp & 0xff; + simm8x256_out_0 = (((int) simm8x256_in_0 << 24) >> 24) << 8; + *valp = simm8x256_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm8x256_encode (uint32 *valp) +{ + unsigned simm8x256_in_0; + unsigned simm8x256_out_0; + simm8x256_out_0 = *valp; + simm8x256_in_0 = ((simm8x256_out_0 >> 8) & 0xff); + *valp = simm8x256_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm12b_decode (uint32 *valp) +{ + unsigned simm12b_out_0; + unsigned simm12b_in_0; + simm12b_in_0 = *valp & 0xfff; + simm12b_out_0 = ((int) simm12b_in_0 << 20) >> 20; + *valp = simm12b_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_simm12b_encode (uint32 *valp) +{ + unsigned simm12b_in_0; + unsigned simm12b_out_0; + simm12b_out_0 = *valp; + simm12b_in_0 = (simm12b_out_0 & 0xfff); + *valp = simm12b_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_msalp32_decode (uint32 *valp) +{ + unsigned msalp32_out_0; + unsigned msalp32_in_0; + msalp32_in_0 = *valp & 0x1f; + msalp32_out_0 = 0x20 - msalp32_in_0; + *valp = msalp32_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_msalp32_encode (uint32 *valp) +{ + unsigned msalp32_in_0; + unsigned msalp32_out_0; + msalp32_out_0 = *valp; + msalp32_in_0 = (0x20 - msalp32_out_0) & 0x1f; + *valp = msalp32_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_op2p1_decode (uint32 *valp) +{ + unsigned op2p1_out_0; + unsigned op2p1_in_0; + op2p1_in_0 = *valp & 0xf; + op2p1_out_0 = op2p1_in_0 + 0x1; + *valp = op2p1_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_op2p1_encode (uint32 *valp) +{ + unsigned op2p1_in_0; + unsigned op2p1_out_0; + op2p1_out_0 = *valp; + op2p1_in_0 = (op2p1_out_0 - 0x1) & 0xf; + *valp = op2p1_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_label8_decode (uint32 *valp) +{ + unsigned label8_out_0; + unsigned label8_in_0; + label8_in_0 = *valp & 0xff; + label8_out_0 = 0x4 + (((int) label8_in_0 << 24) >> 24); + *valp = label8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_label8_encode (uint32 *valp) +{ + unsigned label8_in_0; + unsigned label8_out_0; + label8_out_0 = *valp; + label8_in_0 = (label8_out_0 - 0x4) & 0xff; + *valp = label8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_ulabel8_decode (uint32 *valp) +{ + unsigned ulabel8_out_0; + unsigned ulabel8_in_0; + ulabel8_in_0 = *valp & 0xff; + ulabel8_out_0 = 0x4 + (((0) << 8) | ulabel8_in_0); + *valp = ulabel8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_ulabel8_encode (uint32 *valp) +{ + unsigned ulabel8_in_0; + unsigned ulabel8_out_0; + ulabel8_out_0 = *valp; + ulabel8_in_0 = (ulabel8_out_0 - 0x4) & 0xff; + *valp = ulabel8_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_label12_decode (uint32 *valp) +{ + unsigned label12_out_0; + unsigned label12_in_0; + label12_in_0 = *valp & 0xfff; + label12_out_0 = 0x4 + (((int) label12_in_0 << 20) >> 20); + *valp = label12_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_label12_encode (uint32 *valp) +{ + unsigned label12_in_0; + unsigned label12_out_0; + label12_out_0 = *valp; + label12_in_0 = (label12_out_0 - 0x4) & 0xfff; + *valp = label12_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_soffset_decode (uint32 *valp) +{ + unsigned soffset_out_0; + unsigned soffset_in_0; + soffset_in_0 = *valp & 0x3ffff; + soffset_out_0 = 0x4 + (((int) soffset_in_0 << 14) >> 14); + *valp = soffset_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_soffset_encode (uint32 *valp) +{ + unsigned soffset_in_0; + unsigned soffset_out_0; + soffset_out_0 = *valp; + soffset_in_0 = (soffset_out_0 - 0x4) & 0x3ffff; + *valp = soffset_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm16x4_decode (uint32 *valp) +{ + unsigned uimm16x4_out_0; + unsigned uimm16x4_in_0; + uimm16x4_in_0 = *valp & 0xffff; + uimm16x4_out_0 = (((0xffff) << 16) | uimm16x4_in_0) << 2; + *valp = uimm16x4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_uimm16x4_encode (uint32 *valp) +{ + unsigned uimm16x4_in_0; + unsigned uimm16x4_out_0; + uimm16x4_out_0 = *valp; + uimm16x4_in_0 = (uimm16x4_out_0 >> 2) & 0xffff; + *valp = uimm16x4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_bbi_decode (uint32 *valp) +{ + unsigned bbi_out_0; + unsigned bbi_in_0; + bbi_in_0 = *valp & 0x1f; + bbi_out_0 = (0 << 5) | bbi_in_0; + *valp = bbi_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_bbi_encode (uint32 *valp) +{ + unsigned bbi_in_0; + unsigned bbi_out_0; + bbi_out_0 = *valp; + bbi_in_0 = (bbi_out_0 & 0x1f); + *valp = bbi_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_s_decode (uint32 *valp) +{ + unsigned s_out_0; + unsigned s_in_0; + s_in_0 = *valp & 0xf; + s_out_0 = (0 << 4) | s_in_0; + *valp = s_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_s_encode (uint32 *valp) +{ + unsigned s_in_0; + unsigned s_out_0; + s_out_0 = *valp; + s_in_0 = (s_out_0 & 0xf); + *valp = s_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_MR_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_1_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_1_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_2_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_2_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_3_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_3_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_4_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_4_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_MR_5_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_MR_5_encode (uint32 *valp) +{ + int error; + error = (*valp >= 4); + return error; +} + +static int +OperandSem_opnd_sem_immt_decode (uint32 *valp) +{ + unsigned immt_out_0; + unsigned immt_in_0; + immt_in_0 = *valp & 0xf; + immt_out_0 = immt_in_0; + *valp = immt_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_immt_encode (uint32 *valp) +{ + unsigned immt_in_0; + unsigned immt_out_0; + immt_out_0 = *valp; + immt_in_0 = immt_out_0 & 0xf; + *valp = immt_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_BR_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_BR_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16); + return error; +} + +static int +OperandSem_opnd_sem_BR2_decode (uint32 *valp) +{ + *valp = *valp << 1; + return 0; +} + +static int +OperandSem_opnd_sem_BR2_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16) || ((*valp & 1) != 0); + *valp = *valp >> 1; + return error; +} + +static int +OperandSem_opnd_sem_BR4_decode (uint32 *valp) +{ + *valp = *valp << 2; + return 0; +} + +static int +OperandSem_opnd_sem_BR4_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16) || ((*valp & 3) != 0); + *valp = *valp >> 2; + return error; +} + +static int +OperandSem_opnd_sem_BR8_decode (uint32 *valp) +{ + *valp = *valp << 3; + return 0; +} + +static int +OperandSem_opnd_sem_BR8_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16) || ((*valp & 7) != 0); + *valp = *valp >> 3; + return error; +} + +static int +OperandSem_opnd_sem_BR16_decode (uint32 *valp) +{ + *valp = *valp << 4; + return 0; +} + +static int +OperandSem_opnd_sem_BR16_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16) || ((*valp & 15) != 0); + *valp = *valp >> 4; + return error; +} + +static int +OperandSem_opnd_sem_tp7_decode (uint32 *valp) +{ + unsigned tp7_out_0; + unsigned tp7_in_0; + tp7_in_0 = *valp & 0xf; + tp7_out_0 = tp7_in_0 + 0x7; + *valp = tp7_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_tp7_encode (uint32 *valp) +{ + unsigned tp7_in_0; + unsigned tp7_out_0; + tp7_out_0 = *valp; + tp7_in_0 = (tp7_out_0 - 0x7) & 0xf; + *valp = tp7_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_xt_wbr15_label_decode (uint32 *valp) +{ + unsigned xt_wbr15_label_out_0; + unsigned xt_wbr15_label_in_0; + xt_wbr15_label_in_0 = *valp & 0x7fff; + xt_wbr15_label_out_0 = 0x4 + (((int) xt_wbr15_label_in_0 << 17) >> 17); + *valp = xt_wbr15_label_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_xt_wbr15_label_encode (uint32 *valp) +{ + unsigned xt_wbr15_label_in_0; + unsigned xt_wbr15_label_out_0; + xt_wbr15_label_out_0 = *valp; + xt_wbr15_label_in_0 = (xt_wbr15_label_out_0 - 0x4) & 0x7fff; + *valp = xt_wbr15_label_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_dfp_fld_op2_2_decode (uint32 *valp) +{ + unsigned dfp_fld_op2_2_out_0; + unsigned dfp_fld_op2_2_in_0; + dfp_fld_op2_2_in_0 = *valp & 0x1; + dfp_fld_op2_2_out_0 = (0 << 1) | dfp_fld_op2_2_in_0; + *valp = dfp_fld_op2_2_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_dfp_fld_op2_2_encode (uint32 *valp) +{ + unsigned dfp_fld_op2_2_in_0; + unsigned dfp_fld_op2_2_out_0; + dfp_fld_op2_2_out_0 = *valp; + dfp_fld_op2_2_in_0 = (((dfp_fld_op2_2_out_0 >> 0) & 1)) & 0x1; + *valp = dfp_fld_op2_2_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_dfp_fld_op2_1_0_decode (uint32 *valp) +{ + unsigned dfp_fld_op2_1_0_out_0; + unsigned dfp_fld_op2_1_0_in_0; + dfp_fld_op2_1_0_in_0 = *valp & 0x3; + dfp_fld_op2_1_0_out_0 = (0 << 2) | dfp_fld_op2_1_0_in_0; + *valp = dfp_fld_op2_1_0_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_dfp_fld_op2_1_0_encode (uint32 *valp) +{ + unsigned dfp_fld_op2_1_0_in_0; + unsigned dfp_fld_op2_1_0_out_0; + dfp_fld_op2_1_0_out_0 = *valp; + dfp_fld_op2_1_0_in_0 = (dfp_fld_op2_1_0_out_0 & 0x3); + *valp = dfp_fld_op2_1_0_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_FR_decode (uint32 *valp ATTRIBUTE_UNUSED) +{ + return 0; +} + +static int +OperandSem_opnd_sem_FR_encode (uint32 *valp) +{ + int error; + error = (*valp >= 16); + return error; +} + +static int +OperandSem_opnd_sem_imm8x4_decode (uint32 *valp) +{ + unsigned imm8x4_out_0; + unsigned imm8x4_in_0; + imm8x4_in_0 = *valp & 0xff; + imm8x4_out_0 = (0 << 10) | (imm8x4_in_0 << 2) | 0; + *valp = imm8x4_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_imm8x4_encode (uint32 *valp) +{ + unsigned imm8x4_in_0; + unsigned imm8x4_out_0; + imm8x4_out_0 = *valp; + imm8x4_in_0 = ((imm8x4_out_0 >> 2) & 0xff); + *valp = imm8x4_in_0; + return 0; +} + +static int +OperandSem_opnd_sem_imm8x8_decode (uint32 *valp) +{ + unsigned imm8x8_out_0; + unsigned imm8x8_in_0; + imm8x8_in_0 = *valp & 0xff; + imm8x8_out_0 = (0 << 11) | (imm8x8_in_0 << 3) | 0; + *valp = imm8x8_out_0; + return 0; +} + +static int +OperandSem_opnd_sem_imm8x8_encode (uint32 *valp) +{ + unsigned imm8x8_in_0; + unsigned imm8x8_out_0; + imm8x8_out_0 = *valp; + imm8x8_in_0 = ((imm8x8_out_0 >> 3) & 0xff); + *valp = imm8x8_in_0; + return 0; +} + +static int +Operand_soffsetx4_ator (uint32 *valp, uint32 pc) +{ + *valp -= (pc & ~0x3); + return 0; +} + +static int +Operand_soffsetx4_rtoa (uint32 *valp, uint32 pc) +{ + *valp += (pc & ~0x3); + return 0; +} + +static int +Operand_uimm6_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_uimm6_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_label8_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_label8_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_ulabel8_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_ulabel8_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_label12_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_label12_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_soffset_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_soffset_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_uimm16x4_ator (uint32 *valp, uint32 pc) +{ + *valp -= ((pc + 3) & ~0x3); + return 0; +} + +static int +Operand_uimm16x4_rtoa (uint32 *valp, uint32 pc) +{ + *valp += ((pc + 3) & ~0x3); + return 0; +} + +static int +Operand_xt_wbr15_label_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_xt_wbr15_label_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static int +Operand_xt_wbr18_label_ator (uint32 *valp, uint32 pc) +{ + *valp -= pc; + return 0; +} + +static int +Operand_xt_wbr18_label_rtoa (uint32 *valp, uint32 pc) +{ + *valp += pc; + return 0; +} + +static xtensa_operand_internal operands[] = { + { "soffsetx4", FIELD_offset, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_soffsetx4_encode, OperandSem_opnd_sem_soffsetx4_decode, + Operand_soffsetx4_ator, Operand_soffsetx4_rtoa }, + { "uimm12x8", FIELD_imm12, -1, 0, + 0, + OperandSem_opnd_sem_uimm12x8_encode, OperandSem_opnd_sem_uimm12x8_decode, + 0, 0 }, + { "simm4", FIELD_mn, -1, 0, + 0, + OperandSem_opnd_sem_simm4_encode, OperandSem_opnd_sem_simm4_decode, + 0, 0 }, + { "arr", FIELD_r, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_AR_encode, OperandSem_opnd_sem_AR_decode, + 0, 0 }, + { "ars", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_AR_encode, OperandSem_opnd_sem_AR_decode, + 0, 0 }, + { "*ars_invisible", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_encode, OperandSem_opnd_sem_AR_decode, + 0, 0 }, + { "art", FIELD_t, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_AR_encode, OperandSem_opnd_sem_AR_decode, + 0, 0 }, + { "ar0", FIELD__ar0, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_0_encode, OperandSem_opnd_sem_AR_0_decode, + 0, 0 }, + { "ar4", FIELD__ar4, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_1_encode, OperandSem_opnd_sem_AR_1_decode, + 0, 0 }, + { "ar8", FIELD__ar8, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_2_encode, OperandSem_opnd_sem_AR_2_decode, + 0, 0 }, + { "ar12", FIELD__ar12, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_AR_3_encode, OperandSem_opnd_sem_AR_3_decode, + 0, 0 }, + { "ars_entry", FIELD_s, REGFILE_AR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_AR_4_encode, OperandSem_opnd_sem_AR_4_decode, + 0, 0 }, + { "immrx4", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_immrx4_encode, OperandSem_opnd_sem_immrx4_decode, + 0, 0 }, + { "lsi4x4", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_lsi4x4_encode, OperandSem_opnd_sem_lsi4x4_decode, + 0, 0 }, + { "simm7", FIELD_imm7, -1, 0, + 0, + OperandSem_opnd_sem_simm7_encode, OperandSem_opnd_sem_simm7_decode, + 0, 0 }, + { "uimm6", FIELD_imm6, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_uimm6_encode, OperandSem_opnd_sem_uimm6_decode, + Operand_uimm6_ator, Operand_uimm6_rtoa }, + { "ai4const", FIELD_t, -1, 0, + 0, + OperandSem_opnd_sem_ai4const_encode, OperandSem_opnd_sem_ai4const_decode, + 0, 0 }, + { "b4const", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_b4const_encode, OperandSem_opnd_sem_b4const_decode, + 0, 0 }, + { "b4constu", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_b4constu_encode, OperandSem_opnd_sem_b4constu_decode, + 0, 0 }, + { "uimm8", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_uimm8_encode, OperandSem_opnd_sem_uimm8_decode, + 0, 0 }, + { "uimm8x2", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_uimm8x2_encode, OperandSem_opnd_sem_uimm8x2_decode, + 0, 0 }, + { "uimm8x4", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_uimm8x4_encode, OperandSem_opnd_sem_uimm8x4_decode, + 0, 0 }, + { "uimm4x16", FIELD_op2, -1, 0, + 0, + OperandSem_opnd_sem_uimm4x16_encode, OperandSem_opnd_sem_uimm4x16_decode, + 0, 0 }, + { "uimmrx4", FIELD_r, -1, 0, + 0, + OperandSem_opnd_sem_lsi4x4_encode, OperandSem_opnd_sem_lsi4x4_decode, + 0, 0 }, + { "simm8", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_simm8_encode, OperandSem_opnd_sem_simm8_decode, + 0, 0 }, + { "simm8x256", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_simm8x256_encode, OperandSem_opnd_sem_simm8x256_decode, + 0, 0 }, + { "simm12b", FIELD_imm12b, -1, 0, + 0, + OperandSem_opnd_sem_simm12b_encode, OperandSem_opnd_sem_simm12b_decode, + 0, 0 }, + { "msalp32", FIELD_sal, -1, 0, + 0, + OperandSem_opnd_sem_msalp32_encode, OperandSem_opnd_sem_msalp32_decode, + 0, 0 }, + { "op2p1", FIELD_op2, -1, 0, + 0, + OperandSem_opnd_sem_op2p1_encode, OperandSem_opnd_sem_op2p1_decode, + 0, 0 }, + { "label8", FIELD_imm8, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_label8_encode, OperandSem_opnd_sem_label8_decode, + Operand_label8_ator, Operand_label8_rtoa }, + { "ulabel8", FIELD_imm8, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_ulabel8_encode, OperandSem_opnd_sem_ulabel8_decode, + Operand_ulabel8_ator, Operand_ulabel8_rtoa }, + { "label12", FIELD_imm12, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_label12_encode, OperandSem_opnd_sem_label12_decode, + Operand_label12_ator, Operand_label12_rtoa }, + { "soffset", FIELD_offset, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_soffset_encode, OperandSem_opnd_sem_soffset_decode, + Operand_soffset_ator, Operand_soffset_rtoa }, + { "uimm16x4", FIELD_imm16, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_uimm16x4_encode, OperandSem_opnd_sem_uimm16x4_decode, + Operand_uimm16x4_ator, Operand_uimm16x4_rtoa }, + { "bbi", FIELD_bbi, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "sae", FIELD_sae, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "sas", FIELD_sas, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "sargt", FIELD_sargt, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "s", FIELD_s, -1, 0, + 0, + OperandSem_opnd_sem_s_encode, OperandSem_opnd_sem_s_decode, + 0, 0 }, + { "mx", FIELD_x, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_UNKNOWN, + OperandSem_opnd_sem_MR_encode, OperandSem_opnd_sem_MR_decode, + 0, 0 }, + { "my", FIELD_y, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_UNKNOWN, + OperandSem_opnd_sem_MR_0_encode, OperandSem_opnd_sem_MR_0_decode, + 0, 0 }, + { "mw", FIELD_w, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_MR_1_encode, OperandSem_opnd_sem_MR_1_decode, + 0, 0 }, + { "mr0", FIELD__mr0, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_MR_2_encode, OperandSem_opnd_sem_MR_2_decode, + 0, 0 }, + { "mr1", FIELD__mr1, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_MR_3_encode, OperandSem_opnd_sem_MR_3_decode, + 0, 0 }, + { "mr2", FIELD__mr2, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_MR_4_encode, OperandSem_opnd_sem_MR_4_decode, + 0, 0 }, + { "mr3", FIELD__mr3, REGFILE_MR, 1, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_MR_5_encode, OperandSem_opnd_sem_MR_5_decode, + 0, 0 }, + { "immt", FIELD_t, -1, 0, + 0, + OperandSem_opnd_sem_immt_encode, OperandSem_opnd_sem_immt_decode, + 0, 0 }, + { "imms", FIELD_s, -1, 0, + 0, + OperandSem_opnd_sem_immt_encode, OperandSem_opnd_sem_immt_decode, + 0, 0 }, + { "bt", FIELD_t, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR_encode, OperandSem_opnd_sem_BR_decode, + 0, 0 }, + { "bs", FIELD_s, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR_encode, OperandSem_opnd_sem_BR_decode, + 0, 0 }, + { "br", FIELD_r, REGFILE_BR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR_encode, OperandSem_opnd_sem_BR_decode, + 0, 0 }, + { "bt2", FIELD_t2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR2_encode, OperandSem_opnd_sem_BR2_decode, + 0, 0 }, + { "bs2", FIELD_s2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR2_encode, OperandSem_opnd_sem_BR2_decode, + 0, 0 }, + { "br2", FIELD_r2, REGFILE_BR, 2, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR2_encode, OperandSem_opnd_sem_BR2_decode, + 0, 0 }, + { "bt4", FIELD_t4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR4_encode, OperandSem_opnd_sem_BR4_decode, + 0, 0 }, + { "bs4", FIELD_s4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR4_encode, OperandSem_opnd_sem_BR4_decode, + 0, 0 }, + { "br4", FIELD_r4, REGFILE_BR, 4, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR4_encode, OperandSem_opnd_sem_BR4_decode, + 0, 0 }, + { "bt8", FIELD_t8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR8_encode, OperandSem_opnd_sem_BR8_decode, + 0, 0 }, + { "bs8", FIELD_s8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR8_encode, OperandSem_opnd_sem_BR8_decode, + 0, 0 }, + { "br8", FIELD_r8, REGFILE_BR, 8, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR8_encode, OperandSem_opnd_sem_BR8_decode, + 0, 0 }, + { "bt16", FIELD__bt16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR16_encode, OperandSem_opnd_sem_BR16_decode, + 0, 0 }, + { "bs16", FIELD__bs16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR16_encode, OperandSem_opnd_sem_BR16_decode, + 0, 0 }, + { "br16", FIELD__br16, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_BR16_encode, OperandSem_opnd_sem_BR16_decode, + 0, 0 }, + { "brall", FIELD__brall, REGFILE_BR, 16, + XTENSA_OPERAND_IS_REGISTER | XTENSA_OPERAND_IS_INVISIBLE, + OperandSem_opnd_sem_BR16_encode, OperandSem_opnd_sem_BR16_decode, + 0, 0 }, + { "tp7", FIELD_t, -1, 0, + 0, + OperandSem_opnd_sem_tp7_encode, OperandSem_opnd_sem_tp7_decode, + 0, 0 }, + { "xt_wbr15_label", FIELD_xt_wbr15_imm, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_xt_wbr15_label_encode, OperandSem_opnd_sem_xt_wbr15_label_decode, + Operand_xt_wbr15_label_ator, Operand_xt_wbr15_label_rtoa }, + { "xt_wbr18_label", FIELD_xt_wbr18_imm, -1, 0, + XTENSA_OPERAND_IS_PCRELATIVE, + OperandSem_opnd_sem_soffset_encode, OperandSem_opnd_sem_soffset_decode, + Operand_xt_wbr18_label_ator, Operand_xt_wbr18_label_rtoa }, + { "dfp_fld_op2_2", FIELD_dfp_fld_op2_2, -1, 0, + 0, + OperandSem_opnd_sem_dfp_fld_op2_2_encode, OperandSem_opnd_sem_dfp_fld_op2_2_decode, + 0, 0 }, + { "dfp_fld_op2_1_0", FIELD_dfp_fld_op2_1_0, -1, 0, + 0, + OperandSem_opnd_sem_dfp_fld_op2_1_0_encode, OperandSem_opnd_sem_dfp_fld_op2_1_0_decode, + 0, 0 }, + { "dfp_fld_r_0", FIELD_dfp_fld_r_0, -1, 0, + 0, + OperandSem_opnd_sem_dfp_fld_op2_2_encode, OperandSem_opnd_sem_dfp_fld_op2_2_decode, + 0, 0 }, + { "dfp_fld_r_2_1", FIELD_dfp_fld_r_2_1, -1, 0, + 0, + OperandSem_opnd_sem_dfp_fld_op2_1_0_encode, OperandSem_opnd_sem_dfp_fld_op2_1_0_decode, + 0, 0 }, + { "dfp_fld_op2", FIELD_dfp_fld_op2, -1, 0, + 0, + OperandSem_opnd_sem_s_encode, OperandSem_opnd_sem_s_decode, + 0, 0 }, + { "dfp_fld_op2_0", FIELD_dfp_fld_op2_0, -1, 0, + 0, + OperandSem_opnd_sem_dfp_fld_op2_2_encode, OperandSem_opnd_sem_dfp_fld_op2_2_decode, + 0, 0 }, + { "dfp_fld_s_0", FIELD_dfp_fld_s_0, -1, 0, + 0, + OperandSem_opnd_sem_dfp_fld_op2_2_encode, OperandSem_opnd_sem_dfp_fld_op2_2_decode, + 0, 0 }, + { "frr", FIELD_r, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_FR_encode, OperandSem_opnd_sem_FR_decode, + 0, 0 }, + { "frs", FIELD_s, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_FR_encode, OperandSem_opnd_sem_FR_decode, + 0, 0 }, + { "frt", FIELD_t, REGFILE_FR, 1, + XTENSA_OPERAND_IS_REGISTER, + OperandSem_opnd_sem_FR_encode, OperandSem_opnd_sem_FR_decode, + 0, 0 }, + { "imm_t", FIELD_t, -1, 0, + 0, + OperandSem_opnd_sem_s_encode, OperandSem_opnd_sem_s_decode, + 0, 0 }, + { "imm_s", FIELD_s, -1, 0, + 0, + OperandSem_opnd_sem_s_encode, OperandSem_opnd_sem_s_decode, + 0, 0 }, + { "imm8x4", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_imm8x4_encode, OperandSem_opnd_sem_imm8x4_decode, + 0, 0 }, + { "imm8x8", FIELD_imm8, -1, 0, + 0, + OperandSem_opnd_sem_imm8x8_encode, OperandSem_opnd_sem_imm8x8_decode, + 0, 0 }, + { "bitindex", FIELD_bitindex, -1, 0, + 0, + OperandSem_opnd_sem_bbi_encode, OperandSem_opnd_sem_bbi_decode, + 0, 0 }, + { "t", FIELD_t, -1, 0, 0, 0, 0, 0, 0 }, + { "bbi4", FIELD_bbi4, -1, 0, 0, 0, 0, 0, 0 }, + { "imm12", FIELD_imm12, -1, 0, 0, 0, 0, 0, 0 }, + { "imm8", FIELD_imm8, -1, 0, 0, 0, 0, 0, 0 }, + { "imm12b", FIELD_imm12b, -1, 0, 0, 0, 0, 0, 0 }, + { "imm16", FIELD_imm16, -1, 0, 0, 0, 0, 0, 0 }, + { "m", FIELD_m, -1, 0, 0, 0, 0, 0, 0 }, + { "n", FIELD_n, -1, 0, 0, 0, 0, 0, 0 }, + { "offset", FIELD_offset, -1, 0, 0, 0, 0, 0, 0 }, + { "op0", FIELD_op0, -1, 0, 0, 0, 0, 0, 0 }, + { "op1", FIELD_op1, -1, 0, 0, 0, 0, 0, 0 }, + { "op2", FIELD_op2, -1, 0, 0, 0, 0, 0, 0 }, + { "r", FIELD_r, -1, 0, 0, 0, 0, 0, 0 }, + { "sa4", FIELD_sa4, -1, 0, 0, 0, 0, 0, 0 }, + { "sae4", FIELD_sae4, -1, 0, 0, 0, 0, 0, 0 }, + { "sal", FIELD_sal, -1, 0, 0, 0, 0, 0, 0 }, + { "sas4", FIELD_sas4, -1, 0, 0, 0, 0, 0, 0 }, + { "sr", FIELD_sr, -1, 0, 0, 0, 0, 0, 0 }, + { "st", FIELD_st, -1, 0, 0, 0, 0, 0, 0 }, + { "thi3", FIELD_thi3, -1, 0, 0, 0, 0, 0, 0 }, + { "imm4", FIELD_imm4, -1, 0, 0, 0, 0, 0, 0 }, + { "mn", FIELD_mn, -1, 0, 0, 0, 0, 0, 0 }, + { "i", FIELD_i, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6lo", FIELD_imm6lo, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6hi", FIELD_imm6hi, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7lo", FIELD_imm7lo, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7hi", FIELD_imm7hi, -1, 0, 0, 0, 0, 0, 0 }, + { "z", FIELD_z, -1, 0, 0, 0, 0, 0, 0 }, + { "imm6", FIELD_imm6, -1, 0, 0, 0, 0, 0, 0 }, + { "imm7", FIELD_imm7, -1, 0, 0, 0, 0, 0, 0 }, + { "r3", FIELD_r3, -1, 0, 0, 0, 0, 0, 0 }, + { "rbit2", FIELD_rbit2, -1, 0, 0, 0, 0, 0, 0 }, + { "rhi", FIELD_rhi, -1, 0, 0, 0, 0, 0, 0 }, + { "t3", FIELD_t3, -1, 0, 0, 0, 0, 0, 0 }, + { "tbit2", FIELD_tbit2, -1, 0, 0, 0, 0, 0, 0 }, + { "tlo", FIELD_tlo, -1, 0, 0, 0, 0, 0, 0 }, + { "w", FIELD_w, -1, 0, 0, 0, 0, 0, 0 }, + { "y", FIELD_y, -1, 0, 0, 0, 0, 0, 0 }, + { "x", FIELD_x, -1, 0, 0, 0, 0, 0, 0 }, + { "t2", FIELD_t2, -1, 0, 0, 0, 0, 0, 0 }, + { "s2", FIELD_s2, -1, 0, 0, 0, 0, 0, 0 }, + { "r2", FIELD_r2, -1, 0, 0, 0, 0, 0, 0 }, + { "t4", FIELD_t4, -1, 0, 0, 0, 0, 0, 0 }, + { "s4", FIELD_s4, -1, 0, 0, 0, 0, 0, 0 }, + { "r4", FIELD_r4, -1, 0, 0, 0, 0, 0, 0 }, + { "t8", FIELD_t8, -1, 0, 0, 0, 0, 0, 0 }, + { "s8", FIELD_s8, -1, 0, 0, 0, 0, 0, 0 }, + { "r8", FIELD_r8, -1, 0, 0, 0, 0, 0, 0 }, + { "xt_wbr15_imm", FIELD_xt_wbr15_imm, -1, 0, 0, 0, 0, 0, 0 }, + { "xt_wbr18_imm", FIELD_xt_wbr18_imm, -1, 0, 0, 0, 0, 0, 0 }, + { "dfp_fld_op1", FIELD_dfp_fld_op1, -1, 0, 0, 0, 0, 0, 0 }, + { "dfp_fld_r_3", FIELD_dfp_fld_r_3, -1, 0, 0, 0, 0, 0, 0 }, + { "dfp_fld_r_3_1", FIELD_dfp_fld_r_3_1, -1, 0, 0, 0, 0, 0, 0 }, + { "dfp_fld_s_3_1", FIELD_dfp_fld_s_3_1, -1, 0, 0, 0, 0, 0, 0 }, + { "dfp_fld_op2_3", FIELD_dfp_fld_op2_3, -1, 0, 0, 0, 0, 0, 0 }, + { "dfp_fld_op2_3_2", FIELD_dfp_fld_op2_3_2, -1, 0, 0, 0, 0, 0, 0 }, + { "dfp_fld_op2_3_1", FIELD_dfp_fld_op2_3_1, -1, 0, 0, 0, 0, 0, 0 }, + { "s3to1", FIELD_s3to1, -1, 0, 0, 0, 0, 0, 0 } +}; + +enum xtensa_operand_id { + OPERAND_soffsetx4, + OPERAND_uimm12x8, + OPERAND_simm4, + OPERAND_arr, + OPERAND_ars, + OPERAND__ars_invisible, + OPERAND_art, + OPERAND_ar0, + OPERAND_ar4, + OPERAND_ar8, + OPERAND_ar12, + OPERAND_ars_entry, + OPERAND_immrx4, + OPERAND_lsi4x4, + OPERAND_simm7, + OPERAND_uimm6, + OPERAND_ai4const, + OPERAND_b4const, + OPERAND_b4constu, + OPERAND_uimm8, + OPERAND_uimm8x2, + OPERAND_uimm8x4, + OPERAND_uimm4x16, + OPERAND_uimmrx4, + OPERAND_simm8, + OPERAND_simm8x256, + OPERAND_simm12b, + OPERAND_msalp32, + OPERAND_op2p1, + OPERAND_label8, + OPERAND_ulabel8, + OPERAND_label12, + OPERAND_soffset, + OPERAND_uimm16x4, + OPERAND_bbi, + OPERAND_sae, + OPERAND_sas, + OPERAND_sargt, + OPERAND_s, + OPERAND_mx, + OPERAND_my, + OPERAND_mw, + OPERAND_mr0, + OPERAND_mr1, + OPERAND_mr2, + OPERAND_mr3, + OPERAND_immt, + OPERAND_imms, + OPERAND_bt, + OPERAND_bs, + OPERAND_br, + OPERAND_bt2, + OPERAND_bs2, + OPERAND_br2, + OPERAND_bt4, + OPERAND_bs4, + OPERAND_br4, + OPERAND_bt8, + OPERAND_bs8, + OPERAND_br8, + OPERAND_bt16, + OPERAND_bs16, + OPERAND_br16, + OPERAND_brall, + OPERAND_tp7, + OPERAND_xt_wbr15_label, + OPERAND_xt_wbr18_label, + OPERAND_dfp_fld_op2_2, + OPERAND_dfp_fld_op2_1_0, + OPERAND_dfp_fld_r_0, + OPERAND_dfp_fld_r_2_1, + OPERAND_dfp_fld_op2, + OPERAND_dfp_fld_op2_0, + OPERAND_dfp_fld_s_0, + OPERAND_frr, + OPERAND_frs, + OPERAND_frt, + OPERAND_imm_t, + OPERAND_imm_s, + OPERAND_imm8x4, + OPERAND_imm8x8, + OPERAND_bitindex, + OPERAND_t, + OPERAND_bbi4, + OPERAND_imm12, + OPERAND_imm8, + OPERAND_imm12b, + OPERAND_imm16, + OPERAND_m, + OPERAND_n, + OPERAND_offset, + OPERAND_op0, + OPERAND_op1, + OPERAND_op2, + OPERAND_r, + OPERAND_sa4, + OPERAND_sae4, + OPERAND_sal, + OPERAND_sas4, + OPERAND_sr, + OPERAND_st, + OPERAND_thi3, + OPERAND_imm4, + OPERAND_mn, + OPERAND_i, + OPERAND_imm6lo, + OPERAND_imm6hi, + OPERAND_imm7lo, + OPERAND_imm7hi, + OPERAND_z, + OPERAND_imm6, + OPERAND_imm7, + OPERAND_r3, + OPERAND_rbit2, + OPERAND_rhi, + OPERAND_t3, + OPERAND_tbit2, + OPERAND_tlo, + OPERAND_w, + OPERAND_y, + OPERAND_x, + OPERAND_t2, + OPERAND_s2, + OPERAND_r2, + OPERAND_t4, + OPERAND_s4, + OPERAND_r4, + OPERAND_t8, + OPERAND_s8, + OPERAND_r8, + OPERAND_xt_wbr15_imm, + OPERAND_xt_wbr18_imm, + OPERAND_dfp_fld_op1, + OPERAND_dfp_fld_r_3, + OPERAND_dfp_fld_r_3_1, + OPERAND_dfp_fld_s_3_1, + OPERAND_dfp_fld_op2_3, + OPERAND_dfp_fld_op2_3_2, + OPERAND_dfp_fld_op2_3_1, + OPERAND_s3to1 +}; + + +/* Iclass table. */ + +static xtensa_arg_internal Iclass_LSI_args[] = { + { { OPERAND_frt }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSI_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSIP_args[] = { + { { OPERAND_frt }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_imm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSIP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSX_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSX_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSXP_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_LSXP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSI_args[] = { + { { OPERAND_frt }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSI_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSIP_args[] = { + { { OPERAND_frt }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_imm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSIP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSX_args[] = { + { { OPERAND_frr }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSX_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSXP_args[] = { + { { OPERAND_frr }, 'i' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_SSXP_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ABS_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ABS_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEG_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEG_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOV_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOV_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVEQZ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVEQZ_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVNEZ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVNEZ_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVLTZ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVLTZ_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVGEZ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVGEZ_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVF_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVF_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVT_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MOVT_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_WFR_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_WFR_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RFR_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RFR_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ROUND_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_ROUND_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_CEIL_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_CEIL_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOOR_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOOR_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_TRUNC_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_TRUNC_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UTRUNC_S_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_UTRUNC_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOAT_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_FLOAT_S_stateArgs[] = { + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UFLOAT_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_imm_t }, 'i' } +}; + +static xtensa_arg_internal Iclass_UFLOAT_S_stateArgs[] = { + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UN_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_UN_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULT_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULT_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULE_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ULE_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_UEQ_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_UEQ_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLT_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLT_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLE_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OLE_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_OEQ_S_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_OEQ_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADD_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADD_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SUB_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_SUB_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MUL_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MUL_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADD_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADD_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MSUB_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MSUB_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_SQRT0_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_SQRT0_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIV0_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIV0_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RECIP0_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RECIP0_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_RSQRT0_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_RSQRT0_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADDN_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_MADDN_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIVN_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' }, + { { OPERAND_frt }, 'i' } +}; + +static xtensa_arg_internal Iclass_DIVN_S_stateArgs[] = { + { { STATE_OverflowFlag }, 'm' }, + { { STATE_UnderflowFlag }, 'm' }, + { { STATE_InexactFlag }, 'm' }, + { { STATE_RoundMode }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_CONST_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_imm_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_CONST_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEXP01_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_NEXP01_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXP_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXP_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXPM_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_ADDEXPM_S_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKDADJ_S_args[] = { + { { OPERAND_frr }, 'm' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKDADJ_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_DivZeroFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKSADJ_S_args[] = { + { { OPERAND_frr }, 'o' }, + { { OPERAND_frs }, 'i' } +}; + +static xtensa_arg_internal Iclass_MKSADJ_S_stateArgs[] = { + { { STATE_InvalidFlag }, 'm' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfe_stateArgs[] = { + { { STATE_PSEXCM }, 'o' }, + { { STATE_EPC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfde_stateArgs[] = { + { { STATE_DEPC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call12_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar12 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call12_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call8_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar8 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call8_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call4_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call4_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx12_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar12 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx12_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar8 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx8_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx4_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx4_stateArgs[] = { + { { STATE_PSCALLINC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_entry_args[] = { + { { OPERAND_ars_entry }, 's' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm12x8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_entry_stateArgs[] = { + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSWOE }, 'i' }, + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movsp_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movsp_stateArgs[] = { + { { STATE_WindowBase }, 'i' }, + { { STATE_WindowStart }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rotw_args[] = { + { { OPERAND_simm4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rotw_stateArgs[] = { + { { STATE_WindowBase }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retw_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retw_stateArgs[] = { + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSWOE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfwou_stateArgs[] = { + { { STATE_EPC1 }, 'i' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_WindowBase }, 'm' }, + { { STATE_WindowStart }, 'm' }, + { { STATE_PSOWB }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32e_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_immrx4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32e_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_immrx4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowbase_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowbase_stateArgs[] = { + { { STATE_WindowBase }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowbase_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowbase_stateArgs[] = { + { { STATE_WindowBase }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowbase_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowbase_stateArgs[] = { + { { STATE_WindowBase }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowstart_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_windowstart_stateArgs[] = { + { { STATE_WindowStart }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowstart_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_windowstart_stateArgs[] = { + { { STATE_WindowStart }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowstart_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_windowstart_stateArgs[] = { + { { STATE_WindowStart }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_add_n_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addi_n_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_ai4const }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bz6_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loadi4_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_lsi4x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mov_n_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movi_n_args[] = { + { { OPERAND_ars }, 'o' }, + { { OPERAND_simm7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_retn_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_storei4_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_lsi4x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_threadptr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_threadptr_stateArgs[] = { + { { STATE_THREADPTR }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_threadptr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_threadptr_stateArgs[] = { + { { STATE_THREADPTR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_simm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addmi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_simm8x256 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_addsub_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bit_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_b4const }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8b_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_bbi }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsi8u_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_b4constu }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bst8_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bsz12_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_label12 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_call0_args[] = { + { { OPERAND_soffsetx4 }, 'i' }, + { { OPERAND_ar0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_callx0_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ar0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_exti_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_sae }, 'i' }, + { { OPERAND_op2p1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_jump_args[] = { + { { OPERAND_soffset }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_jumpx_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l16ui_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l16si_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32i_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32r_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_uimm16x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l8i_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loop_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ulabel8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loop_stateArgs[] = { + { { STATE_LBEG }, 'o' }, + { { STATE_LEND }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loopz_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_ulabel8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_loopz_stateArgs[] = { + { { STATE_LBEG }, 'o' }, + { { STATE_LEND }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movi_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_simm12b }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_movz_args[] = { + { { OPERAND_arr }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_neg_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_return_args[] = { + { { OPERAND__ars_invisible }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s16i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32nb_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimmrx4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s8i_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sar_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sar_stateArgs[] = { + { { STATE_SAR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sari_args[] = { + { { OPERAND_sas }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sari_stateArgs[] = { + { { STATE_SAR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shifts_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shifts_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftst_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftst_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftt_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_shiftt_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_slli_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_msalp32 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_srai_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_sargt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_srli_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sync_stateArgs[] = { + { { STATE_XTSYNC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsil_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsil_stateArgs[] = { + { { STATE_PSWOE }, 'i' }, + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSOWB }, 'i' }, + { { STATE_PSUM }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lend_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lend_stateArgs[] = { + { { STATE_LEND }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lend_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lend_stateArgs[] = { + { { STATE_LEND }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lend_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lend_stateArgs[] = { + { { STATE_LEND }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lcount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lcount_stateArgs[] = { + { { STATE_LCOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lcount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lcount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_LCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lcount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lcount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_LCOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lbeg_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lbeg_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lbeg_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_lbeg_stateArgs[] = { + { { STATE_LBEG }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_sar_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_sar_stateArgs[] = { + { { STATE_SAR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_sar_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_sar_stateArgs[] = { + { { STATE_SAR }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_sar_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_sar_stateArgs[] = { + { { STATE_SAR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_memctl_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_memctl_stateArgs[] = { + { { STATE_MEMCTL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_memctl_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_memctl_stateArgs[] = { + { { STATE_MEMCTL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_memctl_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_memctl_stateArgs[] = { + { { STATE_MEMCTL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_litbase_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_litbase_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_litbase_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_configid0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_configid0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_configid1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ps_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'i' }, + { { STATE_PSCALLINC }, 'i' }, + { { STATE_PSOWB }, 'i' }, + { { STATE_PSUM }, 'i' }, + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ps_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_PSINTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ps_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ps_stateArgs[] = { + { { STATE_PSWOE }, 'm' }, + { { STATE_PSCALLINC }, 'm' }, + { { STATE_PSOWB }, 'm' }, + { { STATE_PSUM }, 'm' }, + { { STATE_PSEXCM }, 'm' }, + { { STATE_PSINTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc1_stateArgs[] = { + { { STATE_EPC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc1_stateArgs[] = { + { { STATE_EPC1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc1_stateArgs[] = { + { { STATE_EPC1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave1_stateArgs[] = { + { { STATE_EXCSAVE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave1_stateArgs[] = { + { { STATE_EXCSAVE1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave1_stateArgs[] = { + { { STATE_EXCSAVE1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc2_stateArgs[] = { + { { STATE_EPC2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc2_stateArgs[] = { + { { STATE_EPC2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc2_stateArgs[] = { + { { STATE_EPC2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave2_stateArgs[] = { + { { STATE_EXCSAVE2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave2_stateArgs[] = { + { { STATE_EXCSAVE2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave2_stateArgs[] = { + { { STATE_EXCSAVE2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc3_stateArgs[] = { + { { STATE_EPC3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc3_stateArgs[] = { + { { STATE_EPC3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc3_stateArgs[] = { + { { STATE_EPC3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave3_stateArgs[] = { + { { STATE_EXCSAVE3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave3_stateArgs[] = { + { { STATE_EXCSAVE3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave3_stateArgs[] = { + { { STATE_EXCSAVE3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc4_stateArgs[] = { + { { STATE_EPC4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc4_stateArgs[] = { + { { STATE_EPC4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc4_stateArgs[] = { + { { STATE_EPC4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave4_stateArgs[] = { + { { STATE_EXCSAVE4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave4_stateArgs[] = { + { { STATE_EXCSAVE4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave4_stateArgs[] = { + { { STATE_EXCSAVE4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc5_stateArgs[] = { + { { STATE_EPC5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc5_stateArgs[] = { + { { STATE_EPC5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc5_stateArgs[] = { + { { STATE_EPC5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave5_stateArgs[] = { + { { STATE_EXCSAVE5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave5_stateArgs[] = { + { { STATE_EXCSAVE5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave5_stateArgs[] = { + { { STATE_EXCSAVE5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc6_stateArgs[] = { + { { STATE_EPC6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc6_stateArgs[] = { + { { STATE_EPC6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc6_stateArgs[] = { + { { STATE_EPC6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave6_stateArgs[] = { + { { STATE_EXCSAVE6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave6_stateArgs[] = { + { { STATE_EXCSAVE6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave6_stateArgs[] = { + { { STATE_EXCSAVE6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc7_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_epc7_stateArgs[] = { + { { STATE_EPC7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc7_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_epc7_stateArgs[] = { + { { STATE_EPC7 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc7_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_epc7_stateArgs[] = { + { { STATE_EPC7 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave7_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excsave7_stateArgs[] = { + { { STATE_EXCSAVE7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave7_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excsave7_stateArgs[] = { + { { STATE_EXCSAVE7 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave7_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excsave7_stateArgs[] = { + { { STATE_EXCSAVE7 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps2_stateArgs[] = { + { { STATE_EPS2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps2_stateArgs[] = { + { { STATE_EPS2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps2_stateArgs[] = { + { { STATE_EPS2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps3_stateArgs[] = { + { { STATE_EPS3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps3_stateArgs[] = { + { { STATE_EPS3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps3_stateArgs[] = { + { { STATE_EPS3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps4_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps4_stateArgs[] = { + { { STATE_EPS4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps4_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps4_stateArgs[] = { + { { STATE_EPS4 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps4_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps4_stateArgs[] = { + { { STATE_EPS4 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps5_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps5_stateArgs[] = { + { { STATE_EPS5 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps5_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps5_stateArgs[] = { + { { STATE_EPS5 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps5_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps5_stateArgs[] = { + { { STATE_EPS5 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps6_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps6_stateArgs[] = { + { { STATE_EPS6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps6_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps6_stateArgs[] = { + { { STATE_EPS6 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps6_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps6_stateArgs[] = { + { { STATE_EPS6 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps7_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_eps7_stateArgs[] = { + { { STATE_EPS7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps7_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_eps7_stateArgs[] = { + { { STATE_EPS7 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps7_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_eps7_stateArgs[] = { + { { STATE_EPS7 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excvaddr_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_excvaddr_stateArgs[] = { + { { STATE_EXCVADDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excvaddr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_excvaddr_stateArgs[] = { + { { STATE_EXCVADDR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excvaddr_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_excvaddr_stateArgs[] = { + { { STATE_EXCVADDR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_depc_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_depc_stateArgs[] = { + { { STATE_DEPC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_depc_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_depc_stateArgs[] = { + { { STATE_DEPC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_depc_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_depc_stateArgs[] = { + { { STATE_DEPC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_exccause_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_exccause_stateArgs[] = { + { { STATE_EXCCAUSE }, 'i' }, + { { STATE_XTSYNC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_exccause_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_exccause_stateArgs[] = { + { { STATE_EXCCAUSE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_exccause_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_exccause_stateArgs[] = { + { { STATE_EXCCAUSE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc0_stateArgs[] = { + { { STATE_MISC0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc0_stateArgs[] = { + { { STATE_MISC0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc0_stateArgs[] = { + { { STATE_MISC0 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc1_stateArgs[] = { + { { STATE_MISC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc1_stateArgs[] = { + { { STATE_MISC1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc1_stateArgs[] = { + { { STATE_MISC1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc2_stateArgs[] = { + { { STATE_MISC2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc2_stateArgs[] = { + { { STATE_MISC2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc2_stateArgs[] = { + { { STATE_MISC2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc3_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_misc3_stateArgs[] = { + { { STATE_MISC3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc3_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_misc3_stateArgs[] = { + { { STATE_MISC3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc3_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_misc3_stateArgs[] = { + { { STATE_MISC3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_prid_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_vecbase_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_vecbase_stateArgs[] = { + { { STATE_VECBASE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_vecbase_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_vecbase_stateArgs[] = { + { { STATE_VECBASE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_vecbase_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_vecbase_stateArgs[] = { + { { STATE_VECBASE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_mul16_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_mul32_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_mul32h_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_aa_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_aa_stateArgs[] = { + { { STATE_ACC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_ad_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_ad_stateArgs[] = { + { { STATE_ACC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_da_args[] = { + { { OPERAND_mx }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_da_stateArgs[] = { + { { STATE_ACC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_dd_args[] = { + { { OPERAND_mx }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_dd_stateArgs[] = { + { { STATE_ACC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_aa_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_aa_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_ad_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_ad_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_da_args[] = { + { { OPERAND_mx }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_da_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_dd_args[] = { + { { OPERAND_mx }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16a_dd_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16al_da_args[] = { + { { OPERAND_mw }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_mx }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16al_da_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16al_dd_args[] = { + { { OPERAND_mw }, 'o' }, + { { OPERAND_ars }, 'm' }, + { { OPERAND_mx }, 'i' }, + { { OPERAND_my }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16al_dd_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_mac16_l_args[] = { + { { OPERAND_mw }, 'o' }, + { { OPERAND_ars }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_m0_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_mr0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_m0_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_mr0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_m0_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_mr0 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_m1_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_mr1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_m1_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_mr1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_m1_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_mr1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_m2_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_mr2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_m2_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_mr2 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_m2_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_mr2 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_m3_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_mr3 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_m3_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_mr3 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_m3_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_mr3 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_acclo_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_acclo_stateArgs[] = { + { { STATE_ACC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_acclo_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_acclo_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_acclo_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_acclo_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_acchi_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_acchi_stateArgs[] = { + { { STATE_ACC }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_acchi_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_acchi_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_acchi_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_acchi_stateArgs[] = { + { { STATE_ACC }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfi_args[] = { + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfi_stateArgs[] = { + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_PSINTLEVEL }, 'o' }, + { { STATE_EPC1 }, 'i' }, + { { STATE_EPC2 }, 'i' }, + { { STATE_EPC3 }, 'i' }, + { { STATE_EPC4 }, 'i' }, + { { STATE_EPC5 }, 'i' }, + { { STATE_EPC6 }, 'i' }, + { { STATE_EPC7 }, 'i' }, + { { STATE_EPS2 }, 'i' }, + { { STATE_EPS3 }, 'i' }, + { { STATE_EPS4 }, 'i' }, + { { STATE_EPS5 }, 'i' }, + { { STATE_EPS6 }, 'i' }, + { { STATE_EPS7 }, 'i' }, + { { STATE_InOCDMode }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wait_args[] = { + { { OPERAND_s }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wait_stateArgs[] = { + { { STATE_PSINTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_interrupt_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_interrupt_stateArgs[] = { + { { STATE_INTERRUPT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intset_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intset_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intclear_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intclear_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_intenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_intenable_stateArgs[] = { + { { STATE_INTENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_intenable_stateArgs[] = { + { { STATE_INTENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_intenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_intenable_stateArgs[] = { + { { STATE_INTENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_args[] = { + { { OPERAND_imms }, 'i' }, + { { OPERAND_immt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_n_args[] = { + { { OPERAND_imms }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_break_n_stateArgs[] = { + { { STATE_PSEXCM }, 'i' }, + { { STATE_PSINTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka0_stateArgs[] = { + { { STATE_DBREAKA0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka0_stateArgs[] = { + { { STATE_DBREAKA0 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka0_stateArgs[] = { + { { STATE_DBREAKA0 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc0_stateArgs[] = { + { { STATE_DBREAKC0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc0_stateArgs[] = { + { { STATE_DBREAKC0 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc0_stateArgs[] = { + { { STATE_DBREAKC0 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreaka1_stateArgs[] = { + { { STATE_DBREAKA1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreaka1_stateArgs[] = { + { { STATE_DBREAKA1 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreaka1_stateArgs[] = { + { { STATE_DBREAKA1 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_dbreakc1_stateArgs[] = { + { { STATE_DBREAKC1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_dbreakc1_stateArgs[] = { + { { STATE_DBREAKC1 }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_dbreakc1_stateArgs[] = { + { { STATE_DBREAKC1 }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka0_stateArgs[] = { + { { STATE_IBREAKA0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka0_stateArgs[] = { + { { STATE_IBREAKA0 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka0_stateArgs[] = { + { { STATE_IBREAKA0 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreaka1_stateArgs[] = { + { { STATE_IBREAKA1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreaka1_stateArgs[] = { + { { STATE_IBREAKA1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreaka1_stateArgs[] = { + { { STATE_IBREAKA1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreakenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ibreakenable_stateArgs[] = { + { { STATE_IBREAKENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreakenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ibreakenable_stateArgs[] = { + { { STATE_IBREAKENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreakenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ibreakenable_stateArgs[] = { + { { STATE_IBREAKENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_debugcause_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_debugcause_stateArgs[] = { + { { STATE_DEBUGCAUSE }, 'i' }, + { { STATE_DBNUM }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_debugcause_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_debugcause_stateArgs[] = { + { { STATE_DEBUGCAUSE }, 'o' }, + { { STATE_DBNUM }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_debugcause_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_debugcause_stateArgs[] = { + { { STATE_DEBUGCAUSE }, 'm' }, + { { STATE_DBNUM }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icount_stateArgs[] = { + { { STATE_ICOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_ICOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_ICOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icountlevel_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_icountlevel_stateArgs[] = { + { { STATE_ICOUNTLEVEL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icountlevel_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_icountlevel_stateArgs[] = { + { { STATE_ICOUNTLEVEL }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icountlevel_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_icountlevel_stateArgs[] = { + { { STATE_ICOUNTLEVEL }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ddr_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ddr_stateArgs[] = { + { { STATE_DDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ddr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ddr_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_DDR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ddr_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ddr_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_DDR }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_lddr32_p_args[] = { + { { OPERAND_ars }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_lddr32_p_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_InOCDMode }, 'i' }, + { { STATE_DDR }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sddr32_p_args[] = { + { { OPERAND_ars }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sddr32_p_stateArgs[] = { + { { STATE_InOCDMode }, 'i' }, + { { STATE_DDR }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdo_args[] = { + { { OPERAND_imms }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdo_stateArgs[] = { + { { STATE_InOCDMode }, 'm' }, + { { STATE_EPC6 }, 'i' }, + { { STATE_PSWOE }, 'o' }, + { { STATE_PSCALLINC }, 'o' }, + { { STATE_PSOWB }, 'o' }, + { { STATE_PSUM }, 'o' }, + { { STATE_PSEXCM }, 'o' }, + { { STATE_PSINTLEVEL }, 'o' }, + { { STATE_EPS6 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rfdd_stateArgs[] = { + { { STATE_InOCDMode }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_mmid_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_mmid_stateArgs[] = { + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool1_args[] = { + { { OPERAND_br }, 'o' }, + { { OPERAND_bs }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool4_args[] = { + { { OPERAND_bt }, 'o' }, + { { OPERAND_bs4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbool8_args[] = { + { { OPERAND_bt }, 'o' }, + { { OPERAND_bs8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bbranch_args[] = { + { { OPERAND_bs }, 'i' }, + { { OPERAND_label8 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_bmove_args[] = { + { { OPERAND_arr }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_bt }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_RSR_BR_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_brall }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_WSR_BR_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_brall }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_XSR_BR_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_brall }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccount_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccount_stateArgs[] = { + { { STATE_CCOUNT }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccount_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_CCOUNT }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccount_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccount_stateArgs[] = { + { { STATE_XTSYNC }, 'o' }, + { { STATE_CCOUNT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare0_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare0_stateArgs[] = { + { { STATE_CCOMPARE0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare0_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare0_stateArgs[] = { + { { STATE_CCOMPARE0 }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare0_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare0_stateArgs[] = { + { { STATE_CCOMPARE0 }, 'm' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare1_stateArgs[] = { + { { STATE_CCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare1_stateArgs[] = { + { { STATE_CCOMPARE1 }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare1_stateArgs[] = { + { { STATE_CCOMPARE1 }, 'm' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare2_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_ccompare2_stateArgs[] = { + { { STATE_CCOMPARE2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare2_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_ccompare2_stateArgs[] = { + { { STATE_CCOMPARE2 }, 'o' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare2_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_ccompare2_stateArgs[] = { + { { STATE_CCOMPARE2 }, 'm' }, + { { STATE_INTERRUPT }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_idtlb_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_idtlb_stateArgs[] = { + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rdtlb_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wdtlb_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wdtlb_stateArgs[] = { + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_iitlb_args[] = { + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_ritlb_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_witlb_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_cpenable_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_cpenable_stateArgs[] = { + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_cpenable_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_cpenable_stateArgs[] = { + { { STATE_CPENABLE }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_cpenable_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_cpenable_stateArgs[] = { + { { STATE_CPENABLE }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_clamp_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_tp7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_minmax_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_nsa_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_sx_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_tp7 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_l32ai_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32ri_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32c1i_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_uimm8x4 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_s32c1i_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'i' }, + { { STATE_XTSYNC }, 'i' }, + { { STATE_SCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_scompare1_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_scompare1_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_scompare1_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_scompare1_stateArgs[] = { + { { STATE_SCOMPARE1 }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_atomctl_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rsr_atomctl_stateArgs[] = { + { { STATE_ATOMCTL }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_atomctl_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wsr_atomctl_stateArgs[] = { + { { STATE_ATOMCTL }, 'o' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_atomctl_args[] = { + { { OPERAND_art }, 'm' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_xsr_atomctl_stateArgs[] = { + { { STATE_ATOMCTL }, 'm' }, + { { STATE_XTSYNC }, 'o' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_div_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rer_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_rer_stateArgs[] = { + { { STATE_ERI_RAW_INTERLOCK }, 'i' } +}; + +static xtensa_interface Iclass_xt_iclass_rer_intfArgs[] = { + INTERFACE_ERI_RD_In, + INTERFACE_ERI_RD_Out +}; + +static xtensa_arg_internal Iclass_xt_iclass_wer_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_xt_iclass_wer_stateArgs[] = { + { { STATE_ERI_RAW_INTERLOCK }, 'o' } +}; + +static xtensa_interface Iclass_xt_iclass_wer_intfArgs[] = { + INTERFACE_ERI_WR_In, + INTERFACE_ERI_WR_Out +}; + +static xtensa_arg_internal Iclass_iclass_F64ITER_args[] = { + { { OPERAND_arr }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dfp_fld_op2_1_0 }, 'i' }, + { { OPERAND_dfp_fld_op2_2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_F64ITER_stateArgs[] = { + { { STATE_F64R }, 'm' }, + { { STATE_F64S }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_F64RND_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dfp_fld_op2_1_0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_F64RND_stateArgs[] = { + { { STATE_F64R }, 'm' }, + { { STATE_F64S }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_F64ADDC_F64SUBC_args[] = { + { { OPERAND_art }, 'm' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_dfp_fld_r_2_1 }, 'i' }, + { { OPERAND_dfp_fld_r_0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_F64ADDC_F64SUBC_stateArgs[] = { + { { STATE_F64S }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_F64SIG_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_F64CMPL_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_F64CMPL_stateArgs[] = { + { { STATE_F64S }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_F64CMPH_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dfp_fld_op2 }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_F64CMPH_stateArgs[] = { + { { STATE_SAR }, 'o' }, + { { STATE_F64R }, 'o' }, + { { STATE_F64S }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_F64NORM_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dfp_fld_op2_0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_F64NORM_stateArgs[] = { + { { STATE_SAR }, 'o' }, + { { STATE_F64S }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_F64SEXP_args[] = { + { { OPERAND_arr }, 'o' }, + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RF64R_args[] = { + { { OPERAND_art }, 'o' }, + { { OPERAND_dfp_fld_s_0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_RF64R_stateArgs[] = { + { { STATE_F64R }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_WF64R_args[] = { + { { OPERAND_ars }, 'i' }, + { { OPERAND_art }, 'i' }, + { { OPERAND_dfp_fld_r_0 }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_WF64R_stateArgs[] = { + { { STATE_F64R }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_f64r_lo_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_f64r_lo_stateArgs[] = { + { { STATE_F64R }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_f64r_lo_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_f64r_lo_stateArgs[] = { + { { STATE_F64R }, 'm' } +}; + +static xtensa_arg_internal Iclass_rur_f64r_hi_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_f64r_hi_stateArgs[] = { + { { STATE_F64R }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_f64r_hi_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_f64r_hi_stateArgs[] = { + { { STATE_F64R }, 'm' } +}; + +static xtensa_arg_internal Iclass_rur_f64s_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_f64s_stateArgs[] = { + { { STATE_F64S }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_f64s_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_f64s_stateArgs[] = { + { { STATE_F64S }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_fcr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_fcr_stateArgs[] = { + { { STATE_RoundMode }, 'i' }, + { { STATE_InvalidEnable }, 'i' }, + { { STATE_DivZeroEnable }, 'i' }, + { { STATE_OverflowEnable }, 'i' }, + { { STATE_UnderflowEnable }, 'i' }, + { { STATE_InexactEnable }, 'i' }, + { { STATE_FPreserved20 }, 'i' }, + { { STATE_FPreserved5 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fcr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fcr_stateArgs[] = { + { { STATE_RoundMode }, 'o' }, + { { STATE_InvalidEnable }, 'o' }, + { { STATE_DivZeroEnable }, 'o' }, + { { STATE_OverflowEnable }, 'o' }, + { { STATE_UnderflowEnable }, 'o' }, + { { STATE_InexactEnable }, 'o' }, + { { STATE_FPreserved20 }, 'o' }, + { { STATE_FPreserved5 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_fsr_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_fsr_stateArgs[] = { + { { STATE_InvalidFlag }, 'i' }, + { { STATE_DivZeroFlag }, 'i' }, + { { STATE_OverflowFlag }, 'i' }, + { { STATE_UnderflowFlag }, 'i' }, + { { STATE_InexactFlag }, 'i' }, + { { STATE_FPreserved20a }, 'i' }, + { { STATE_FPreserved7 }, 'i' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fsr_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_fsr_stateArgs[] = { + { { STATE_InvalidFlag }, 'o' }, + { { STATE_DivZeroFlag }, 'o' }, + { { STATE_OverflowFlag }, 'o' }, + { { STATE_UnderflowFlag }, 'o' }, + { { STATE_InexactFlag }, 'o' }, + { { STATE_FPreserved20a }, 'o' }, + { { STATE_FPreserved7 }, 'o' }, + { { STATE_CPENABLE }, 'i' } +}; + +static xtensa_arg_internal Iclass_rur_expstate_args[] = { + { { OPERAND_arr }, 'o' } +}; + +static xtensa_arg_internal Iclass_rur_expstate_stateArgs[] = { + { { STATE_EXPSTATE }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_expstate_args[] = { + { { OPERAND_art }, 'i' } +}; + +static xtensa_arg_internal Iclass_wur_expstate_stateArgs[] = { + { { STATE_EXPSTATE }, 'o' } +}; + +static xtensa_arg_internal Iclass_iclass_READ_IMPWIRE_args[] = { + { { OPERAND_art }, 'o' } +}; + +static xtensa_interface Iclass_iclass_READ_IMPWIRE_intfArgs[] = { + INTERFACE_IMPWIRE +}; + +static xtensa_arg_internal Iclass_iclass_SETB_EXPSTATE_args[] = { + { { OPERAND_bitindex }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_SETB_EXPSTATE_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRB_EXPSTATE_args[] = { + { { OPERAND_bitindex }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_CLRB_EXPSTATE_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' } +}; + +static xtensa_arg_internal Iclass_iclass_WRMSK_EXPSTATE_args[] = { + { { OPERAND_art }, 'i' }, + { { OPERAND_ars }, 'i' } +}; + +static xtensa_arg_internal Iclass_iclass_WRMSK_EXPSTATE_stateArgs[] = { + { { STATE_EXPSTATE }, 'm' } +}; + +static xtensa_iclass_internal iclasses[] = { + { 3, Iclass_LSI_args, + 1, Iclass_LSI_stateArgs, 0, 0 }, + { 3, Iclass_LSIP_args, + 1, Iclass_LSIP_stateArgs, 0, 0 }, + { 3, Iclass_LSX_args, + 1, Iclass_LSX_stateArgs, 0, 0 }, + { 3, Iclass_LSXP_args, + 1, Iclass_LSXP_stateArgs, 0, 0 }, + { 3, Iclass_SSI_args, + 1, Iclass_SSI_stateArgs, 0, 0 }, + { 3, Iclass_SSIP_args, + 1, Iclass_SSIP_stateArgs, 0, 0 }, + { 3, Iclass_SSX_args, + 1, Iclass_SSX_stateArgs, 0, 0 }, + { 3, Iclass_SSXP_args, + 1, Iclass_SSXP_stateArgs, 0, 0 }, + { 2, Iclass_ABS_S_args, + 1, Iclass_ABS_S_stateArgs, 0, 0 }, + { 2, Iclass_NEG_S_args, + 1, Iclass_NEG_S_stateArgs, 0, 0 }, + { 2, Iclass_MOV_S_args, + 1, Iclass_MOV_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVEQZ_S_args, + 1, Iclass_MOVEQZ_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVNEZ_S_args, + 1, Iclass_MOVNEZ_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVLTZ_S_args, + 1, Iclass_MOVLTZ_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVGEZ_S_args, + 1, Iclass_MOVGEZ_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVF_S_args, + 1, Iclass_MOVF_S_stateArgs, 0, 0 }, + { 3, Iclass_MOVT_S_args, + 1, Iclass_MOVT_S_stateArgs, 0, 0 }, + { 2, Iclass_WFR_args, + 1, Iclass_WFR_stateArgs, 0, 0 }, + { 2, Iclass_RFR_args, + 1, Iclass_RFR_stateArgs, 0, 0 }, + { 3, Iclass_ROUND_S_args, + 3, Iclass_ROUND_S_stateArgs, 0, 0 }, + { 3, Iclass_CEIL_S_args, + 3, Iclass_CEIL_S_stateArgs, 0, 0 }, + { 3, Iclass_FLOOR_S_args, + 3, Iclass_FLOOR_S_stateArgs, 0, 0 }, + { 3, Iclass_TRUNC_S_args, + 3, Iclass_TRUNC_S_stateArgs, 0, 0 }, + { 3, Iclass_UTRUNC_S_args, + 3, Iclass_UTRUNC_S_stateArgs, 0, 0 }, + { 3, Iclass_FLOAT_S_args, + 3, Iclass_FLOAT_S_stateArgs, 0, 0 }, + { 3, Iclass_UFLOAT_S_args, + 3, Iclass_UFLOAT_S_stateArgs, 0, 0 }, + { 3, Iclass_UN_S_args, + 2, Iclass_UN_S_stateArgs, 0, 0 }, + { 3, Iclass_ULT_S_args, + 2, Iclass_ULT_S_stateArgs, 0, 0 }, + { 3, Iclass_ULE_S_args, + 2, Iclass_ULE_S_stateArgs, 0, 0 }, + { 3, Iclass_UEQ_S_args, + 2, Iclass_UEQ_S_stateArgs, 0, 0 }, + { 3, Iclass_OLT_S_args, + 2, Iclass_OLT_S_stateArgs, 0, 0 }, + { 3, Iclass_OLE_S_args, + 2, Iclass_OLE_S_stateArgs, 0, 0 }, + { 3, Iclass_OEQ_S_args, + 2, Iclass_OEQ_S_stateArgs, 0, 0 }, + { 3, Iclass_ADD_S_args, + 6, Iclass_ADD_S_stateArgs, 0, 0 }, + { 3, Iclass_SUB_S_args, + 6, Iclass_SUB_S_stateArgs, 0, 0 }, + { 3, Iclass_MUL_S_args, + 6, Iclass_MUL_S_stateArgs, 0, 0 }, + { 3, Iclass_MADD_S_args, + 6, Iclass_MADD_S_stateArgs, 0, 0 }, + { 3, Iclass_MSUB_S_args, + 6, Iclass_MSUB_S_stateArgs, 0, 0 }, + { 2, Iclass_SQRT0_S_args, + 1, Iclass_SQRT0_S_stateArgs, 0, 0 }, + { 2, Iclass_DIV0_S_args, + 1, Iclass_DIV0_S_stateArgs, 0, 0 }, + { 2, Iclass_RECIP0_S_args, + 3, Iclass_RECIP0_S_stateArgs, 0, 0 }, + { 2, Iclass_RSQRT0_S_args, + 3, Iclass_RSQRT0_S_stateArgs, 0, 0 }, + { 3, Iclass_MADDN_S_args, + 1, Iclass_MADDN_S_stateArgs, 0, 0 }, + { 3, Iclass_DIVN_S_args, + 5, Iclass_DIVN_S_stateArgs, 0, 0 }, + { 2, Iclass_CONST_S_args, + 1, Iclass_CONST_S_stateArgs, 0, 0 }, + { 2, Iclass_NEXP01_S_args, + 1, Iclass_NEXP01_S_stateArgs, 0, 0 }, + { 2, Iclass_ADDEXP_S_args, + 1, Iclass_ADDEXP_S_stateArgs, 0, 0 }, + { 2, Iclass_ADDEXPM_S_args, + 1, Iclass_ADDEXPM_S_stateArgs, 0, 0 }, + { 2, Iclass_MKDADJ_S_args, + 3, Iclass_MKDADJ_S_stateArgs, 0, 0 }, + { 2, Iclass_MKSADJ_S_args, + 2, Iclass_MKSADJ_S_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_excw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_rfe */, + 2, Iclass_xt_iclass_rfe_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfde */, + 1, Iclass_xt_iclass_rfde_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_syscall */, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_call12_args, + 1, Iclass_xt_iclass_call12_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_call8_args, + 1, Iclass_xt_iclass_call8_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_call4_args, + 1, Iclass_xt_iclass_call4_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx12_args, + 1, Iclass_xt_iclass_callx12_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx8_args, + 1, Iclass_xt_iclass_callx8_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_callx4_args, + 1, Iclass_xt_iclass_callx4_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_entry_args, + 5, Iclass_xt_iclass_entry_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_movsp_args, + 2, Iclass_xt_iclass_movsp_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rotw_args, + 1, Iclass_xt_iclass_rotw_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_retw_args, + 5, Iclass_xt_iclass_retw_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfwou */, + 5, Iclass_xt_iclass_rfwou_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_l32e_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32e_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_windowbase_args, + 1, Iclass_xt_iclass_rsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_windowbase_args, + 1, Iclass_xt_iclass_wsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_windowbase_args, + 1, Iclass_xt_iclass_xsr_windowbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_windowstart_args, + 1, Iclass_xt_iclass_rsr_windowstart_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_windowstart_args, + 1, Iclass_xt_iclass_wsr_windowstart_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_windowstart_args, + 1, Iclass_xt_iclass_xsr_windowstart_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_add_n_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addi_n_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bz6_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_ill_n */, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_loadi4_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_mov_n_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_movi_n_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_nopn */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_retn_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_storei4_args, + 0, 0, 0, 0 }, + { 1, Iclass_rur_threadptr_args, + 1, Iclass_rur_threadptr_stateArgs, 0, 0 }, + { 1, Iclass_wur_threadptr_args, + 1, Iclass_wur_threadptr_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_addi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addmi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_addsub_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bit_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8b_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bsi8u_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bst8_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bsz12_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_call0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_callx0_args, + 0, 0, 0, 0 }, + { 4, Iclass_xt_iclass_exti_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_ill */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_jump_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_jumpx_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l16ui_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l16si_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l32i_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_l32r_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l8i_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_loop_args, + 3, Iclass_xt_iclass_loop_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_loopz_args, + 3, Iclass_xt_iclass_loopz_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_movi_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_movz_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_neg_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_nop */, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_return_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_simcall */, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s16i_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32i_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32nb_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s8i_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_sar_args, + 1, Iclass_xt_iclass_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_sari_args, + 1, Iclass_xt_iclass_sari_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_shifts_args, + 1, Iclass_xt_iclass_shifts_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_shiftst_args, + 1, Iclass_xt_iclass_shiftst_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_shiftt_args, + 1, Iclass_xt_iclass_shiftt_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_slli_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_srai_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_srli_args, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_memw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_extw */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_isync */, + 0, 0, 0, 0 }, + { 0, 0 /* xt_iclass_sync */, + 1, Iclass_xt_iclass_sync_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_rsil_args, + 6, Iclass_xt_iclass_rsil_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lend_args, + 1, Iclass_xt_iclass_rsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lend_args, + 1, Iclass_xt_iclass_wsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lend_args, + 1, Iclass_xt_iclass_xsr_lend_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lcount_args, + 1, Iclass_xt_iclass_rsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lcount_args, + 2, Iclass_xt_iclass_wsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lcount_args, + 2, Iclass_xt_iclass_xsr_lcount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_lbeg_args, + 1, Iclass_xt_iclass_rsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_lbeg_args, + 1, Iclass_xt_iclass_wsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_lbeg_args, + 1, Iclass_xt_iclass_xsr_lbeg_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_sar_args, + 1, Iclass_xt_iclass_rsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_sar_args, + 2, Iclass_xt_iclass_wsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_sar_args, + 1, Iclass_xt_iclass_xsr_sar_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_memctl_args, + 1, Iclass_xt_iclass_rsr_memctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_memctl_args, + 1, Iclass_xt_iclass_wsr_memctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_memctl_args, + 1, Iclass_xt_iclass_xsr_memctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_litbase_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_litbase_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_litbase_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_configid0_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_configid0_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_configid1_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ps_args, + 6, Iclass_xt_iclass_rsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ps_args, + 6, Iclass_xt_iclass_wsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ps_args, + 6, Iclass_xt_iclass_xsr_ps_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc1_args, + 1, Iclass_xt_iclass_rsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc1_args, + 1, Iclass_xt_iclass_wsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc1_args, + 1, Iclass_xt_iclass_xsr_epc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave1_args, + 1, Iclass_xt_iclass_rsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave1_args, + 1, Iclass_xt_iclass_wsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave1_args, + 1, Iclass_xt_iclass_xsr_excsave1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc2_args, + 1, Iclass_xt_iclass_rsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc2_args, + 1, Iclass_xt_iclass_wsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc2_args, + 1, Iclass_xt_iclass_xsr_epc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave2_args, + 1, Iclass_xt_iclass_rsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave2_args, + 1, Iclass_xt_iclass_wsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave2_args, + 1, Iclass_xt_iclass_xsr_excsave2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc3_args, + 1, Iclass_xt_iclass_rsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc3_args, + 1, Iclass_xt_iclass_wsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc3_args, + 1, Iclass_xt_iclass_xsr_epc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave3_args, + 1, Iclass_xt_iclass_rsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave3_args, + 1, Iclass_xt_iclass_wsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave3_args, + 1, Iclass_xt_iclass_xsr_excsave3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc4_args, + 1, Iclass_xt_iclass_rsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc4_args, + 1, Iclass_xt_iclass_wsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc4_args, + 1, Iclass_xt_iclass_xsr_epc4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave4_args, + 1, Iclass_xt_iclass_rsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave4_args, + 1, Iclass_xt_iclass_wsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave4_args, + 1, Iclass_xt_iclass_xsr_excsave4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc5_args, + 1, Iclass_xt_iclass_rsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc5_args, + 1, Iclass_xt_iclass_wsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc5_args, + 1, Iclass_xt_iclass_xsr_epc5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave5_args, + 1, Iclass_xt_iclass_rsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave5_args, + 1, Iclass_xt_iclass_wsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave5_args, + 1, Iclass_xt_iclass_xsr_excsave5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc6_args, + 1, Iclass_xt_iclass_rsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc6_args, + 1, Iclass_xt_iclass_wsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc6_args, + 1, Iclass_xt_iclass_xsr_epc6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave6_args, + 1, Iclass_xt_iclass_rsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave6_args, + 1, Iclass_xt_iclass_wsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave6_args, + 1, Iclass_xt_iclass_xsr_excsave6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_epc7_args, + 1, Iclass_xt_iclass_rsr_epc7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_epc7_args, + 1, Iclass_xt_iclass_wsr_epc7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_epc7_args, + 1, Iclass_xt_iclass_xsr_epc7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excsave7_args, + 1, Iclass_xt_iclass_rsr_excsave7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excsave7_args, + 1, Iclass_xt_iclass_wsr_excsave7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excsave7_args, + 1, Iclass_xt_iclass_xsr_excsave7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps2_args, + 1, Iclass_xt_iclass_rsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps2_args, + 1, Iclass_xt_iclass_wsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps2_args, + 1, Iclass_xt_iclass_xsr_eps2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps3_args, + 1, Iclass_xt_iclass_rsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps3_args, + 1, Iclass_xt_iclass_wsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps3_args, + 1, Iclass_xt_iclass_xsr_eps3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps4_args, + 1, Iclass_xt_iclass_rsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps4_args, + 1, Iclass_xt_iclass_wsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps4_args, + 1, Iclass_xt_iclass_xsr_eps4_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps5_args, + 1, Iclass_xt_iclass_rsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps5_args, + 1, Iclass_xt_iclass_wsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps5_args, + 1, Iclass_xt_iclass_xsr_eps5_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps6_args, + 1, Iclass_xt_iclass_rsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps6_args, + 1, Iclass_xt_iclass_wsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps6_args, + 1, Iclass_xt_iclass_xsr_eps6_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_eps7_args, + 1, Iclass_xt_iclass_rsr_eps7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_eps7_args, + 1, Iclass_xt_iclass_wsr_eps7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_eps7_args, + 1, Iclass_xt_iclass_xsr_eps7_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_excvaddr_args, + 1, Iclass_xt_iclass_rsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_excvaddr_args, + 1, Iclass_xt_iclass_wsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_excvaddr_args, + 1, Iclass_xt_iclass_xsr_excvaddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_depc_args, + 1, Iclass_xt_iclass_rsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_depc_args, + 1, Iclass_xt_iclass_wsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_depc_args, + 1, Iclass_xt_iclass_xsr_depc_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_exccause_args, + 2, Iclass_xt_iclass_rsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_exccause_args, + 1, Iclass_xt_iclass_wsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_exccause_args, + 1, Iclass_xt_iclass_xsr_exccause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_misc0_args, + 1, Iclass_xt_iclass_rsr_misc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_misc0_args, + 1, Iclass_xt_iclass_wsr_misc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_misc0_args, + 1, Iclass_xt_iclass_xsr_misc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_misc1_args, + 1, Iclass_xt_iclass_rsr_misc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_misc1_args, + 1, Iclass_xt_iclass_wsr_misc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_misc1_args, + 1, Iclass_xt_iclass_xsr_misc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_misc2_args, + 1, Iclass_xt_iclass_rsr_misc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_misc2_args, + 1, Iclass_xt_iclass_wsr_misc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_misc2_args, + 1, Iclass_xt_iclass_xsr_misc2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_misc3_args, + 1, Iclass_xt_iclass_rsr_misc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_misc3_args, + 1, Iclass_xt_iclass_wsr_misc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_misc3_args, + 1, Iclass_xt_iclass_xsr_misc3_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_prid_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_vecbase_args, + 1, Iclass_xt_iclass_rsr_vecbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_vecbase_args, + 1, Iclass_xt_iclass_wsr_vecbase_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_vecbase_args, + 1, Iclass_xt_iclass_xsr_vecbase_stateArgs, 0, 0 }, + { 3, Iclass_xt_mul16_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_mul32_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_mul32h_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_aa_args, + 1, Iclass_xt_iclass_mac16_aa_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_ad_args, + 1, Iclass_xt_iclass_mac16_ad_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_da_args, + 1, Iclass_xt_iclass_mac16_da_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_dd_args, + 1, Iclass_xt_iclass_mac16_dd_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16a_aa_args, + 1, Iclass_xt_iclass_mac16a_aa_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16a_ad_args, + 1, Iclass_xt_iclass_mac16a_ad_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16a_da_args, + 1, Iclass_xt_iclass_mac16a_da_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16a_dd_args, + 1, Iclass_xt_iclass_mac16a_dd_stateArgs, 0, 0 }, + { 4, Iclass_xt_iclass_mac16al_da_args, + 1, Iclass_xt_iclass_mac16al_da_stateArgs, 0, 0 }, + { 4, Iclass_xt_iclass_mac16al_dd_args, + 1, Iclass_xt_iclass_mac16al_dd_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_mac16_l_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rsr_m0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wsr_m0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_xsr_m0_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rsr_m1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wsr_m1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_xsr_m1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rsr_m2_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wsr_m2_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_xsr_m2_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rsr_m3_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wsr_m3_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_xsr_m3_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_acclo_args, + 1, Iclass_xt_iclass_rsr_acclo_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_acclo_args, + 1, Iclass_xt_iclass_wsr_acclo_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_acclo_args, + 1, Iclass_xt_iclass_xsr_acclo_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_acchi_args, + 1, Iclass_xt_iclass_rsr_acchi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_acchi_args, + 1, Iclass_xt_iclass_wsr_acchi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_acchi_args, + 1, Iclass_xt_iclass_xsr_acchi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rfi_args, + 20, Iclass_xt_iclass_rfi_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wait_args, + 1, Iclass_xt_iclass_wait_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_interrupt_args, + 1, Iclass_xt_iclass_rsr_interrupt_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intset_args, + 2, Iclass_xt_iclass_wsr_intset_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intclear_args, + 2, Iclass_xt_iclass_wsr_intclear_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_intenable_args, + 1, Iclass_xt_iclass_rsr_intenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_intenable_args, + 1, Iclass_xt_iclass_wsr_intenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_intenable_args, + 1, Iclass_xt_iclass_xsr_intenable_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_break_args, + 2, Iclass_xt_iclass_break_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_break_n_args, + 2, Iclass_xt_iclass_break_n_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreaka0_args, + 1, Iclass_xt_iclass_rsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreaka0_args, + 2, Iclass_xt_iclass_wsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreaka0_args, + 2, Iclass_xt_iclass_xsr_dbreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreakc0_args, + 1, Iclass_xt_iclass_rsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreakc0_args, + 2, Iclass_xt_iclass_wsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreakc0_args, + 2, Iclass_xt_iclass_xsr_dbreakc0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreaka1_args, + 1, Iclass_xt_iclass_rsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreaka1_args, + 2, Iclass_xt_iclass_wsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreaka1_args, + 2, Iclass_xt_iclass_xsr_dbreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_dbreakc1_args, + 1, Iclass_xt_iclass_rsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_dbreakc1_args, + 2, Iclass_xt_iclass_wsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_dbreakc1_args, + 2, Iclass_xt_iclass_xsr_dbreakc1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreaka0_args, + 1, Iclass_xt_iclass_rsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreaka0_args, + 1, Iclass_xt_iclass_wsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreaka0_args, + 1, Iclass_xt_iclass_xsr_ibreaka0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreaka1_args, + 1, Iclass_xt_iclass_rsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreaka1_args, + 1, Iclass_xt_iclass_wsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreaka1_args, + 1, Iclass_xt_iclass_xsr_ibreaka1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ibreakenable_args, + 1, Iclass_xt_iclass_rsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ibreakenable_args, + 1, Iclass_xt_iclass_wsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ibreakenable_args, + 1, Iclass_xt_iclass_xsr_ibreakenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_debugcause_args, + 2, Iclass_xt_iclass_rsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_debugcause_args, + 2, Iclass_xt_iclass_wsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_debugcause_args, + 2, Iclass_xt_iclass_xsr_debugcause_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_icount_args, + 1, Iclass_xt_iclass_rsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_icount_args, + 2, Iclass_xt_iclass_wsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_icount_args, + 2, Iclass_xt_iclass_xsr_icount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_icountlevel_args, + 1, Iclass_xt_iclass_rsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_icountlevel_args, + 1, Iclass_xt_iclass_wsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_icountlevel_args, + 1, Iclass_xt_iclass_xsr_icountlevel_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ddr_args, + 1, Iclass_xt_iclass_rsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ddr_args, + 2, Iclass_xt_iclass_wsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ddr_args, + 2, Iclass_xt_iclass_xsr_ddr_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_lddr32_p_args, + 3, Iclass_xt_iclass_lddr32_p_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_sddr32_p_args, + 2, Iclass_xt_iclass_sddr32_p_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rfdo_args, + 9, Iclass_xt_iclass_rfdo_stateArgs, 0, 0 }, + { 0, 0 /* xt_iclass_rfdd */, + 1, Iclass_xt_iclass_rfdd_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_mmid_args, + 1, Iclass_xt_iclass_wsr_mmid_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_bbool1_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbool4_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbool8_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_bbranch_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_bmove_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_RSR_BR_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_WSR_BR_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_XSR_BR_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccount_args, + 1, Iclass_xt_iclass_rsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccount_args, + 2, Iclass_xt_iclass_wsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccount_args, + 2, Iclass_xt_iclass_xsr_ccount_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccompare0_args, + 1, Iclass_xt_iclass_rsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccompare0_args, + 2, Iclass_xt_iclass_wsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccompare0_args, + 2, Iclass_xt_iclass_xsr_ccompare0_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccompare1_args, + 1, Iclass_xt_iclass_rsr_ccompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccompare1_args, + 2, Iclass_xt_iclass_wsr_ccompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccompare1_args, + 2, Iclass_xt_iclass_xsr_ccompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_ccompare2_args, + 1, Iclass_xt_iclass_rsr_ccompare2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_ccompare2_args, + 2, Iclass_xt_iclass_wsr_ccompare2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_ccompare2_args, + 2, Iclass_xt_iclass_xsr_ccompare2_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_idtlb_args, + 1, Iclass_xt_iclass_idtlb_stateArgs, 0, 0 }, + { 2, Iclass_xt_iclass_rdtlb_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_wdtlb_args, + 1, Iclass_xt_iclass_wdtlb_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_iitlb_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_ritlb_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_witlb_args, + 0, 0, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_cpenable_args, + 1, Iclass_xt_iclass_rsr_cpenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_cpenable_args, + 1, Iclass_xt_iclass_wsr_cpenable_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_cpenable_args, + 1, Iclass_xt_iclass_xsr_cpenable_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_clamp_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_minmax_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_nsa_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_sx_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_l32ai_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32ri_args, + 0, 0, 0, 0 }, + { 3, Iclass_xt_iclass_s32c1i_args, + 3, Iclass_xt_iclass_s32c1i_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_scompare1_args, + 1, Iclass_xt_iclass_rsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_scompare1_args, + 1, Iclass_xt_iclass_wsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_scompare1_args, + 1, Iclass_xt_iclass_xsr_scompare1_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_rsr_atomctl_args, + 1, Iclass_xt_iclass_rsr_atomctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_wsr_atomctl_args, + 2, Iclass_xt_iclass_wsr_atomctl_stateArgs, 0, 0 }, + { 1, Iclass_xt_iclass_xsr_atomctl_args, + 2, Iclass_xt_iclass_xsr_atomctl_stateArgs, 0, 0 }, + { 3, Iclass_xt_iclass_div_args, + 0, 0, 0, 0 }, + { 2, Iclass_xt_iclass_rer_args, + 1, Iclass_xt_iclass_rer_stateArgs, 2, Iclass_xt_iclass_rer_intfArgs }, + { 2, Iclass_xt_iclass_wer_args, + 1, Iclass_xt_iclass_wer_stateArgs, 2, Iclass_xt_iclass_wer_intfArgs }, + { 5, Iclass_iclass_F64ITER_args, + 2, Iclass_iclass_F64ITER_stateArgs, 0, 0 }, + { 4, Iclass_iclass_F64RND_args, + 2, Iclass_iclass_F64RND_stateArgs, 0, 0 }, + { 4, Iclass_iclass_F64ADDC_F64SUBC_args, + 1, Iclass_iclass_F64ADDC_F64SUBC_stateArgs, 0, 0 }, + { 2, Iclass_iclass_F64SIG_args, + 0, 0, 0, 0 }, + { 3, Iclass_iclass_F64CMPL_args, + 1, Iclass_iclass_F64CMPL_stateArgs, 0, 0 }, + { 4, Iclass_iclass_F64CMPH_args, + 3, Iclass_iclass_F64CMPH_stateArgs, 0, 0 }, + { 4, Iclass_iclass_F64NORM_args, + 2, Iclass_iclass_F64NORM_stateArgs, 0, 0 }, + { 3, Iclass_iclass_F64SEXP_args, + 0, 0, 0, 0 }, + { 2, Iclass_iclass_RF64R_args, + 1, Iclass_iclass_RF64R_stateArgs, 0, 0 }, + { 3, Iclass_iclass_WF64R_args, + 1, Iclass_iclass_WF64R_stateArgs, 0, 0 }, + { 1, Iclass_rur_f64r_lo_args, + 1, Iclass_rur_f64r_lo_stateArgs, 0, 0 }, + { 1, Iclass_wur_f64r_lo_args, + 1, Iclass_wur_f64r_lo_stateArgs, 0, 0 }, + { 1, Iclass_rur_f64r_hi_args, + 1, Iclass_rur_f64r_hi_stateArgs, 0, 0 }, + { 1, Iclass_wur_f64r_hi_args, + 1, Iclass_wur_f64r_hi_stateArgs, 0, 0 }, + { 1, Iclass_rur_f64s_args, + 1, Iclass_rur_f64s_stateArgs, 0, 0 }, + { 1, Iclass_wur_f64s_args, + 1, Iclass_wur_f64s_stateArgs, 0, 0 }, + { 1, Iclass_rur_fcr_args, + 9, Iclass_rur_fcr_stateArgs, 0, 0 }, + { 1, Iclass_wur_fcr_args, + 9, Iclass_wur_fcr_stateArgs, 0, 0 }, + { 1, Iclass_rur_fsr_args, + 8, Iclass_rur_fsr_stateArgs, 0, 0 }, + { 1, Iclass_wur_fsr_args, + 8, Iclass_wur_fsr_stateArgs, 0, 0 }, + { 1, Iclass_rur_expstate_args, + 1, Iclass_rur_expstate_stateArgs, 0, 0 }, + { 1, Iclass_wur_expstate_args, + 1, Iclass_wur_expstate_stateArgs, 0, 0 }, + { 1, Iclass_iclass_READ_IMPWIRE_args, + 0, 0, 1, Iclass_iclass_READ_IMPWIRE_intfArgs }, + { 1, Iclass_iclass_SETB_EXPSTATE_args, + 1, Iclass_iclass_SETB_EXPSTATE_stateArgs, 0, 0 }, + { 1, Iclass_iclass_CLRB_EXPSTATE_args, + 1, Iclass_iclass_CLRB_EXPSTATE_stateArgs, 0, 0 }, + { 2, Iclass_iclass_WRMSK_EXPSTATE_args, + 1, Iclass_iclass_WRMSK_EXPSTATE_stateArgs, 0, 0 } +}; + +enum xtensa_iclass_id { + ICLASS_LSI, + ICLASS_LSIP, + ICLASS_LSX, + ICLASS_LSXP, + ICLASS_SSI, + ICLASS_SSIP, + ICLASS_SSX, + ICLASS_SSXP, + ICLASS_ABS_S, + ICLASS_NEG_S, + ICLASS_MOV_S, + ICLASS_MOVEQZ_S, + ICLASS_MOVNEZ_S, + ICLASS_MOVLTZ_S, + ICLASS_MOVGEZ_S, + ICLASS_MOVF_S, + ICLASS_MOVT_S, + ICLASS_WFR, + ICLASS_RFR, + ICLASS_ROUND_S, + ICLASS_CEIL_S, + ICLASS_FLOOR_S, + ICLASS_TRUNC_S, + ICLASS_UTRUNC_S, + ICLASS_FLOAT_S, + ICLASS_UFLOAT_S, + ICLASS_UN_S, + ICLASS_ULT_S, + ICLASS_ULE_S, + ICLASS_UEQ_S, + ICLASS_OLT_S, + ICLASS_OLE_S, + ICLASS_OEQ_S, + ICLASS_ADD_S, + ICLASS_SUB_S, + ICLASS_MUL_S, + ICLASS_MADD_S, + ICLASS_MSUB_S, + ICLASS_SQRT0_S, + ICLASS_DIV0_S, + ICLASS_RECIP0_S, + ICLASS_RSQRT0_S, + ICLASS_MADDN_S, + ICLASS_DIVN_S, + ICLASS_CONST_S, + ICLASS_NEXP01_S, + ICLASS_ADDEXP_S, + ICLASS_ADDEXPM_S, + ICLASS_MKDADJ_S, + ICLASS_MKSADJ_S, + ICLASS_xt_iclass_excw, + ICLASS_xt_iclass_rfe, + ICLASS_xt_iclass_rfde, + ICLASS_xt_iclass_syscall, + ICLASS_xt_iclass_call12, + ICLASS_xt_iclass_call8, + ICLASS_xt_iclass_call4, + ICLASS_xt_iclass_callx12, + ICLASS_xt_iclass_callx8, + ICLASS_xt_iclass_callx4, + ICLASS_xt_iclass_entry, + ICLASS_xt_iclass_movsp, + ICLASS_xt_iclass_rotw, + ICLASS_xt_iclass_retw, + ICLASS_xt_iclass_rfwou, + ICLASS_xt_iclass_l32e, + ICLASS_xt_iclass_s32e, + ICLASS_xt_iclass_rsr_windowbase, + ICLASS_xt_iclass_wsr_windowbase, + ICLASS_xt_iclass_xsr_windowbase, + ICLASS_xt_iclass_rsr_windowstart, + ICLASS_xt_iclass_wsr_windowstart, + ICLASS_xt_iclass_xsr_windowstart, + ICLASS_xt_iclass_add_n, + ICLASS_xt_iclass_addi_n, + ICLASS_xt_iclass_bz6, + ICLASS_xt_iclass_ill_n, + ICLASS_xt_iclass_loadi4, + ICLASS_xt_iclass_mov_n, + ICLASS_xt_iclass_movi_n, + ICLASS_xt_iclass_nopn, + ICLASS_xt_iclass_retn, + ICLASS_xt_iclass_storei4, + ICLASS_rur_threadptr, + ICLASS_wur_threadptr, + ICLASS_xt_iclass_addi, + ICLASS_xt_iclass_addmi, + ICLASS_xt_iclass_addsub, + ICLASS_xt_iclass_bit, + ICLASS_xt_iclass_bsi8, + ICLASS_xt_iclass_bsi8b, + ICLASS_xt_iclass_bsi8u, + ICLASS_xt_iclass_bst8, + ICLASS_xt_iclass_bsz12, + ICLASS_xt_iclass_call0, + ICLASS_xt_iclass_callx0, + ICLASS_xt_iclass_exti, + ICLASS_xt_iclass_ill, + ICLASS_xt_iclass_jump, + ICLASS_xt_iclass_jumpx, + ICLASS_xt_iclass_l16ui, + ICLASS_xt_iclass_l16si, + ICLASS_xt_iclass_l32i, + ICLASS_xt_iclass_l32r, + ICLASS_xt_iclass_l8i, + ICLASS_xt_iclass_loop, + ICLASS_xt_iclass_loopz, + ICLASS_xt_iclass_movi, + ICLASS_xt_iclass_movz, + ICLASS_xt_iclass_neg, + ICLASS_xt_iclass_nop, + ICLASS_xt_iclass_return, + ICLASS_xt_iclass_simcall, + ICLASS_xt_iclass_s16i, + ICLASS_xt_iclass_s32i, + ICLASS_xt_iclass_s32nb, + ICLASS_xt_iclass_s8i, + ICLASS_xt_iclass_sar, + ICLASS_xt_iclass_sari, + ICLASS_xt_iclass_shifts, + ICLASS_xt_iclass_shiftst, + ICLASS_xt_iclass_shiftt, + ICLASS_xt_iclass_slli, + ICLASS_xt_iclass_srai, + ICLASS_xt_iclass_srli, + ICLASS_xt_iclass_memw, + ICLASS_xt_iclass_extw, + ICLASS_xt_iclass_isync, + ICLASS_xt_iclass_sync, + ICLASS_xt_iclass_rsil, + ICLASS_xt_iclass_rsr_lend, + ICLASS_xt_iclass_wsr_lend, + ICLASS_xt_iclass_xsr_lend, + ICLASS_xt_iclass_rsr_lcount, + ICLASS_xt_iclass_wsr_lcount, + ICLASS_xt_iclass_xsr_lcount, + ICLASS_xt_iclass_rsr_lbeg, + ICLASS_xt_iclass_wsr_lbeg, + ICLASS_xt_iclass_xsr_lbeg, + ICLASS_xt_iclass_rsr_sar, + ICLASS_xt_iclass_wsr_sar, + ICLASS_xt_iclass_xsr_sar, + ICLASS_xt_iclass_rsr_memctl, + ICLASS_xt_iclass_wsr_memctl, + ICLASS_xt_iclass_xsr_memctl, + ICLASS_xt_iclass_rsr_litbase, + ICLASS_xt_iclass_wsr_litbase, + ICLASS_xt_iclass_xsr_litbase, + ICLASS_xt_iclass_rsr_configid0, + ICLASS_xt_iclass_wsr_configid0, + ICLASS_xt_iclass_rsr_configid1, + ICLASS_xt_iclass_rsr_ps, + ICLASS_xt_iclass_wsr_ps, + ICLASS_xt_iclass_xsr_ps, + ICLASS_xt_iclass_rsr_epc1, + ICLASS_xt_iclass_wsr_epc1, + ICLASS_xt_iclass_xsr_epc1, + ICLASS_xt_iclass_rsr_excsave1, + ICLASS_xt_iclass_wsr_excsave1, + ICLASS_xt_iclass_xsr_excsave1, + ICLASS_xt_iclass_rsr_epc2, + ICLASS_xt_iclass_wsr_epc2, + ICLASS_xt_iclass_xsr_epc2, + ICLASS_xt_iclass_rsr_excsave2, + ICLASS_xt_iclass_wsr_excsave2, + ICLASS_xt_iclass_xsr_excsave2, + ICLASS_xt_iclass_rsr_epc3, + ICLASS_xt_iclass_wsr_epc3, + ICLASS_xt_iclass_xsr_epc3, + ICLASS_xt_iclass_rsr_excsave3, + ICLASS_xt_iclass_wsr_excsave3, + ICLASS_xt_iclass_xsr_excsave3, + ICLASS_xt_iclass_rsr_epc4, + ICLASS_xt_iclass_wsr_epc4, + ICLASS_xt_iclass_xsr_epc4, + ICLASS_xt_iclass_rsr_excsave4, + ICLASS_xt_iclass_wsr_excsave4, + ICLASS_xt_iclass_xsr_excsave4, + ICLASS_xt_iclass_rsr_epc5, + ICLASS_xt_iclass_wsr_epc5, + ICLASS_xt_iclass_xsr_epc5, + ICLASS_xt_iclass_rsr_excsave5, + ICLASS_xt_iclass_wsr_excsave5, + ICLASS_xt_iclass_xsr_excsave5, + ICLASS_xt_iclass_rsr_epc6, + ICLASS_xt_iclass_wsr_epc6, + ICLASS_xt_iclass_xsr_epc6, + ICLASS_xt_iclass_rsr_excsave6, + ICLASS_xt_iclass_wsr_excsave6, + ICLASS_xt_iclass_xsr_excsave6, + ICLASS_xt_iclass_rsr_epc7, + ICLASS_xt_iclass_wsr_epc7, + ICLASS_xt_iclass_xsr_epc7, + ICLASS_xt_iclass_rsr_excsave7, + ICLASS_xt_iclass_wsr_excsave7, + ICLASS_xt_iclass_xsr_excsave7, + ICLASS_xt_iclass_rsr_eps2, + ICLASS_xt_iclass_wsr_eps2, + ICLASS_xt_iclass_xsr_eps2, + ICLASS_xt_iclass_rsr_eps3, + ICLASS_xt_iclass_wsr_eps3, + ICLASS_xt_iclass_xsr_eps3, + ICLASS_xt_iclass_rsr_eps4, + ICLASS_xt_iclass_wsr_eps4, + ICLASS_xt_iclass_xsr_eps4, + ICLASS_xt_iclass_rsr_eps5, + ICLASS_xt_iclass_wsr_eps5, + ICLASS_xt_iclass_xsr_eps5, + ICLASS_xt_iclass_rsr_eps6, + ICLASS_xt_iclass_wsr_eps6, + ICLASS_xt_iclass_xsr_eps6, + ICLASS_xt_iclass_rsr_eps7, + ICLASS_xt_iclass_wsr_eps7, + ICLASS_xt_iclass_xsr_eps7, + ICLASS_xt_iclass_rsr_excvaddr, + ICLASS_xt_iclass_wsr_excvaddr, + ICLASS_xt_iclass_xsr_excvaddr, + ICLASS_xt_iclass_rsr_depc, + ICLASS_xt_iclass_wsr_depc, + ICLASS_xt_iclass_xsr_depc, + ICLASS_xt_iclass_rsr_exccause, + ICLASS_xt_iclass_wsr_exccause, + ICLASS_xt_iclass_xsr_exccause, + ICLASS_xt_iclass_rsr_misc0, + ICLASS_xt_iclass_wsr_misc0, + ICLASS_xt_iclass_xsr_misc0, + ICLASS_xt_iclass_rsr_misc1, + ICLASS_xt_iclass_wsr_misc1, + ICLASS_xt_iclass_xsr_misc1, + ICLASS_xt_iclass_rsr_misc2, + ICLASS_xt_iclass_wsr_misc2, + ICLASS_xt_iclass_xsr_misc2, + ICLASS_xt_iclass_rsr_misc3, + ICLASS_xt_iclass_wsr_misc3, + ICLASS_xt_iclass_xsr_misc3, + ICLASS_xt_iclass_rsr_prid, + ICLASS_xt_iclass_rsr_vecbase, + ICLASS_xt_iclass_wsr_vecbase, + ICLASS_xt_iclass_xsr_vecbase, + ICLASS_xt_mul16, + ICLASS_xt_mul32, + ICLASS_xt_mul32h, + ICLASS_xt_iclass_mac16_aa, + ICLASS_xt_iclass_mac16_ad, + ICLASS_xt_iclass_mac16_da, + ICLASS_xt_iclass_mac16_dd, + ICLASS_xt_iclass_mac16a_aa, + ICLASS_xt_iclass_mac16a_ad, + ICLASS_xt_iclass_mac16a_da, + ICLASS_xt_iclass_mac16a_dd, + ICLASS_xt_iclass_mac16al_da, + ICLASS_xt_iclass_mac16al_dd, + ICLASS_xt_iclass_mac16_l, + ICLASS_xt_iclass_rsr_m0, + ICLASS_xt_iclass_wsr_m0, + ICLASS_xt_iclass_xsr_m0, + ICLASS_xt_iclass_rsr_m1, + ICLASS_xt_iclass_wsr_m1, + ICLASS_xt_iclass_xsr_m1, + ICLASS_xt_iclass_rsr_m2, + ICLASS_xt_iclass_wsr_m2, + ICLASS_xt_iclass_xsr_m2, + ICLASS_xt_iclass_rsr_m3, + ICLASS_xt_iclass_wsr_m3, + ICLASS_xt_iclass_xsr_m3, + ICLASS_xt_iclass_rsr_acclo, + ICLASS_xt_iclass_wsr_acclo, + ICLASS_xt_iclass_xsr_acclo, + ICLASS_xt_iclass_rsr_acchi, + ICLASS_xt_iclass_wsr_acchi, + ICLASS_xt_iclass_xsr_acchi, + ICLASS_xt_iclass_rfi, + ICLASS_xt_iclass_wait, + ICLASS_xt_iclass_rsr_interrupt, + ICLASS_xt_iclass_wsr_intset, + ICLASS_xt_iclass_wsr_intclear, + ICLASS_xt_iclass_rsr_intenable, + ICLASS_xt_iclass_wsr_intenable, + ICLASS_xt_iclass_xsr_intenable, + ICLASS_xt_iclass_break, + ICLASS_xt_iclass_break_n, + ICLASS_xt_iclass_rsr_dbreaka0, + ICLASS_xt_iclass_wsr_dbreaka0, + ICLASS_xt_iclass_xsr_dbreaka0, + ICLASS_xt_iclass_rsr_dbreakc0, + ICLASS_xt_iclass_wsr_dbreakc0, + ICLASS_xt_iclass_xsr_dbreakc0, + ICLASS_xt_iclass_rsr_dbreaka1, + ICLASS_xt_iclass_wsr_dbreaka1, + ICLASS_xt_iclass_xsr_dbreaka1, + ICLASS_xt_iclass_rsr_dbreakc1, + ICLASS_xt_iclass_wsr_dbreakc1, + ICLASS_xt_iclass_xsr_dbreakc1, + ICLASS_xt_iclass_rsr_ibreaka0, + ICLASS_xt_iclass_wsr_ibreaka0, + ICLASS_xt_iclass_xsr_ibreaka0, + ICLASS_xt_iclass_rsr_ibreaka1, + ICLASS_xt_iclass_wsr_ibreaka1, + ICLASS_xt_iclass_xsr_ibreaka1, + ICLASS_xt_iclass_rsr_ibreakenable, + ICLASS_xt_iclass_wsr_ibreakenable, + ICLASS_xt_iclass_xsr_ibreakenable, + ICLASS_xt_iclass_rsr_debugcause, + ICLASS_xt_iclass_wsr_debugcause, + ICLASS_xt_iclass_xsr_debugcause, + ICLASS_xt_iclass_rsr_icount, + ICLASS_xt_iclass_wsr_icount, + ICLASS_xt_iclass_xsr_icount, + ICLASS_xt_iclass_rsr_icountlevel, + ICLASS_xt_iclass_wsr_icountlevel, + ICLASS_xt_iclass_xsr_icountlevel, + ICLASS_xt_iclass_rsr_ddr, + ICLASS_xt_iclass_wsr_ddr, + ICLASS_xt_iclass_xsr_ddr, + ICLASS_xt_iclass_lddr32_p, + ICLASS_xt_iclass_sddr32_p, + ICLASS_xt_iclass_rfdo, + ICLASS_xt_iclass_rfdd, + ICLASS_xt_iclass_wsr_mmid, + ICLASS_xt_iclass_bbool1, + ICLASS_xt_iclass_bbool4, + ICLASS_xt_iclass_bbool8, + ICLASS_xt_iclass_bbranch, + ICLASS_xt_iclass_bmove, + ICLASS_xt_iclass_RSR_BR, + ICLASS_xt_iclass_WSR_BR, + ICLASS_xt_iclass_XSR_BR, + ICLASS_xt_iclass_rsr_ccount, + ICLASS_xt_iclass_wsr_ccount, + ICLASS_xt_iclass_xsr_ccount, + ICLASS_xt_iclass_rsr_ccompare0, + ICLASS_xt_iclass_wsr_ccompare0, + ICLASS_xt_iclass_xsr_ccompare0, + ICLASS_xt_iclass_rsr_ccompare1, + ICLASS_xt_iclass_wsr_ccompare1, + ICLASS_xt_iclass_xsr_ccompare1, + ICLASS_xt_iclass_rsr_ccompare2, + ICLASS_xt_iclass_wsr_ccompare2, + ICLASS_xt_iclass_xsr_ccompare2, + ICLASS_xt_iclass_idtlb, + ICLASS_xt_iclass_rdtlb, + ICLASS_xt_iclass_wdtlb, + ICLASS_xt_iclass_iitlb, + ICLASS_xt_iclass_ritlb, + ICLASS_xt_iclass_witlb, + ICLASS_xt_iclass_rsr_cpenable, + ICLASS_xt_iclass_wsr_cpenable, + ICLASS_xt_iclass_xsr_cpenable, + ICLASS_xt_iclass_clamp, + ICLASS_xt_iclass_minmax, + ICLASS_xt_iclass_nsa, + ICLASS_xt_iclass_sx, + ICLASS_xt_iclass_l32ai, + ICLASS_xt_iclass_s32ri, + ICLASS_xt_iclass_s32c1i, + ICLASS_xt_iclass_rsr_scompare1, + ICLASS_xt_iclass_wsr_scompare1, + ICLASS_xt_iclass_xsr_scompare1, + ICLASS_xt_iclass_rsr_atomctl, + ICLASS_xt_iclass_wsr_atomctl, + ICLASS_xt_iclass_xsr_atomctl, + ICLASS_xt_iclass_div, + ICLASS_xt_iclass_rer, + ICLASS_xt_iclass_wer, + ICLASS_iclass_F64ITER, + ICLASS_iclass_F64RND, + ICLASS_iclass_F64ADDC_F64SUBC, + ICLASS_iclass_F64SIG, + ICLASS_iclass_F64CMPL, + ICLASS_iclass_F64CMPH, + ICLASS_iclass_F64NORM, + ICLASS_iclass_F64SEXP, + ICLASS_iclass_RF64R, + ICLASS_iclass_WF64R, + ICLASS_rur_f64r_lo, + ICLASS_wur_f64r_lo, + ICLASS_rur_f64r_hi, + ICLASS_wur_f64r_hi, + ICLASS_rur_f64s, + ICLASS_wur_f64s, + ICLASS_rur_fcr, + ICLASS_wur_fcr, + ICLASS_rur_fsr, + ICLASS_wur_fsr, + ICLASS_rur_expstate, + ICLASS_wur_expstate, + ICLASS_iclass_READ_IMPWIRE, + ICLASS_iclass_SETB_EXPSTATE, + ICLASS_iclass_CLRB_EXPSTATE, + ICLASS_iclass_WRMSK_EXPSTATE +}; + + +/* Opcode encodings. */ + +static void +Opcode_lsi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3; +} + +static void +Opcode_lsip_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8003; +} + +static void +Opcode_lsx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80000; +} + +static void +Opcode_lsxp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180000; +} + +static void +Opcode_ssi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4003; +} + +static void +Opcode_ssip_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc003; +} + +static void +Opcode_ssx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x480000; +} + +static void +Opcode_ssxp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x580000; +} + +static void +Opcode_abs_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0010; +} + +static void +Opcode_neg_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0060; +} + +static void +Opcode_mov_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0000; +} + +static void +Opcode_moveqz_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8b0000; +} + +static void +Opcode_movnez_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9b0000; +} + +static void +Opcode_movltz_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xab0000; +} + +static void +Opcode_movgez_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbb0000; +} + +static void +Opcode_movf_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcb0000; +} + +static void +Opcode_movt_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xdb0000; +} + +static void +Opcode_wfr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0050; +} + +static void +Opcode_rfr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0040; +} + +static void +Opcode_round_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8a0000; +} + +static void +Opcode_ceil_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xba0000; +} + +static void +Opcode_floor_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xaa0000; +} + +static void +Opcode_trunc_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9a0000; +} + +static void +Opcode_utrunc_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xea0000; +} + +static void +Opcode_float_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xca0000; +} + +static void +Opcode_ufloat_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xda0000; +} + +static void +Opcode_un_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1b0000; +} + +static void +Opcode_ult_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5b0000; +} + +static void +Opcode_ule_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7b0000; +} + +static void +Opcode_ueq_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b0000; +} + +static void +Opcode_olt_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4b0000; +} + +static void +Opcode_ole_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b0000; +} + +static void +Opcode_oeq_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2b0000; +} + +static void +Opcode_add_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0000; +} + +static void +Opcode_sub_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1a0000; +} + +static void +Opcode_mul_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a0000; +} + +static void +Opcode_madd_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4a0000; +} + +static void +Opcode_msub_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a0000; +} + +static void +Opcode_sqrt0_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0090; +} + +static void +Opcode_div0_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0070; +} + +static void +Opcode_recip0_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0080; +} + +static void +Opcode_rsqrt0_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00a0; +} + +static void +Opcode_maddn_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a0000; +} + +static void +Opcode_divn_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7a0000; +} + +static void +Opcode_const_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa0030; +} + +static void +Opcode_nexp01_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00b0; +} + +static void +Opcode_addexp_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00e0; +} + +static void +Opcode_addexpm_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00f0; +} + +static void +Opcode_mkdadj_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00d0; +} + +static void +Opcode_mksadj_s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfa00c0; +} + +static void +Opcode_excw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2080; +} + +static void +Opcode_rfe_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3000; +} + +static void +Opcode_rfde_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3200; +} + +static void +Opcode_syscall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5000; +} + +static void +Opcode_call12_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x35; +} + +static void +Opcode_call8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x25; +} + +static void +Opcode_call4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x15; +} + +static void +Opcode_callx12_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf0; +} + +static void +Opcode_callx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe0; +} + +static void +Opcode_callx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd0; +} + +static void +Opcode_entry_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36; +} + +static void +Opcode_movsp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1000; +} + +static void +Opcode_rotw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x408000; +} + +static void +Opcode_retw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x90; +} + +static void +Opcode_retw_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf01d; +} + +static void +Opcode_rfwo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3400; +} + +static void +Opcode_rfwu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3500; +} + +static void +Opcode_l32e_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x90000; +} + +static void +Opcode_s32e_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x490000; +} + +static void +Opcode_rsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34800; +} + +static void +Opcode_wsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x134800; +} + +static void +Opcode_xsr_windowbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x614800; +} + +static void +Opcode_rsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x34900; +} + +static void +Opcode_wsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x134900; +} + +static void +Opcode_xsr_windowstart_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x614900; +} + +static void +Opcode_add_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa; +} + +static void +Opcode_addi_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb; +} + +static void +Opcode_beqz_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8c; +} + +static void +Opcode_bnez_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xcc; +} + +static void +Opcode_ill_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf06d; +} + +static void +Opcode_l32i_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8; +} + +static void +Opcode_mov_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd; +} + +static void +Opcode_movi_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc; +} + +static void +Opcode_nop_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf03d; +} + +static void +Opcode_ret_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf00d; +} + +static void +Opcode_s32i_n_Slot_inst16a_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9; +} + +static void +Opcode_rur_threadptr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e70; +} + +static void +Opcode_wur_threadptr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e700; +} + +static void +Opcode_addi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc002; +} + +static void +Opcode_addmi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd002; +} + +static void +Opcode_add_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800000; +} + +static void +Opcode_sub_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc00000; +} + +static void +Opcode_addx2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x900000; +} + +static void +Opcode_addx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa00000; +} + +static void +Opcode_addx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb00000; +} + +static void +Opcode_subx2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd00000; +} + +static void +Opcode_subx4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe00000; +} + +static void +Opcode_subx8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf00000; +} + +static void +Opcode_and_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x100000; +} + +static void +Opcode_or_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x200000; +} + +static void +Opcode_xor_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x300000; +} + +static void +Opcode_beqi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x26; +} + +static void +Opcode_bnei_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x66; +} + +static void +Opcode_bgei_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe6; +} + +static void +Opcode_blti_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa6; +} + +static void +Opcode_bbci_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6007; +} + +static void +Opcode_bbsi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe007; +} + +static void +Opcode_bgeui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf6; +} + +static void +Opcode_bltui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb6; +} + +static void +Opcode_beq_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1007; +} + +static void +Opcode_bne_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9007; +} + +static void +Opcode_bge_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa007; +} + +static void +Opcode_blt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2007; +} + +static void +Opcode_bgeu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb007; +} + +static void +Opcode_bltu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3007; +} + +static void +Opcode_bany_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8007; +} + +static void +Opcode_bnone_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7; +} + +static void +Opcode_ball_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4007; +} + +static void +Opcode_bnall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc007; +} + +static void +Opcode_bbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5007; +} + +static void +Opcode_bbs_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd007; +} + +static void +Opcode_beqz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x16; +} + +static void +Opcode_bnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x56; +} + +static void +Opcode_bgez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd6; +} + +static void +Opcode_bltz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x96; +} + +static void +Opcode_call0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5; +} + +static void +Opcode_callx0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc0; +} + +static void +Opcode_extui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40000; +} + +static void +Opcode_ill_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0; +} + +static void +Opcode_j_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6; +} + +static void +Opcode_jx_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0; +} + +static void +Opcode_l16ui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1002; +} + +static void +Opcode_l16si_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9002; +} + +static void +Opcode_l32i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2002; +} + +static void +Opcode_l32r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1; +} + +static void +Opcode_l8ui_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2; +} + +static void +Opcode_loop_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8076; +} + +static void +Opcode_loopnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9076; +} + +static void +Opcode_loopgtz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa076; +} + +static void +Opcode_movi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa002; +} + +static void +Opcode_moveqz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x830000; +} + +static void +Opcode_movnez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x930000; +} + +static void +Opcode_movltz_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa30000; +} + +static void +Opcode_movgez_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb30000; +} + +static void +Opcode_neg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x600000; +} + +static void +Opcode_abs_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x600100; +} + +static void +Opcode_nop_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20f0; +} + +static void +Opcode_ret_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80; +} + +static void +Opcode_simcall_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5100; +} + +static void +Opcode_s16i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5002; +} + +static void +Opcode_s32i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6002; +} + +static void +Opcode_s32nb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x590000; +} + +static void +Opcode_s8i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4002; +} + +static void +Opcode_ssr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x400000; +} + +static void +Opcode_ssl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x401000; +} + +static void +Opcode_ssa8l_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x402000; +} + +static void +Opcode_ssa8b_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x403000; +} + +static void +Opcode_ssai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x404000; +} + +static void +Opcode_sll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa10000; +} + +static void +Opcode_src_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x810000; +} + +static void +Opcode_srl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x910000; +} + +static void +Opcode_sra_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb10000; +} + +static void +Opcode_slli_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x10000; +} + +static void +Opcode_srai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x210000; +} + +static void +Opcode_srli_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x410000; +} + +static void +Opcode_memw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20c0; +} + +static void +Opcode_extw_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20d0; +} + +static void +Opcode_isync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2000; +} + +static void +Opcode_rsync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2010; +} + +static void +Opcode_esync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2020; +} + +static void +Opcode_dsync_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2030; +} + +static void +Opcode_rsil_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6000; +} + +static void +Opcode_rsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30100; +} + +static void +Opcode_wsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130100; +} + +static void +Opcode_xsr_lend_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610100; +} + +static void +Opcode_rsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30200; +} + +static void +Opcode_wsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130200; +} + +static void +Opcode_xsr_lcount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610200; +} + +static void +Opcode_rsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30000; +} + +static void +Opcode_wsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130000; +} + +static void +Opcode_xsr_lbeg_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610000; +} + +static void +Opcode_rsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30300; +} + +static void +Opcode_wsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130300; +} + +static void +Opcode_xsr_sar_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610300; +} + +static void +Opcode_rsr_memctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36100; +} + +static void +Opcode_wsr_memctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136100; +} + +static void +Opcode_xsr_memctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616100; +} + +static void +Opcode_rsr_litbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30500; +} + +static void +Opcode_wsr_litbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130500; +} + +static void +Opcode_xsr_litbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610500; +} + +static void +Opcode_rsr_configid0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b000; +} + +static void +Opcode_wsr_configid0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b000; +} + +static void +Opcode_rsr_configid1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d000; +} + +static void +Opcode_rsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e600; +} + +static void +Opcode_wsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e600; +} + +static void +Opcode_xsr_ps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e600; +} + +static void +Opcode_rsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b100; +} + +static void +Opcode_wsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b100; +} + +static void +Opcode_xsr_epc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b100; +} + +static void +Opcode_rsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d100; +} + +static void +Opcode_wsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d100; +} + +static void +Opcode_xsr_excsave1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d100; +} + +static void +Opcode_rsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b200; +} + +static void +Opcode_wsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b200; +} + +static void +Opcode_xsr_epc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b200; +} + +static void +Opcode_rsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d200; +} + +static void +Opcode_wsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d200; +} + +static void +Opcode_xsr_excsave2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d200; +} + +static void +Opcode_rsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b300; +} + +static void +Opcode_wsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b300; +} + +static void +Opcode_xsr_epc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b300; +} + +static void +Opcode_rsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d300; +} + +static void +Opcode_wsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d300; +} + +static void +Opcode_xsr_excsave3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d300; +} + +static void +Opcode_rsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b400; +} + +static void +Opcode_wsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b400; +} + +static void +Opcode_xsr_epc4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b400; +} + +static void +Opcode_rsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d400; +} + +static void +Opcode_wsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d400; +} + +static void +Opcode_xsr_excsave4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d400; +} + +static void +Opcode_rsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b500; +} + +static void +Opcode_wsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b500; +} + +static void +Opcode_xsr_epc5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b500; +} + +static void +Opcode_rsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d500; +} + +static void +Opcode_wsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d500; +} + +static void +Opcode_xsr_excsave5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d500; +} + +static void +Opcode_rsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b600; +} + +static void +Opcode_wsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b600; +} + +static void +Opcode_xsr_epc6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b600; +} + +static void +Opcode_rsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d600; +} + +static void +Opcode_wsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d600; +} + +static void +Opcode_xsr_excsave6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d600; +} + +static void +Opcode_rsr_epc7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b700; +} + +static void +Opcode_wsr_epc7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13b700; +} + +static void +Opcode_xsr_epc7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61b700; +} + +static void +Opcode_rsr_excsave7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d700; +} + +static void +Opcode_wsr_excsave7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13d700; +} + +static void +Opcode_xsr_excsave7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61d700; +} + +static void +Opcode_rsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c200; +} + +static void +Opcode_wsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c200; +} + +static void +Opcode_xsr_eps2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c200; +} + +static void +Opcode_rsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c300; +} + +static void +Opcode_wsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c300; +} + +static void +Opcode_xsr_eps3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c300; +} + +static void +Opcode_rsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c400; +} + +static void +Opcode_wsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c400; +} + +static void +Opcode_xsr_eps4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c400; +} + +static void +Opcode_rsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c500; +} + +static void +Opcode_wsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c500; +} + +static void +Opcode_xsr_eps5_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c500; +} + +static void +Opcode_rsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c600; +} + +static void +Opcode_wsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c600; +} + +static void +Opcode_xsr_eps6_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c600; +} + +static void +Opcode_rsr_eps7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c700; +} + +static void +Opcode_wsr_eps7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c700; +} + +static void +Opcode_xsr_eps7_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c700; +} + +static void +Opcode_rsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ee00; +} + +static void +Opcode_wsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ee00; +} + +static void +Opcode_xsr_excvaddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ee00; +} + +static void +Opcode_rsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c000; +} + +static void +Opcode_wsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13c000; +} + +static void +Opcode_xsr_depc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61c000; +} + +static void +Opcode_rsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e800; +} + +static void +Opcode_wsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e800; +} + +static void +Opcode_xsr_exccause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e800; +} + +static void +Opcode_rsr_misc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f400; +} + +static void +Opcode_wsr_misc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f400; +} + +static void +Opcode_xsr_misc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f400; +} + +static void +Opcode_rsr_misc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f500; +} + +static void +Opcode_wsr_misc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f500; +} + +static void +Opcode_xsr_misc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f500; +} + +static void +Opcode_rsr_misc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f600; +} + +static void +Opcode_wsr_misc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f600; +} + +static void +Opcode_xsr_misc2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f600; +} + +static void +Opcode_rsr_misc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f700; +} + +static void +Opcode_wsr_misc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f700; +} + +static void +Opcode_xsr_misc3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f700; +} + +static void +Opcode_rsr_prid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3eb00; +} + +static void +Opcode_rsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e700; +} + +static void +Opcode_wsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e700; +} + +static void +Opcode_xsr_vecbase_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e700; +} + +static void +Opcode_mul16u_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc10000; +} + +static void +Opcode_mul16s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd10000; +} + +static void +Opcode_mull_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x820000; +} + +static void +Opcode_muluh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa20000; +} + +static void +Opcode_mulsh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb20000; +} + +static void +Opcode_mul_aa_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x740004; +} + +static void +Opcode_mul_aa_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x750004; +} + +static void +Opcode_mul_aa_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x760004; +} + +static void +Opcode_mul_aa_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x770004; +} + +static void +Opcode_umul_aa_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x700004; +} + +static void +Opcode_umul_aa_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x710004; +} + +static void +Opcode_umul_aa_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x720004; +} + +static void +Opcode_umul_aa_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x730004; +} + +static void +Opcode_mul_ad_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x340004; +} + +static void +Opcode_mul_ad_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x350004; +} + +static void +Opcode_mul_ad_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x360004; +} + +static void +Opcode_mul_ad_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x370004; +} + +static void +Opcode_mul_da_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x640004; +} + +static void +Opcode_mul_da_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x650004; +} + +static void +Opcode_mul_da_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x660004; +} + +static void +Opcode_mul_da_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x670004; +} + +static void +Opcode_mul_dd_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x240004; +} + +static void +Opcode_mul_dd_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x250004; +} + +static void +Opcode_mul_dd_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x260004; +} + +static void +Opcode_mul_dd_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x270004; +} + +static void +Opcode_mula_aa_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x780004; +} + +static void +Opcode_mula_aa_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x790004; +} + +static void +Opcode_mula_aa_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7a0004; +} + +static void +Opcode_mula_aa_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7b0004; +} + +static void +Opcode_muls_aa_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7c0004; +} + +static void +Opcode_muls_aa_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7d0004; +} + +static void +Opcode_muls_aa_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7e0004; +} + +static void +Opcode_muls_aa_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7f0004; +} + +static void +Opcode_mula_ad_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x380004; +} + +static void +Opcode_mula_ad_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x390004; +} + +static void +Opcode_mula_ad_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a0004; +} + +static void +Opcode_mula_ad_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3b0004; +} + +static void +Opcode_muls_ad_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3c0004; +} + +static void +Opcode_muls_ad_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3d0004; +} + +static void +Opcode_muls_ad_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e0004; +} + +static void +Opcode_muls_ad_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f0004; +} + +static void +Opcode_mula_da_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x680004; +} + +static void +Opcode_mula_da_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x690004; +} + +static void +Opcode_mula_da_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6a0004; +} + +static void +Opcode_mula_da_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6b0004; +} + +static void +Opcode_muls_da_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6c0004; +} + +static void +Opcode_muls_da_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6d0004; +} + +static void +Opcode_muls_da_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6e0004; +} + +static void +Opcode_muls_da_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x6f0004; +} + +static void +Opcode_mula_dd_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x280004; +} + +static void +Opcode_mula_dd_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x290004; +} + +static void +Opcode_mula_dd_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2a0004; +} + +static void +Opcode_mula_dd_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2b0004; +} + +static void +Opcode_muls_dd_ll_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2c0004; +} + +static void +Opcode_muls_dd_hl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2d0004; +} + +static void +Opcode_muls_dd_lh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e0004; +} + +static void +Opcode_muls_dd_hh_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2f0004; +} + +static void +Opcode_mula_da_ll_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x580004; +} + +static void +Opcode_mula_da_ll_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x480004; +} + +static void +Opcode_mula_da_hl_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x590004; +} + +static void +Opcode_mula_da_hl_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x490004; +} + +static void +Opcode_mula_da_lh_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5a0004; +} + +static void +Opcode_mula_da_lh_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4a0004; +} + +static void +Opcode_mula_da_hh_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x5b0004; +} + +static void +Opcode_mula_da_hh_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4b0004; +} + +static void +Opcode_mula_dd_ll_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x180004; +} + +static void +Opcode_mula_dd_ll_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x80004; +} + +static void +Opcode_mula_dd_hl_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x190004; +} + +static void +Opcode_mula_dd_hl_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x90004; +} + +static void +Opcode_mula_dd_lh_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1a0004; +} + +static void +Opcode_mula_dd_lh_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa0004; +} + +static void +Opcode_mula_dd_hh_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1b0004; +} + +static void +Opcode_mula_dd_hh_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb0004; +} + +static void +Opcode_lddec_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x900004; +} + +static void +Opcode_ldinc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x800004; +} + +static void +Opcode_rsr_m0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32000; +} + +static void +Opcode_wsr_m0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132000; +} + +static void +Opcode_xsr_m0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x612000; +} + +static void +Opcode_rsr_m1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32100; +} + +static void +Opcode_wsr_m1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132100; +} + +static void +Opcode_xsr_m1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x612100; +} + +static void +Opcode_rsr_m2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32200; +} + +static void +Opcode_wsr_m2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132200; +} + +static void +Opcode_xsr_m2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x612200; +} + +static void +Opcode_rsr_m3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x32300; +} + +static void +Opcode_wsr_m3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x132300; +} + +static void +Opcode_xsr_m3_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x612300; +} + +static void +Opcode_rsr_acclo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x31000; +} + +static void +Opcode_wsr_acclo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x131000; +} + +static void +Opcode_xsr_acclo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x611000; +} + +static void +Opcode_rsr_acchi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x31100; +} + +static void +Opcode_wsr_acchi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x131100; +} + +static void +Opcode_xsr_acchi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x611100; +} + +static void +Opcode_rfi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3010; +} + +static void +Opcode_waiti_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x7000; +} + +static void +Opcode_rsr_interrupt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e200; +} + +static void +Opcode_wsr_intset_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e200; +} + +static void +Opcode_wsr_intclear_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e300; +} + +static void +Opcode_rsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e400; +} + +static void +Opcode_wsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e400; +} + +static void +Opcode_xsr_intenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e400; +} + +static void +Opcode_break_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4000; +} + +static void +Opcode_break_n_Slot_inst16b_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf02d; +} + +static void +Opcode_rsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39000; +} + +static void +Opcode_wsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x139000; +} + +static void +Opcode_xsr_dbreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x619000; +} + +static void +Opcode_rsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a000; +} + +static void +Opcode_wsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13a000; +} + +static void +Opcode_xsr_dbreakc0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61a000; +} + +static void +Opcode_rsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x39100; +} + +static void +Opcode_wsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x139100; +} + +static void +Opcode_xsr_dbreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x619100; +} + +static void +Opcode_rsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3a100; +} + +static void +Opcode_wsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13a100; +} + +static void +Opcode_xsr_dbreakc1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61a100; +} + +static void +Opcode_rsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38000; +} + +static void +Opcode_wsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x138000; +} + +static void +Opcode_xsr_ibreaka0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x618000; +} + +static void +Opcode_rsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x38100; +} + +static void +Opcode_wsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x138100; +} + +static void +Opcode_xsr_ibreaka1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x618100; +} + +static void +Opcode_rsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36000; +} + +static void +Opcode_wsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136000; +} + +static void +Opcode_xsr_ibreakenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616000; +} + +static void +Opcode_rsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e900; +} + +static void +Opcode_wsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e900; +} + +static void +Opcode_xsr_debugcause_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e900; +} + +static void +Opcode_rsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ec00; +} + +static void +Opcode_wsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ec00; +} + +static void +Opcode_xsr_icount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ec00; +} + +static void +Opcode_rsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ed00; +} + +static void +Opcode_wsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ed00; +} + +static void +Opcode_xsr_icountlevel_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ed00; +} + +static void +Opcode_rsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36800; +} + +static void +Opcode_wsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136800; +} + +static void +Opcode_xsr_ddr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616800; +} + +static void +Opcode_lddr32_p_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70e0; +} + +static void +Opcode_sddr32_p_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x70f0; +} + +static void +Opcode_rfdo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1e000; +} + +static void +Opcode_rfdd_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf1e010; +} + +static void +Opcode_wsr_mmid_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x135900; +} + +static void +Opcode_andb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x20000; +} + +static void +Opcode_andbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x120000; +} + +static void +Opcode_orb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x220000; +} + +static void +Opcode_orbc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x320000; +} + +static void +Opcode_xorb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x420000; +} + +static void +Opcode_any4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8000; +} + +static void +Opcode_all4_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x9000; +} + +static void +Opcode_any8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xa000; +} + +static void +Opcode_all8_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb000; +} + +static void +Opcode_bf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x76; +} + +static void +Opcode_bt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1076; +} + +static void +Opcode_movf_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc30000; +} + +static void +Opcode_movt_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd30000; +} + +static void +Opcode_rsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30400; +} + +static void +Opcode_wsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130400; +} + +static void +Opcode_xsr_br_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610400; +} + +static void +Opcode_rsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3ea00; +} + +static void +Opcode_wsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13ea00; +} + +static void +Opcode_xsr_ccount_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61ea00; +} + +static void +Opcode_rsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f000; +} + +static void +Opcode_wsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f000; +} + +static void +Opcode_xsr_ccompare0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f000; +} + +static void +Opcode_rsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f100; +} + +static void +Opcode_wsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f100; +} + +static void +Opcode_xsr_ccompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f100; +} + +static void +Opcode_rsr_ccompare2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3f200; +} + +static void +Opcode_wsr_ccompare2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13f200; +} + +static void +Opcode_xsr_ccompare2_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61f200; +} + +static void +Opcode_idtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50c000; +} + +static void +Opcode_pdtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50d000; +} + +static void +Opcode_rdtlb0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50b000; +} + +static void +Opcode_rdtlb1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50f000; +} + +static void +Opcode_wdtlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x50e000; +} + +static void +Opcode_iitlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x504000; +} + +static void +Opcode_pitlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x505000; +} + +static void +Opcode_ritlb0_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x503000; +} + +static void +Opcode_ritlb1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x507000; +} + +static void +Opcode_witlb_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x506000; +} + +static void +Opcode_rsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x3e000; +} + +static void +Opcode_wsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x13e000; +} + +static void +Opcode_xsr_cpenable_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x61e000; +} + +static void +Opcode_clamps_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x330000; +} + +static void +Opcode_min_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x430000; +} + +static void +Opcode_max_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x530000; +} + +static void +Opcode_minu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x630000; +} + +static void +Opcode_maxu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x730000; +} + +static void +Opcode_nsa_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40e000; +} + +static void +Opcode_nsau_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x40f000; +} + +static void +Opcode_sext_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x230000; +} + +static void +Opcode_l32ai_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xb002; +} + +static void +Opcode_s32ri_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf002; +} + +static void +Opcode_s32c1i_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe002; +} + +static void +Opcode_rsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x30c00; +} + +static void +Opcode_wsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x130c00; +} + +static void +Opcode_xsr_scompare1_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x610c00; +} + +static void +Opcode_rsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x36300; +} + +static void +Opcode_wsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x136300; +} + +static void +Opcode_xsr_atomctl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x616300; +} + +static void +Opcode_quou_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xc20000; +} + +static void +Opcode_quos_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xd20000; +} + +static void +Opcode_remu_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe20000; +} + +static void +Opcode_rems_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf20000; +} + +static void +Opcode_rer_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x406000; +} + +static void +Opcode_wer_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x407000; +} + +static void +Opcode_f64iter_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x8e0000; +} + +static void +Opcode_f64rnd_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x4e0000; +} + +static void +Opcode_f64addc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfb0000; +} + +static void +Opcode_f64subc_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xfb8000; +} + +static void +Opcode_f64sig_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xed000; +} + +static void +Opcode_f64cmpl_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xeb0000; +} + +static void +Opcode_f64cmph_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf0000; +} + +static void +Opcode_f64norm_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x2e0000; +} + +static void +Opcode_f64sexp_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0x1e0000; +} + +static void +Opcode_rf64r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbce00; +} + +static void +Opcode_wf64r_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xbe000; +} + +static void +Opcode_rur_f64r_lo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30ea0; +} + +static void +Opcode_wur_f64r_lo_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3ea00; +} + +static void +Opcode_rur_f64r_hi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30eb0; +} + +static void +Opcode_wur_f64r_hi_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3eb00; +} + +static void +Opcode_rur_f64s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30ec0; +} + +static void +Opcode_wur_f64s_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3ec00; +} + +static void +Opcode_rur_fcr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e80; +} + +static void +Opcode_wur_fcr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e800; +} + +static void +Opcode_rur_fsr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e90; +} + +static void +Opcode_wur_fsr_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e900; +} + +static void +Opcode_rur_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe30e60; +} + +static void +Opcode_wur_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xf3e600; +} + +static void +Opcode_read_impwire_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe0000; +} + +static void +Opcode_setb_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe1000; +} + +static void +Opcode_clrb_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe1200; +} + +static void +Opcode_wrmsk_expstate_Slot_inst_encode (xtensa_insnbuf slotbuf) +{ + slotbuf[0] = 0xe2000; +} + +static xtensa_opcode_encode_fn Opcode_lsi_encode_fns[] = { + Opcode_lsi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsip_encode_fns[] = { + Opcode_lsip_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsx_encode_fns[] = { + Opcode_lsx_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lsxp_encode_fns[] = { + Opcode_lsxp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssi_encode_fns[] = { + Opcode_ssi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssip_encode_fns[] = { + Opcode_ssip_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssx_encode_fns[] = { + Opcode_ssx_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssxp_encode_fns[] = { + Opcode_ssxp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_abs_s_encode_fns[] = { + Opcode_abs_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_neg_s_encode_fns[] = { + Opcode_neg_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mov_s_encode_fns[] = { + Opcode_mov_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveqz_s_encode_fns[] = { + Opcode_moveqz_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movnez_s_encode_fns[] = { + Opcode_movnez_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movltz_s_encode_fns[] = { + Opcode_movltz_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movgez_s_encode_fns[] = { + Opcode_movgez_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movf_s_encode_fns[] = { + Opcode_movf_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movt_s_encode_fns[] = { + Opcode_movt_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wfr_encode_fns[] = { + Opcode_wfr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfr_encode_fns[] = { + Opcode_rfr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_round_s_encode_fns[] = { + Opcode_round_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ceil_s_encode_fns[] = { + Opcode_ceil_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_floor_s_encode_fns[] = { + Opcode_floor_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_trunc_s_encode_fns[] = { + Opcode_trunc_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_utrunc_s_encode_fns[] = { + Opcode_utrunc_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_float_s_encode_fns[] = { + Opcode_float_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ufloat_s_encode_fns[] = { + Opcode_ufloat_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_un_s_encode_fns[] = { + Opcode_un_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ult_s_encode_fns[] = { + Opcode_ult_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ule_s_encode_fns[] = { + Opcode_ule_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ueq_s_encode_fns[] = { + Opcode_ueq_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_olt_s_encode_fns[] = { + Opcode_olt_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ole_s_encode_fns[] = { + Opcode_ole_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_oeq_s_encode_fns[] = { + Opcode_oeq_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_s_encode_fns[] = { + Opcode_add_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sub_s_encode_fns[] = { + Opcode_sub_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_s_encode_fns[] = { + Opcode_mul_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_madd_s_encode_fns[] = { + Opcode_madd_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_msub_s_encode_fns[] = { + Opcode_msub_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sqrt0_s_encode_fns[] = { + Opcode_sqrt0_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_div0_s_encode_fns[] = { + Opcode_div0_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_recip0_s_encode_fns[] = { + Opcode_recip0_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsqrt0_s_encode_fns[] = { + Opcode_rsqrt0_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_maddn_s_encode_fns[] = { + Opcode_maddn_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_divn_s_encode_fns[] = { + Opcode_divn_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_const_s_encode_fns[] = { + Opcode_const_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nexp01_s_encode_fns[] = { + Opcode_nexp01_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addexp_s_encode_fns[] = { + Opcode_addexp_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addexpm_s_encode_fns[] = { + Opcode_addexpm_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mkdadj_s_encode_fns[] = { + Opcode_mkdadj_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mksadj_s_encode_fns[] = { + Opcode_mksadj_s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_excw_encode_fns[] = { + Opcode_excw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfe_encode_fns[] = { + Opcode_rfe_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfde_encode_fns[] = { + Opcode_rfde_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_syscall_encode_fns[] = { + Opcode_syscall_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call12_encode_fns[] = { + Opcode_call12_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call8_encode_fns[] = { + Opcode_call8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call4_encode_fns[] = { + Opcode_call4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx12_encode_fns[] = { + Opcode_callx12_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx8_encode_fns[] = { + Opcode_callx8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx4_encode_fns[] = { + Opcode_callx4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_entry_encode_fns[] = { + Opcode_entry_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movsp_encode_fns[] = { + Opcode_movsp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rotw_encode_fns[] = { + Opcode_rotw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_retw_encode_fns[] = { + Opcode_retw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_retw_n_encode_fns[] = { + 0, 0, Opcode_retw_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_rfwo_encode_fns[] = { + Opcode_rfwo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfwu_encode_fns[] = { + Opcode_rfwu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32e_encode_fns[] = { + Opcode_l32e_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32e_encode_fns[] = { + Opcode_s32e_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_windowbase_encode_fns[] = { + Opcode_rsr_windowbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_windowbase_encode_fns[] = { + Opcode_wsr_windowbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_windowbase_encode_fns[] = { + Opcode_xsr_windowbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_windowstart_encode_fns[] = { + Opcode_rsr_windowstart_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_windowstart_encode_fns[] = { + Opcode_wsr_windowstart_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_windowstart_encode_fns[] = { + Opcode_xsr_windowstart_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_n_encode_fns[] = { + 0, Opcode_add_n_Slot_inst16a_encode, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addi_n_encode_fns[] = { + 0, Opcode_addi_n_Slot_inst16a_encode, 0 +}; + +static xtensa_opcode_encode_fn Opcode_beqz_n_encode_fns[] = { + 0, 0, Opcode_beqz_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_bnez_n_encode_fns[] = { + 0, 0, Opcode_bnez_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_ill_n_encode_fns[] = { + 0, 0, Opcode_ill_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_l32i_n_encode_fns[] = { + 0, Opcode_l32i_n_Slot_inst16a_encode, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mov_n_encode_fns[] = { + 0, 0, Opcode_mov_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_movi_n_encode_fns[] = { + 0, 0, Opcode_movi_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_nop_n_encode_fns[] = { + 0, 0, Opcode_nop_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_ret_n_encode_fns[] = { + 0, 0, Opcode_ret_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_s32i_n_encode_fns[] = { + 0, Opcode_s32i_n_Slot_inst16a_encode, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_threadptr_encode_fns[] = { + Opcode_rur_threadptr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_threadptr_encode_fns[] = { + Opcode_wur_threadptr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addi_encode_fns[] = { + Opcode_addi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addmi_encode_fns[] = { + Opcode_addmi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_add_encode_fns[] = { + Opcode_add_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sub_encode_fns[] = { + Opcode_sub_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addx2_encode_fns[] = { + Opcode_addx2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addx4_encode_fns[] = { + Opcode_addx4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_addx8_encode_fns[] = { + Opcode_addx8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subx2_encode_fns[] = { + Opcode_subx2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subx4_encode_fns[] = { + Opcode_subx4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_subx8_encode_fns[] = { + Opcode_subx8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_and_encode_fns[] = { + Opcode_and_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_or_encode_fns[] = { + Opcode_or_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xor_encode_fns[] = { + Opcode_xor_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_beqi_encode_fns[] = { + Opcode_beqi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bnei_encode_fns[] = { + Opcode_bnei_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bgei_encode_fns[] = { + Opcode_bgei_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_blti_encode_fns[] = { + Opcode_blti_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bbci_encode_fns[] = { + Opcode_bbci_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bbsi_encode_fns[] = { + Opcode_bbsi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bgeui_encode_fns[] = { + Opcode_bgeui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bltui_encode_fns[] = { + Opcode_bltui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_beq_encode_fns[] = { + Opcode_beq_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bne_encode_fns[] = { + Opcode_bne_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bge_encode_fns[] = { + Opcode_bge_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_blt_encode_fns[] = { + Opcode_blt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bgeu_encode_fns[] = { + Opcode_bgeu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bltu_encode_fns[] = { + Opcode_bltu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bany_encode_fns[] = { + Opcode_bany_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bnone_encode_fns[] = { + Opcode_bnone_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ball_encode_fns[] = { + Opcode_ball_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bnall_encode_fns[] = { + Opcode_bnall_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bbc_encode_fns[] = { + Opcode_bbc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bbs_encode_fns[] = { + Opcode_bbs_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_beqz_encode_fns[] = { + Opcode_beqz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bnez_encode_fns[] = { + Opcode_bnez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bgez_encode_fns[] = { + Opcode_bgez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bltz_encode_fns[] = { + Opcode_bltz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_call0_encode_fns[] = { + Opcode_call0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_callx0_encode_fns[] = { + Opcode_callx0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_extui_encode_fns[] = { + Opcode_extui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ill_encode_fns[] = { + Opcode_ill_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_j_encode_fns[] = { + Opcode_j_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_jx_encode_fns[] = { + Opcode_jx_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l16ui_encode_fns[] = { + Opcode_l16ui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l16si_encode_fns[] = { + Opcode_l16si_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32i_encode_fns[] = { + Opcode_l32i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32r_encode_fns[] = { + Opcode_l32r_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l8ui_encode_fns[] = { + Opcode_l8ui_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_loop_encode_fns[] = { + Opcode_loop_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_loopnez_encode_fns[] = { + Opcode_loopnez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_loopgtz_encode_fns[] = { + Opcode_loopgtz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movi_encode_fns[] = { + Opcode_movi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_moveqz_encode_fns[] = { + Opcode_moveqz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movnez_encode_fns[] = { + Opcode_movnez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movltz_encode_fns[] = { + Opcode_movltz_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movgez_encode_fns[] = { + Opcode_movgez_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_neg_encode_fns[] = { + Opcode_neg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_abs_encode_fns[] = { + Opcode_abs_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nop_encode_fns[] = { + Opcode_nop_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ret_encode_fns[] = { + Opcode_ret_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_simcall_encode_fns[] = { + Opcode_simcall_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s16i_encode_fns[] = { + Opcode_s16i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32i_encode_fns[] = { + Opcode_s32i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32nb_encode_fns[] = { + Opcode_s32nb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s8i_encode_fns[] = { + Opcode_s8i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssr_encode_fns[] = { + Opcode_ssr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssl_encode_fns[] = { + Opcode_ssl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssa8l_encode_fns[] = { + Opcode_ssa8l_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssa8b_encode_fns[] = { + Opcode_ssa8b_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ssai_encode_fns[] = { + Opcode_ssai_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sll_encode_fns[] = { + Opcode_sll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_src_encode_fns[] = { + Opcode_src_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_srl_encode_fns[] = { + Opcode_srl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sra_encode_fns[] = { + Opcode_sra_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_slli_encode_fns[] = { + Opcode_slli_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_srai_encode_fns[] = { + Opcode_srai_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_srli_encode_fns[] = { + Opcode_srli_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_memw_encode_fns[] = { + Opcode_memw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_extw_encode_fns[] = { + Opcode_extw_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_isync_encode_fns[] = { + Opcode_isync_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsync_encode_fns[] = { + Opcode_rsync_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_esync_encode_fns[] = { + Opcode_esync_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_dsync_encode_fns[] = { + Opcode_dsync_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsil_encode_fns[] = { + Opcode_rsil_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lend_encode_fns[] = { + Opcode_rsr_lend_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lend_encode_fns[] = { + Opcode_wsr_lend_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lend_encode_fns[] = { + Opcode_xsr_lend_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lcount_encode_fns[] = { + Opcode_rsr_lcount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lcount_encode_fns[] = { + Opcode_wsr_lcount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lcount_encode_fns[] = { + Opcode_xsr_lcount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_lbeg_encode_fns[] = { + Opcode_rsr_lbeg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_lbeg_encode_fns[] = { + Opcode_wsr_lbeg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_lbeg_encode_fns[] = { + Opcode_xsr_lbeg_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_sar_encode_fns[] = { + Opcode_rsr_sar_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_sar_encode_fns[] = { + Opcode_wsr_sar_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_sar_encode_fns[] = { + Opcode_xsr_sar_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_memctl_encode_fns[] = { + Opcode_rsr_memctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_memctl_encode_fns[] = { + Opcode_wsr_memctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_memctl_encode_fns[] = { + Opcode_xsr_memctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_litbase_encode_fns[] = { + Opcode_rsr_litbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_litbase_encode_fns[] = { + Opcode_wsr_litbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_litbase_encode_fns[] = { + Opcode_xsr_litbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_configid0_encode_fns[] = { + Opcode_rsr_configid0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_configid0_encode_fns[] = { + Opcode_wsr_configid0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_configid1_encode_fns[] = { + Opcode_rsr_configid1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ps_encode_fns[] = { + Opcode_rsr_ps_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ps_encode_fns[] = { + Opcode_wsr_ps_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ps_encode_fns[] = { + Opcode_xsr_ps_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc1_encode_fns[] = { + Opcode_rsr_epc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc1_encode_fns[] = { + Opcode_wsr_epc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc1_encode_fns[] = { + Opcode_xsr_epc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave1_encode_fns[] = { + Opcode_rsr_excsave1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave1_encode_fns[] = { + Opcode_wsr_excsave1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave1_encode_fns[] = { + Opcode_xsr_excsave1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc2_encode_fns[] = { + Opcode_rsr_epc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc2_encode_fns[] = { + Opcode_wsr_epc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc2_encode_fns[] = { + Opcode_xsr_epc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave2_encode_fns[] = { + Opcode_rsr_excsave2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave2_encode_fns[] = { + Opcode_wsr_excsave2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave2_encode_fns[] = { + Opcode_xsr_excsave2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc3_encode_fns[] = { + Opcode_rsr_epc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc3_encode_fns[] = { + Opcode_wsr_epc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc3_encode_fns[] = { + Opcode_xsr_epc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave3_encode_fns[] = { + Opcode_rsr_excsave3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave3_encode_fns[] = { + Opcode_wsr_excsave3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave3_encode_fns[] = { + Opcode_xsr_excsave3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc4_encode_fns[] = { + Opcode_rsr_epc4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc4_encode_fns[] = { + Opcode_wsr_epc4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc4_encode_fns[] = { + Opcode_xsr_epc4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave4_encode_fns[] = { + Opcode_rsr_excsave4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave4_encode_fns[] = { + Opcode_wsr_excsave4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave4_encode_fns[] = { + Opcode_xsr_excsave4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc5_encode_fns[] = { + Opcode_rsr_epc5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc5_encode_fns[] = { + Opcode_wsr_epc5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc5_encode_fns[] = { + Opcode_xsr_epc5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave5_encode_fns[] = { + Opcode_rsr_excsave5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave5_encode_fns[] = { + Opcode_wsr_excsave5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave5_encode_fns[] = { + Opcode_xsr_excsave5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc6_encode_fns[] = { + Opcode_rsr_epc6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc6_encode_fns[] = { + Opcode_wsr_epc6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc6_encode_fns[] = { + Opcode_xsr_epc6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave6_encode_fns[] = { + Opcode_rsr_excsave6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave6_encode_fns[] = { + Opcode_wsr_excsave6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave6_encode_fns[] = { + Opcode_xsr_excsave6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_epc7_encode_fns[] = { + Opcode_rsr_epc7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_epc7_encode_fns[] = { + Opcode_wsr_epc7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_epc7_encode_fns[] = { + Opcode_xsr_epc7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excsave7_encode_fns[] = { + Opcode_rsr_excsave7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excsave7_encode_fns[] = { + Opcode_wsr_excsave7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excsave7_encode_fns[] = { + Opcode_xsr_excsave7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps2_encode_fns[] = { + Opcode_rsr_eps2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps2_encode_fns[] = { + Opcode_wsr_eps2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps2_encode_fns[] = { + Opcode_xsr_eps2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps3_encode_fns[] = { + Opcode_rsr_eps3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps3_encode_fns[] = { + Opcode_wsr_eps3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps3_encode_fns[] = { + Opcode_xsr_eps3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps4_encode_fns[] = { + Opcode_rsr_eps4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps4_encode_fns[] = { + Opcode_wsr_eps4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps4_encode_fns[] = { + Opcode_xsr_eps4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps5_encode_fns[] = { + Opcode_rsr_eps5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps5_encode_fns[] = { + Opcode_wsr_eps5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps5_encode_fns[] = { + Opcode_xsr_eps5_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps6_encode_fns[] = { + Opcode_rsr_eps6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps6_encode_fns[] = { + Opcode_wsr_eps6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps6_encode_fns[] = { + Opcode_xsr_eps6_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_eps7_encode_fns[] = { + Opcode_rsr_eps7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_eps7_encode_fns[] = { + Opcode_wsr_eps7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_eps7_encode_fns[] = { + Opcode_xsr_eps7_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_excvaddr_encode_fns[] = { + Opcode_rsr_excvaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_excvaddr_encode_fns[] = { + Opcode_wsr_excvaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_excvaddr_encode_fns[] = { + Opcode_xsr_excvaddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_depc_encode_fns[] = { + Opcode_rsr_depc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_depc_encode_fns[] = { + Opcode_wsr_depc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_depc_encode_fns[] = { + Opcode_xsr_depc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_exccause_encode_fns[] = { + Opcode_rsr_exccause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_exccause_encode_fns[] = { + Opcode_wsr_exccause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_exccause_encode_fns[] = { + Opcode_xsr_exccause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_misc0_encode_fns[] = { + Opcode_rsr_misc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_misc0_encode_fns[] = { + Opcode_wsr_misc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_misc0_encode_fns[] = { + Opcode_xsr_misc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_misc1_encode_fns[] = { + Opcode_rsr_misc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_misc1_encode_fns[] = { + Opcode_wsr_misc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_misc1_encode_fns[] = { + Opcode_xsr_misc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_misc2_encode_fns[] = { + Opcode_rsr_misc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_misc2_encode_fns[] = { + Opcode_wsr_misc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_misc2_encode_fns[] = { + Opcode_xsr_misc2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_misc3_encode_fns[] = { + Opcode_rsr_misc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_misc3_encode_fns[] = { + Opcode_wsr_misc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_misc3_encode_fns[] = { + Opcode_xsr_misc3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_prid_encode_fns[] = { + Opcode_rsr_prid_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_vecbase_encode_fns[] = { + Opcode_rsr_vecbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_vecbase_encode_fns[] = { + Opcode_wsr_vecbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_vecbase_encode_fns[] = { + Opcode_xsr_vecbase_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul16u_encode_fns[] = { + Opcode_mul16u_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul16s_encode_fns[] = { + Opcode_mul16s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mull_encode_fns[] = { + Opcode_mull_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muluh_encode_fns[] = { + Opcode_muluh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mulsh_encode_fns[] = { + Opcode_mulsh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_aa_ll_encode_fns[] = { + Opcode_mul_aa_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_aa_hl_encode_fns[] = { + Opcode_mul_aa_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_aa_lh_encode_fns[] = { + Opcode_mul_aa_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_aa_hh_encode_fns[] = { + Opcode_mul_aa_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_umul_aa_ll_encode_fns[] = { + Opcode_umul_aa_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_umul_aa_hl_encode_fns[] = { + Opcode_umul_aa_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_umul_aa_lh_encode_fns[] = { + Opcode_umul_aa_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_umul_aa_hh_encode_fns[] = { + Opcode_umul_aa_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_ad_ll_encode_fns[] = { + Opcode_mul_ad_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_ad_hl_encode_fns[] = { + Opcode_mul_ad_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_ad_lh_encode_fns[] = { + Opcode_mul_ad_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_ad_hh_encode_fns[] = { + Opcode_mul_ad_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_da_ll_encode_fns[] = { + Opcode_mul_da_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_da_hl_encode_fns[] = { + Opcode_mul_da_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_da_lh_encode_fns[] = { + Opcode_mul_da_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_da_hh_encode_fns[] = { + Opcode_mul_da_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_dd_ll_encode_fns[] = { + Opcode_mul_dd_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_dd_hl_encode_fns[] = { + Opcode_mul_dd_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_dd_lh_encode_fns[] = { + Opcode_mul_dd_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mul_dd_hh_encode_fns[] = { + Opcode_mul_dd_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_aa_ll_encode_fns[] = { + Opcode_mula_aa_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_aa_hl_encode_fns[] = { + Opcode_mula_aa_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_aa_lh_encode_fns[] = { + Opcode_mula_aa_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_aa_hh_encode_fns[] = { + Opcode_mula_aa_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_aa_ll_encode_fns[] = { + Opcode_muls_aa_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_aa_hl_encode_fns[] = { + Opcode_muls_aa_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_aa_lh_encode_fns[] = { + Opcode_muls_aa_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_aa_hh_encode_fns[] = { + Opcode_muls_aa_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_ad_ll_encode_fns[] = { + Opcode_mula_ad_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_ad_hl_encode_fns[] = { + Opcode_mula_ad_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_ad_lh_encode_fns[] = { + Opcode_mula_ad_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_ad_hh_encode_fns[] = { + Opcode_mula_ad_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_ad_ll_encode_fns[] = { + Opcode_muls_ad_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_ad_hl_encode_fns[] = { + Opcode_muls_ad_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_ad_lh_encode_fns[] = { + Opcode_muls_ad_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_ad_hh_encode_fns[] = { + Opcode_muls_ad_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_ll_encode_fns[] = { + Opcode_mula_da_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hl_encode_fns[] = { + Opcode_mula_da_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_lh_encode_fns[] = { + Opcode_mula_da_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hh_encode_fns[] = { + Opcode_mula_da_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_da_ll_encode_fns[] = { + Opcode_muls_da_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_da_hl_encode_fns[] = { + Opcode_muls_da_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_da_lh_encode_fns[] = { + Opcode_muls_da_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_da_hh_encode_fns[] = { + Opcode_muls_da_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_ll_encode_fns[] = { + Opcode_mula_dd_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hl_encode_fns[] = { + Opcode_mula_dd_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_lh_encode_fns[] = { + Opcode_mula_dd_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hh_encode_fns[] = { + Opcode_mula_dd_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_dd_ll_encode_fns[] = { + Opcode_muls_dd_ll_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_dd_hl_encode_fns[] = { + Opcode_muls_dd_hl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_dd_lh_encode_fns[] = { + Opcode_muls_dd_lh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_muls_dd_hh_encode_fns[] = { + Opcode_muls_dd_hh_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_ll_lddec_encode_fns[] = { + Opcode_mula_da_ll_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_ll_ldinc_encode_fns[] = { + Opcode_mula_da_ll_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hl_lddec_encode_fns[] = { + Opcode_mula_da_hl_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hl_ldinc_encode_fns[] = { + Opcode_mula_da_hl_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_lh_lddec_encode_fns[] = { + Opcode_mula_da_lh_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_lh_ldinc_encode_fns[] = { + Opcode_mula_da_lh_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hh_lddec_encode_fns[] = { + Opcode_mula_da_hh_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_da_hh_ldinc_encode_fns[] = { + Opcode_mula_da_hh_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_ll_lddec_encode_fns[] = { + Opcode_mula_dd_ll_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_ll_ldinc_encode_fns[] = { + Opcode_mula_dd_ll_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hl_lddec_encode_fns[] = { + Opcode_mula_dd_hl_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hl_ldinc_encode_fns[] = { + Opcode_mula_dd_hl_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_lh_lddec_encode_fns[] = { + Opcode_mula_dd_lh_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_lh_ldinc_encode_fns[] = { + Opcode_mula_dd_lh_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hh_lddec_encode_fns[] = { + Opcode_mula_dd_hh_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_mula_dd_hh_ldinc_encode_fns[] = { + Opcode_mula_dd_hh_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lddec_encode_fns[] = { + Opcode_lddec_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ldinc_encode_fns[] = { + Opcode_ldinc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_m0_encode_fns[] = { + Opcode_rsr_m0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_m0_encode_fns[] = { + Opcode_wsr_m0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_m0_encode_fns[] = { + Opcode_xsr_m0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_m1_encode_fns[] = { + Opcode_rsr_m1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_m1_encode_fns[] = { + Opcode_wsr_m1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_m1_encode_fns[] = { + Opcode_xsr_m1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_m2_encode_fns[] = { + Opcode_rsr_m2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_m2_encode_fns[] = { + Opcode_wsr_m2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_m2_encode_fns[] = { + Opcode_xsr_m2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_m3_encode_fns[] = { + Opcode_rsr_m3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_m3_encode_fns[] = { + Opcode_wsr_m3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_m3_encode_fns[] = { + Opcode_xsr_m3_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_acclo_encode_fns[] = { + Opcode_rsr_acclo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_acclo_encode_fns[] = { + Opcode_wsr_acclo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_acclo_encode_fns[] = { + Opcode_xsr_acclo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_acchi_encode_fns[] = { + Opcode_rsr_acchi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_acchi_encode_fns[] = { + Opcode_wsr_acchi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_acchi_encode_fns[] = { + Opcode_xsr_acchi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfi_encode_fns[] = { + Opcode_rfi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_waiti_encode_fns[] = { + Opcode_waiti_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_interrupt_encode_fns[] = { + Opcode_rsr_interrupt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intset_encode_fns[] = { + Opcode_wsr_intset_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intclear_encode_fns[] = { + Opcode_wsr_intclear_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_intenable_encode_fns[] = { + Opcode_rsr_intenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_intenable_encode_fns[] = { + Opcode_wsr_intenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_intenable_encode_fns[] = { + Opcode_xsr_intenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_break_encode_fns[] = { + Opcode_break_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_break_n_encode_fns[] = { + 0, 0, Opcode_break_n_Slot_inst16b_encode +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreaka0_encode_fns[] = { + Opcode_rsr_dbreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreaka0_encode_fns[] = { + Opcode_wsr_dbreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreaka0_encode_fns[] = { + Opcode_xsr_dbreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreakc0_encode_fns[] = { + Opcode_rsr_dbreakc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreakc0_encode_fns[] = { + Opcode_wsr_dbreakc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreakc0_encode_fns[] = { + Opcode_xsr_dbreakc0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreaka1_encode_fns[] = { + Opcode_rsr_dbreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreaka1_encode_fns[] = { + Opcode_wsr_dbreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreaka1_encode_fns[] = { + Opcode_xsr_dbreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_dbreakc1_encode_fns[] = { + Opcode_rsr_dbreakc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_dbreakc1_encode_fns[] = { + Opcode_wsr_dbreakc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_dbreakc1_encode_fns[] = { + Opcode_xsr_dbreakc1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreaka0_encode_fns[] = { + Opcode_rsr_ibreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreaka0_encode_fns[] = { + Opcode_wsr_ibreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreaka0_encode_fns[] = { + Opcode_xsr_ibreaka0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreaka1_encode_fns[] = { + Opcode_rsr_ibreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreaka1_encode_fns[] = { + Opcode_wsr_ibreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreaka1_encode_fns[] = { + Opcode_xsr_ibreaka1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ibreakenable_encode_fns[] = { + Opcode_rsr_ibreakenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ibreakenable_encode_fns[] = { + Opcode_wsr_ibreakenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ibreakenable_encode_fns[] = { + Opcode_xsr_ibreakenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_debugcause_encode_fns[] = { + Opcode_rsr_debugcause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_debugcause_encode_fns[] = { + Opcode_wsr_debugcause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_debugcause_encode_fns[] = { + Opcode_xsr_debugcause_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_icount_encode_fns[] = { + Opcode_rsr_icount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_icount_encode_fns[] = { + Opcode_wsr_icount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_icount_encode_fns[] = { + Opcode_xsr_icount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_icountlevel_encode_fns[] = { + Opcode_rsr_icountlevel_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_icountlevel_encode_fns[] = { + Opcode_wsr_icountlevel_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_icountlevel_encode_fns[] = { + Opcode_xsr_icountlevel_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ddr_encode_fns[] = { + Opcode_rsr_ddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ddr_encode_fns[] = { + Opcode_wsr_ddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ddr_encode_fns[] = { + Opcode_xsr_ddr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_lddr32_p_encode_fns[] = { + Opcode_lddr32_p_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sddr32_p_encode_fns[] = { + Opcode_sddr32_p_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfdo_encode_fns[] = { + Opcode_rfdo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rfdd_encode_fns[] = { + Opcode_rfdd_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_mmid_encode_fns[] = { + Opcode_wsr_mmid_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_andb_encode_fns[] = { + Opcode_andb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_andbc_encode_fns[] = { + Opcode_andbc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_orb_encode_fns[] = { + Opcode_orb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_orbc_encode_fns[] = { + Opcode_orbc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xorb_encode_fns[] = { + Opcode_xorb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_any4_encode_fns[] = { + Opcode_any4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_all4_encode_fns[] = { + Opcode_all4_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_any8_encode_fns[] = { + Opcode_any8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_all8_encode_fns[] = { + Opcode_all8_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bf_encode_fns[] = { + Opcode_bf_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_bt_encode_fns[] = { + Opcode_bt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movf_encode_fns[] = { + Opcode_movf_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_movt_encode_fns[] = { + Opcode_movt_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_br_encode_fns[] = { + Opcode_rsr_br_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_br_encode_fns[] = { + Opcode_wsr_br_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_br_encode_fns[] = { + Opcode_xsr_br_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccount_encode_fns[] = { + Opcode_rsr_ccount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccount_encode_fns[] = { + Opcode_wsr_ccount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccount_encode_fns[] = { + Opcode_xsr_ccount_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccompare0_encode_fns[] = { + Opcode_rsr_ccompare0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccompare0_encode_fns[] = { + Opcode_wsr_ccompare0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccompare0_encode_fns[] = { + Opcode_xsr_ccompare0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccompare1_encode_fns[] = { + Opcode_rsr_ccompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccompare1_encode_fns[] = { + Opcode_wsr_ccompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccompare1_encode_fns[] = { + Opcode_xsr_ccompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_ccompare2_encode_fns[] = { + Opcode_rsr_ccompare2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_ccompare2_encode_fns[] = { + Opcode_wsr_ccompare2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_ccompare2_encode_fns[] = { + Opcode_xsr_ccompare2_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_idtlb_encode_fns[] = { + Opcode_idtlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pdtlb_encode_fns[] = { + Opcode_pdtlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rdtlb0_encode_fns[] = { + Opcode_rdtlb0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rdtlb1_encode_fns[] = { + Opcode_rdtlb1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wdtlb_encode_fns[] = { + Opcode_wdtlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_iitlb_encode_fns[] = { + Opcode_iitlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_pitlb_encode_fns[] = { + Opcode_pitlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ritlb0_encode_fns[] = { + Opcode_ritlb0_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_ritlb1_encode_fns[] = { + Opcode_ritlb1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_witlb_encode_fns[] = { + Opcode_witlb_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_cpenable_encode_fns[] = { + Opcode_rsr_cpenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_cpenable_encode_fns[] = { + Opcode_wsr_cpenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_cpenable_encode_fns[] = { + Opcode_xsr_cpenable_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_clamps_encode_fns[] = { + Opcode_clamps_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_min_encode_fns[] = { + Opcode_min_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_max_encode_fns[] = { + Opcode_max_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_minu_encode_fns[] = { + Opcode_minu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_maxu_encode_fns[] = { + Opcode_maxu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nsa_encode_fns[] = { + Opcode_nsa_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_nsau_encode_fns[] = { + Opcode_nsau_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_sext_encode_fns[] = { + Opcode_sext_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_l32ai_encode_fns[] = { + Opcode_l32ai_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32ri_encode_fns[] = { + Opcode_s32ri_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_s32c1i_encode_fns[] = { + Opcode_s32c1i_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_scompare1_encode_fns[] = { + Opcode_rsr_scompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_scompare1_encode_fns[] = { + Opcode_wsr_scompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_scompare1_encode_fns[] = { + Opcode_xsr_scompare1_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rsr_atomctl_encode_fns[] = { + Opcode_rsr_atomctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wsr_atomctl_encode_fns[] = { + Opcode_wsr_atomctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_xsr_atomctl_encode_fns[] = { + Opcode_xsr_atomctl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_quou_encode_fns[] = { + Opcode_quou_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_quos_encode_fns[] = { + Opcode_quos_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_remu_encode_fns[] = { + Opcode_remu_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rems_encode_fns[] = { + Opcode_rems_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rer_encode_fns[] = { + Opcode_rer_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wer_encode_fns[] = { + Opcode_wer_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64iter_encode_fns[] = { + Opcode_f64iter_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64rnd_encode_fns[] = { + Opcode_f64rnd_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64addc_encode_fns[] = { + Opcode_f64addc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64subc_encode_fns[] = { + Opcode_f64subc_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64sig_encode_fns[] = { + Opcode_f64sig_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64cmpl_encode_fns[] = { + Opcode_f64cmpl_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64cmph_encode_fns[] = { + Opcode_f64cmph_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64norm_encode_fns[] = { + Opcode_f64norm_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_f64sexp_encode_fns[] = { + Opcode_f64sexp_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rf64r_encode_fns[] = { + Opcode_rf64r_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wf64r_encode_fns[] = { + Opcode_wf64r_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_f64r_lo_encode_fns[] = { + Opcode_rur_f64r_lo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_f64r_lo_encode_fns[] = { + Opcode_wur_f64r_lo_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_f64r_hi_encode_fns[] = { + Opcode_rur_f64r_hi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_f64r_hi_encode_fns[] = { + Opcode_wur_f64r_hi_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_f64s_encode_fns[] = { + Opcode_rur_f64s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_f64s_encode_fns[] = { + Opcode_wur_f64s_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_fcr_encode_fns[] = { + Opcode_rur_fcr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_fcr_encode_fns[] = { + Opcode_wur_fcr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_fsr_encode_fns[] = { + Opcode_rur_fsr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_fsr_encode_fns[] = { + Opcode_wur_fsr_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_rur_expstate_encode_fns[] = { + Opcode_rur_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wur_expstate_encode_fns[] = { + Opcode_wur_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_read_impwire_encode_fns[] = { + Opcode_read_impwire_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_setb_expstate_encode_fns[] = { + Opcode_setb_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_clrb_expstate_encode_fns[] = { + Opcode_clrb_expstate_Slot_inst_encode, 0, 0 +}; + +static xtensa_opcode_encode_fn Opcode_wrmsk_expstate_encode_fns[] = { + Opcode_wrmsk_expstate_Slot_inst_encode, 0, 0 +}; + + +uint32 *bypass_entry(__attribute__((unused)) int i); +uint32 *bypass_entry(__attribute__((unused)) int i) { + return 0; +} + + +/* Opcode table. */ + +static xtensa_opcode_internal opcodes[] = { + { "lsi", ICLASS_LSI, + 0, + Opcode_lsi_encode_fns, 0, 0 }, + { "lsip", ICLASS_LSIP, + 0, + Opcode_lsip_encode_fns, 0, 0 }, + { "lsx", ICLASS_LSX, + 0, + Opcode_lsx_encode_fns, 0, 0 }, + { "lsxp", ICLASS_LSXP, + 0, + Opcode_lsxp_encode_fns, 0, 0 }, + { "ssi", ICLASS_SSI, + 0, + Opcode_ssi_encode_fns, 0, 0 }, + { "ssip", ICLASS_SSIP, + 0, + Opcode_ssip_encode_fns, 0, 0 }, + { "ssx", ICLASS_SSX, + 0, + Opcode_ssx_encode_fns, 0, 0 }, + { "ssxp", ICLASS_SSXP, + 0, + Opcode_ssxp_encode_fns, 0, 0 }, + { "abs.s", ICLASS_ABS_S, + 0, + Opcode_abs_s_encode_fns, 0, 0 }, + { "neg.s", ICLASS_NEG_S, + 0, + Opcode_neg_s_encode_fns, 0, 0 }, + { "mov.s", ICLASS_MOV_S, + 0, + Opcode_mov_s_encode_fns, 0, 0 }, + { "moveqz.s", ICLASS_MOVEQZ_S, + 0, + Opcode_moveqz_s_encode_fns, 0, 0 }, + { "movnez.s", ICLASS_MOVNEZ_S, + 0, + Opcode_movnez_s_encode_fns, 0, 0 }, + { "movltz.s", ICLASS_MOVLTZ_S, + 0, + Opcode_movltz_s_encode_fns, 0, 0 }, + { "movgez.s", ICLASS_MOVGEZ_S, + 0, + Opcode_movgez_s_encode_fns, 0, 0 }, + { "movf.s", ICLASS_MOVF_S, + 0, + Opcode_movf_s_encode_fns, 0, 0 }, + { "movt.s", ICLASS_MOVT_S, + 0, + Opcode_movt_s_encode_fns, 0, 0 }, + { "wfr", ICLASS_WFR, + 0, + Opcode_wfr_encode_fns, 0, 0 }, + { "rfr", ICLASS_RFR, + 0, + Opcode_rfr_encode_fns, 0, 0 }, + { "round.s", ICLASS_ROUND_S, + 0, + Opcode_round_s_encode_fns, 0, 0 }, + { "ceil.s", ICLASS_CEIL_S, + 0, + Opcode_ceil_s_encode_fns, 0, 0 }, + { "floor.s", ICLASS_FLOOR_S, + 0, + Opcode_floor_s_encode_fns, 0, 0 }, + { "trunc.s", ICLASS_TRUNC_S, + 0, + Opcode_trunc_s_encode_fns, 0, 0 }, + { "utrunc.s", ICLASS_UTRUNC_S, + 0, + Opcode_utrunc_s_encode_fns, 0, 0 }, + { "float.s", ICLASS_FLOAT_S, + 0, + Opcode_float_s_encode_fns, 0, 0 }, + { "ufloat.s", ICLASS_UFLOAT_S, + 0, + Opcode_ufloat_s_encode_fns, 0, 0 }, + { "un.s", ICLASS_UN_S, + 0, + Opcode_un_s_encode_fns, 0, 0 }, + { "ult.s", ICLASS_ULT_S, + 0, + Opcode_ult_s_encode_fns, 0, 0 }, + { "ule.s", ICLASS_ULE_S, + 0, + Opcode_ule_s_encode_fns, 0, 0 }, + { "ueq.s", ICLASS_UEQ_S, + 0, + Opcode_ueq_s_encode_fns, 0, 0 }, + { "olt.s", ICLASS_OLT_S, + 0, + Opcode_olt_s_encode_fns, 0, 0 }, + { "ole.s", ICLASS_OLE_S, + 0, + Opcode_ole_s_encode_fns, 0, 0 }, + { "oeq.s", ICLASS_OEQ_S, + 0, + Opcode_oeq_s_encode_fns, 0, 0 }, + { "add.s", ICLASS_ADD_S, + 0, + Opcode_add_s_encode_fns, 0, 0 }, + { "sub.s", ICLASS_SUB_S, + 0, + Opcode_sub_s_encode_fns, 0, 0 }, + { "mul.s", ICLASS_MUL_S, + 0, + Opcode_mul_s_encode_fns, 0, 0 }, + { "madd.s", ICLASS_MADD_S, + 0, + Opcode_madd_s_encode_fns, 0, 0 }, + { "msub.s", ICLASS_MSUB_S, + 0, + Opcode_msub_s_encode_fns, 0, 0 }, + { "sqrt0.s", ICLASS_SQRT0_S, + 0, + Opcode_sqrt0_s_encode_fns, 0, 0 }, + { "div0.s", ICLASS_DIV0_S, + 0, + Opcode_div0_s_encode_fns, 0, 0 }, + { "recip0.s", ICLASS_RECIP0_S, + 0, + Opcode_recip0_s_encode_fns, 0, 0 }, + { "rsqrt0.s", ICLASS_RSQRT0_S, + 0, + Opcode_rsqrt0_s_encode_fns, 0, 0 }, + { "maddn.s", ICLASS_MADDN_S, + 0, + Opcode_maddn_s_encode_fns, 0, 0 }, + { "divn.s", ICLASS_DIVN_S, + 0, + Opcode_divn_s_encode_fns, 0, 0 }, + { "const.s", ICLASS_CONST_S, + 0, + Opcode_const_s_encode_fns, 0, 0 }, + { "nexp01.s", ICLASS_NEXP01_S, + 0, + Opcode_nexp01_s_encode_fns, 0, 0 }, + { "addexp.s", ICLASS_ADDEXP_S, + 0, + Opcode_addexp_s_encode_fns, 0, 0 }, + { "addexpm.s", ICLASS_ADDEXPM_S, + 0, + Opcode_addexpm_s_encode_fns, 0, 0 }, + { "mkdadj.s", ICLASS_MKDADJ_S, + 0, + Opcode_mkdadj_s_encode_fns, 0, 0 }, + { "mksadj.s", ICLASS_MKSADJ_S, + 0, + Opcode_mksadj_s_encode_fns, 0, 0 }, + { "excw", ICLASS_xt_iclass_excw, + 0, + Opcode_excw_encode_fns, 0, 0 }, + { "rfe", ICLASS_xt_iclass_rfe, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfe_encode_fns, 0, 0 }, + { "rfde", ICLASS_xt_iclass_rfde, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfde_encode_fns, 0, 0 }, + { "syscall", ICLASS_xt_iclass_syscall, + 0, + Opcode_syscall_encode_fns, 0, 0 }, + { "call12", ICLASS_xt_iclass_call12, + XTENSA_OPCODE_IS_CALL, + Opcode_call12_encode_fns, 0, 0 }, + { "call8", ICLASS_xt_iclass_call8, + XTENSA_OPCODE_IS_CALL, + Opcode_call8_encode_fns, 0, 0 }, + { "call4", ICLASS_xt_iclass_call4, + XTENSA_OPCODE_IS_CALL, + Opcode_call4_encode_fns, 0, 0 }, + { "callx12", ICLASS_xt_iclass_callx12, + XTENSA_OPCODE_IS_CALL, + Opcode_callx12_encode_fns, 0, 0 }, + { "callx8", ICLASS_xt_iclass_callx8, + XTENSA_OPCODE_IS_CALL, + Opcode_callx8_encode_fns, 0, 0 }, + { "callx4", ICLASS_xt_iclass_callx4, + XTENSA_OPCODE_IS_CALL, + Opcode_callx4_encode_fns, 0, 0 }, + { "entry", ICLASS_xt_iclass_entry, + 0, + Opcode_entry_encode_fns, 0, 0 }, + { "movsp", ICLASS_xt_iclass_movsp, + 0, + Opcode_movsp_encode_fns, 0, 0 }, + { "rotw", ICLASS_xt_iclass_rotw, + 0, + Opcode_rotw_encode_fns, 0, 0 }, + { "retw", ICLASS_xt_iclass_retw, + XTENSA_OPCODE_IS_JUMP, + Opcode_retw_encode_fns, 0, 0 }, + { "retw.n", ICLASS_xt_iclass_retw, + XTENSA_OPCODE_IS_JUMP, + Opcode_retw_n_encode_fns, 0, 0 }, + { "rfwo", ICLASS_xt_iclass_rfwou, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfwo_encode_fns, 0, 0 }, + { "rfwu", ICLASS_xt_iclass_rfwou, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfwu_encode_fns, 0, 0 }, + { "l32e", ICLASS_xt_iclass_l32e, + 0, + Opcode_l32e_encode_fns, 0, 0 }, + { "s32e", ICLASS_xt_iclass_s32e, + 0, + Opcode_s32e_encode_fns, 0, 0 }, + { "rsr.windowbase", ICLASS_xt_iclass_rsr_windowbase, + 0, + Opcode_rsr_windowbase_encode_fns, 0, 0 }, + { "wsr.windowbase", ICLASS_xt_iclass_wsr_windowbase, + 0, + Opcode_wsr_windowbase_encode_fns, 0, 0 }, + { "xsr.windowbase", ICLASS_xt_iclass_xsr_windowbase, + 0, + Opcode_xsr_windowbase_encode_fns, 0, 0 }, + { "rsr.windowstart", ICLASS_xt_iclass_rsr_windowstart, + 0, + Opcode_rsr_windowstart_encode_fns, 0, 0 }, + { "wsr.windowstart", ICLASS_xt_iclass_wsr_windowstart, + 0, + Opcode_wsr_windowstart_encode_fns, 0, 0 }, + { "xsr.windowstart", ICLASS_xt_iclass_xsr_windowstart, + 0, + Opcode_xsr_windowstart_encode_fns, 0, 0 }, + { "add.n", ICLASS_xt_iclass_add_n, + 0, + Opcode_add_n_encode_fns, 0, 0 }, + { "addi.n", ICLASS_xt_iclass_addi_n, + 0, + Opcode_addi_n_encode_fns, 0, 0 }, + { "beqz.n", ICLASS_xt_iclass_bz6, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqz_n_encode_fns, 0, 0 }, + { "bnez.n", ICLASS_xt_iclass_bz6, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnez_n_encode_fns, 0, 0 }, + { "ill.n", ICLASS_xt_iclass_ill_n, + 0, + Opcode_ill_n_encode_fns, 0, 0 }, + { "l32i.n", ICLASS_xt_iclass_loadi4, + 0, + Opcode_l32i_n_encode_fns, 0, 0 }, + { "mov.n", ICLASS_xt_iclass_mov_n, + 0, + Opcode_mov_n_encode_fns, 0, 0 }, + { "movi.n", ICLASS_xt_iclass_movi_n, + 0, + Opcode_movi_n_encode_fns, 0, 0 }, + { "nop.n", ICLASS_xt_iclass_nopn, + 0, + Opcode_nop_n_encode_fns, 0, 0 }, + { "ret.n", ICLASS_xt_iclass_retn, + XTENSA_OPCODE_IS_JUMP, + Opcode_ret_n_encode_fns, 0, 0 }, + { "s32i.n", ICLASS_xt_iclass_storei4, + 0, + Opcode_s32i_n_encode_fns, 0, 0 }, + { "rur.threadptr", ICLASS_rur_threadptr, + 0, + Opcode_rur_threadptr_encode_fns, 0, 0 }, + { "wur.threadptr", ICLASS_wur_threadptr, + 0, + Opcode_wur_threadptr_encode_fns, 0, 0 }, + { "addi", ICLASS_xt_iclass_addi, + 0, + Opcode_addi_encode_fns, 0, 0 }, + { "addmi", ICLASS_xt_iclass_addmi, + 0, + Opcode_addmi_encode_fns, 0, 0 }, + { "add", ICLASS_xt_iclass_addsub, + 0, + Opcode_add_encode_fns, 0, 0 }, + { "sub", ICLASS_xt_iclass_addsub, + 0, + Opcode_sub_encode_fns, 0, 0 }, + { "addx2", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx2_encode_fns, 0, 0 }, + { "addx4", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx4_encode_fns, 0, 0 }, + { "addx8", ICLASS_xt_iclass_addsub, + 0, + Opcode_addx8_encode_fns, 0, 0 }, + { "subx2", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx2_encode_fns, 0, 0 }, + { "subx4", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx4_encode_fns, 0, 0 }, + { "subx8", ICLASS_xt_iclass_addsub, + 0, + Opcode_subx8_encode_fns, 0, 0 }, + { "and", ICLASS_xt_iclass_bit, + 0, + Opcode_and_encode_fns, 0, 0 }, + { "or", ICLASS_xt_iclass_bit, + 0, + Opcode_or_encode_fns, 0, 0 }, + { "xor", ICLASS_xt_iclass_bit, + 0, + Opcode_xor_encode_fns, 0, 0 }, + { "beqi", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqi_encode_fns, 0, 0 }, + { "bnei", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnei_encode_fns, 0, 0 }, + { "bgei", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgei_encode_fns, 0, 0 }, + { "blti", ICLASS_xt_iclass_bsi8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_blti_encode_fns, 0, 0 }, + { "bbci", ICLASS_xt_iclass_bsi8b, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbci_encode_fns, 0, 0 }, + { "bbsi", ICLASS_xt_iclass_bsi8b, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbsi_encode_fns, 0, 0 }, + { "bgeui", ICLASS_xt_iclass_bsi8u, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgeui_encode_fns, 0, 0 }, + { "bltui", ICLASS_xt_iclass_bsi8u, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltui_encode_fns, 0, 0 }, + { "beq", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beq_encode_fns, 0, 0 }, + { "bne", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bne_encode_fns, 0, 0 }, + { "bge", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bge_encode_fns, 0, 0 }, + { "blt", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_blt_encode_fns, 0, 0 }, + { "bgeu", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgeu_encode_fns, 0, 0 }, + { "bltu", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltu_encode_fns, 0, 0 }, + { "bany", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bany_encode_fns, 0, 0 }, + { "bnone", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnone_encode_fns, 0, 0 }, + { "ball", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_ball_encode_fns, 0, 0 }, + { "bnall", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnall_encode_fns, 0, 0 }, + { "bbc", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbc_encode_fns, 0, 0 }, + { "bbs", ICLASS_xt_iclass_bst8, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bbs_encode_fns, 0, 0 }, + { "beqz", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_beqz_encode_fns, 0, 0 }, + { "bnez", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bnez_encode_fns, 0, 0 }, + { "bgez", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bgez_encode_fns, 0, 0 }, + { "bltz", ICLASS_xt_iclass_bsz12, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bltz_encode_fns, 0, 0 }, + { "call0", ICLASS_xt_iclass_call0, + XTENSA_OPCODE_IS_CALL, + Opcode_call0_encode_fns, 0, 0 }, + { "callx0", ICLASS_xt_iclass_callx0, + XTENSA_OPCODE_IS_CALL, + Opcode_callx0_encode_fns, 0, 0 }, + { "extui", ICLASS_xt_iclass_exti, + 0, + Opcode_extui_encode_fns, 0, 0 }, + { "ill", ICLASS_xt_iclass_ill, + 0, + Opcode_ill_encode_fns, 0, 0 }, + { "j", ICLASS_xt_iclass_jump, + XTENSA_OPCODE_IS_JUMP, + Opcode_j_encode_fns, 0, 0 }, + { "jx", ICLASS_xt_iclass_jumpx, + XTENSA_OPCODE_IS_JUMP, + Opcode_jx_encode_fns, 0, 0 }, + { "l16ui", ICLASS_xt_iclass_l16ui, + 0, + Opcode_l16ui_encode_fns, 0, 0 }, + { "l16si", ICLASS_xt_iclass_l16si, + 0, + Opcode_l16si_encode_fns, 0, 0 }, + { "l32i", ICLASS_xt_iclass_l32i, + 0, + Opcode_l32i_encode_fns, 0, 0 }, + { "l32r", ICLASS_xt_iclass_l32r, + 0, + Opcode_l32r_encode_fns, 0, 0 }, + { "l8ui", ICLASS_xt_iclass_l8i, + 0, + Opcode_l8ui_encode_fns, 0, 0 }, + { "loop", ICLASS_xt_iclass_loop, + XTENSA_OPCODE_IS_LOOP, + Opcode_loop_encode_fns, 0, 0 }, + { "loopnez", ICLASS_xt_iclass_loopz, + XTENSA_OPCODE_IS_LOOP, + Opcode_loopnez_encode_fns, 0, 0 }, + { "loopgtz", ICLASS_xt_iclass_loopz, + XTENSA_OPCODE_IS_LOOP, + Opcode_loopgtz_encode_fns, 0, 0 }, + { "movi", ICLASS_xt_iclass_movi, + 0, + Opcode_movi_encode_fns, 0, 0 }, + { "moveqz", ICLASS_xt_iclass_movz, + 0, + Opcode_moveqz_encode_fns, 0, 0 }, + { "movnez", ICLASS_xt_iclass_movz, + 0, + Opcode_movnez_encode_fns, 0, 0 }, + { "movltz", ICLASS_xt_iclass_movz, + 0, + Opcode_movltz_encode_fns, 0, 0 }, + { "movgez", ICLASS_xt_iclass_movz, + 0, + Opcode_movgez_encode_fns, 0, 0 }, + { "neg", ICLASS_xt_iclass_neg, + 0, + Opcode_neg_encode_fns, 0, 0 }, + { "abs", ICLASS_xt_iclass_neg, + 0, + Opcode_abs_encode_fns, 0, 0 }, + { "nop", ICLASS_xt_iclass_nop, + 0, + Opcode_nop_encode_fns, 0, 0 }, + { "ret", ICLASS_xt_iclass_return, + XTENSA_OPCODE_IS_JUMP, + Opcode_ret_encode_fns, 0, 0 }, + { "simcall", ICLASS_xt_iclass_simcall, + 0, + Opcode_simcall_encode_fns, 0, 0 }, + { "s16i", ICLASS_xt_iclass_s16i, + 0, + Opcode_s16i_encode_fns, 0, 0 }, + { "s32i", ICLASS_xt_iclass_s32i, + 0, + Opcode_s32i_encode_fns, 0, 0 }, + { "s32nb", ICLASS_xt_iclass_s32nb, + 0, + Opcode_s32nb_encode_fns, 0, 0 }, + { "s8i", ICLASS_xt_iclass_s8i, + 0, + Opcode_s8i_encode_fns, 0, 0 }, + { "ssr", ICLASS_xt_iclass_sar, + 0, + Opcode_ssr_encode_fns, 0, 0 }, + { "ssl", ICLASS_xt_iclass_sar, + 0, + Opcode_ssl_encode_fns, 0, 0 }, + { "ssa8l", ICLASS_xt_iclass_sar, + 0, + Opcode_ssa8l_encode_fns, 0, 0 }, + { "ssa8b", ICLASS_xt_iclass_sar, + 0, + Opcode_ssa8b_encode_fns, 0, 0 }, + { "ssai", ICLASS_xt_iclass_sari, + 0, + Opcode_ssai_encode_fns, 0, 0 }, + { "sll", ICLASS_xt_iclass_shifts, + 0, + Opcode_sll_encode_fns, 0, 0 }, + { "src", ICLASS_xt_iclass_shiftst, + 0, + Opcode_src_encode_fns, 0, 0 }, + { "srl", ICLASS_xt_iclass_shiftt, + 0, + Opcode_srl_encode_fns, 0, 0 }, + { "sra", ICLASS_xt_iclass_shiftt, + 0, + Opcode_sra_encode_fns, 0, 0 }, + { "slli", ICLASS_xt_iclass_slli, + 0, + Opcode_slli_encode_fns, 0, 0 }, + { "srai", ICLASS_xt_iclass_srai, + 0, + Opcode_srai_encode_fns, 0, 0 }, + { "srli", ICLASS_xt_iclass_srli, + 0, + Opcode_srli_encode_fns, 0, 0 }, + { "memw", ICLASS_xt_iclass_memw, + 0, + Opcode_memw_encode_fns, 0, 0 }, + { "extw", ICLASS_xt_iclass_extw, + 0, + Opcode_extw_encode_fns, 0, 0 }, + { "isync", ICLASS_xt_iclass_isync, + 0, + Opcode_isync_encode_fns, 0, 0 }, + { "rsync", ICLASS_xt_iclass_sync, + 0, + Opcode_rsync_encode_fns, 0, 0 }, + { "esync", ICLASS_xt_iclass_sync, + 0, + Opcode_esync_encode_fns, 0, 0 }, + { "dsync", ICLASS_xt_iclass_sync, + 0, + Opcode_dsync_encode_fns, 0, 0 }, + { "rsil", ICLASS_xt_iclass_rsil, + 0, + Opcode_rsil_encode_fns, 0, 0 }, + { "rsr.lend", ICLASS_xt_iclass_rsr_lend, + 0, + Opcode_rsr_lend_encode_fns, 0, 0 }, + { "wsr.lend", ICLASS_xt_iclass_wsr_lend, + 0, + Opcode_wsr_lend_encode_fns, 0, 0 }, + { "xsr.lend", ICLASS_xt_iclass_xsr_lend, + 0, + Opcode_xsr_lend_encode_fns, 0, 0 }, + { "rsr.lcount", ICLASS_xt_iclass_rsr_lcount, + 0, + Opcode_rsr_lcount_encode_fns, 0, 0 }, + { "wsr.lcount", ICLASS_xt_iclass_wsr_lcount, + 0, + Opcode_wsr_lcount_encode_fns, 0, 0 }, + { "xsr.lcount", ICLASS_xt_iclass_xsr_lcount, + 0, + Opcode_xsr_lcount_encode_fns, 0, 0 }, + { "rsr.lbeg", ICLASS_xt_iclass_rsr_lbeg, + 0, + Opcode_rsr_lbeg_encode_fns, 0, 0 }, + { "wsr.lbeg", ICLASS_xt_iclass_wsr_lbeg, + 0, + Opcode_wsr_lbeg_encode_fns, 0, 0 }, + { "xsr.lbeg", ICLASS_xt_iclass_xsr_lbeg, + 0, + Opcode_xsr_lbeg_encode_fns, 0, 0 }, + { "rsr.sar", ICLASS_xt_iclass_rsr_sar, + 0, + Opcode_rsr_sar_encode_fns, 0, 0 }, + { "wsr.sar", ICLASS_xt_iclass_wsr_sar, + 0, + Opcode_wsr_sar_encode_fns, 0, 0 }, + { "xsr.sar", ICLASS_xt_iclass_xsr_sar, + 0, + Opcode_xsr_sar_encode_fns, 0, 0 }, + { "rsr.memctl", ICLASS_xt_iclass_rsr_memctl, + 0, + Opcode_rsr_memctl_encode_fns, 0, 0 }, + { "wsr.memctl", ICLASS_xt_iclass_wsr_memctl, + 0, + Opcode_wsr_memctl_encode_fns, 0, 0 }, + { "xsr.memctl", ICLASS_xt_iclass_xsr_memctl, + 0, + Opcode_xsr_memctl_encode_fns, 0, 0 }, + { "rsr.litbase", ICLASS_xt_iclass_rsr_litbase, + 0, + Opcode_rsr_litbase_encode_fns, 0, 0 }, + { "wsr.litbase", ICLASS_xt_iclass_wsr_litbase, + 0, + Opcode_wsr_litbase_encode_fns, 0, 0 }, + { "xsr.litbase", ICLASS_xt_iclass_xsr_litbase, + 0, + Opcode_xsr_litbase_encode_fns, 0, 0 }, + { "rsr.configid0", ICLASS_xt_iclass_rsr_configid0, + 0, + Opcode_rsr_configid0_encode_fns, 0, 0 }, + { "wsr.configid0", ICLASS_xt_iclass_wsr_configid0, + 0, + Opcode_wsr_configid0_encode_fns, 0, 0 }, + { "rsr.configid1", ICLASS_xt_iclass_rsr_configid1, + 0, + Opcode_rsr_configid1_encode_fns, 0, 0 }, + { "rsr.ps", ICLASS_xt_iclass_rsr_ps, + 0, + Opcode_rsr_ps_encode_fns, 0, 0 }, + { "wsr.ps", ICLASS_xt_iclass_wsr_ps, + 0, + Opcode_wsr_ps_encode_fns, 0, 0 }, + { "xsr.ps", ICLASS_xt_iclass_xsr_ps, + 0, + Opcode_xsr_ps_encode_fns, 0, 0 }, + { "rsr.epc1", ICLASS_xt_iclass_rsr_epc1, + 0, + Opcode_rsr_epc1_encode_fns, 0, 0 }, + { "wsr.epc1", ICLASS_xt_iclass_wsr_epc1, + 0, + Opcode_wsr_epc1_encode_fns, 0, 0 }, + { "xsr.epc1", ICLASS_xt_iclass_xsr_epc1, + 0, + Opcode_xsr_epc1_encode_fns, 0, 0 }, + { "rsr.excsave1", ICLASS_xt_iclass_rsr_excsave1, + 0, + Opcode_rsr_excsave1_encode_fns, 0, 0 }, + { "wsr.excsave1", ICLASS_xt_iclass_wsr_excsave1, + 0, + Opcode_wsr_excsave1_encode_fns, 0, 0 }, + { "xsr.excsave1", ICLASS_xt_iclass_xsr_excsave1, + 0, + Opcode_xsr_excsave1_encode_fns, 0, 0 }, + { "rsr.epc2", ICLASS_xt_iclass_rsr_epc2, + 0, + Opcode_rsr_epc2_encode_fns, 0, 0 }, + { "wsr.epc2", ICLASS_xt_iclass_wsr_epc2, + 0, + Opcode_wsr_epc2_encode_fns, 0, 0 }, + { "xsr.epc2", ICLASS_xt_iclass_xsr_epc2, + 0, + Opcode_xsr_epc2_encode_fns, 0, 0 }, + { "rsr.excsave2", ICLASS_xt_iclass_rsr_excsave2, + 0, + Opcode_rsr_excsave2_encode_fns, 0, 0 }, + { "wsr.excsave2", ICLASS_xt_iclass_wsr_excsave2, + 0, + Opcode_wsr_excsave2_encode_fns, 0, 0 }, + { "xsr.excsave2", ICLASS_xt_iclass_xsr_excsave2, + 0, + Opcode_xsr_excsave2_encode_fns, 0, 0 }, + { "rsr.epc3", ICLASS_xt_iclass_rsr_epc3, + 0, + Opcode_rsr_epc3_encode_fns, 0, 0 }, + { "wsr.epc3", ICLASS_xt_iclass_wsr_epc3, + 0, + Opcode_wsr_epc3_encode_fns, 0, 0 }, + { "xsr.epc3", ICLASS_xt_iclass_xsr_epc3, + 0, + Opcode_xsr_epc3_encode_fns, 0, 0 }, + { "rsr.excsave3", ICLASS_xt_iclass_rsr_excsave3, + 0, + Opcode_rsr_excsave3_encode_fns, 0, 0 }, + { "wsr.excsave3", ICLASS_xt_iclass_wsr_excsave3, + 0, + Opcode_wsr_excsave3_encode_fns, 0, 0 }, + { "xsr.excsave3", ICLASS_xt_iclass_xsr_excsave3, + 0, + Opcode_xsr_excsave3_encode_fns, 0, 0 }, + { "rsr.epc4", ICLASS_xt_iclass_rsr_epc4, + 0, + Opcode_rsr_epc4_encode_fns, 0, 0 }, + { "wsr.epc4", ICLASS_xt_iclass_wsr_epc4, + 0, + Opcode_wsr_epc4_encode_fns, 0, 0 }, + { "xsr.epc4", ICLASS_xt_iclass_xsr_epc4, + 0, + Opcode_xsr_epc4_encode_fns, 0, 0 }, + { "rsr.excsave4", ICLASS_xt_iclass_rsr_excsave4, + 0, + Opcode_rsr_excsave4_encode_fns, 0, 0 }, + { "wsr.excsave4", ICLASS_xt_iclass_wsr_excsave4, + 0, + Opcode_wsr_excsave4_encode_fns, 0, 0 }, + { "xsr.excsave4", ICLASS_xt_iclass_xsr_excsave4, + 0, + Opcode_xsr_excsave4_encode_fns, 0, 0 }, + { "rsr.epc5", ICLASS_xt_iclass_rsr_epc5, + 0, + Opcode_rsr_epc5_encode_fns, 0, 0 }, + { "wsr.epc5", ICLASS_xt_iclass_wsr_epc5, + 0, + Opcode_wsr_epc5_encode_fns, 0, 0 }, + { "xsr.epc5", ICLASS_xt_iclass_xsr_epc5, + 0, + Opcode_xsr_epc5_encode_fns, 0, 0 }, + { "rsr.excsave5", ICLASS_xt_iclass_rsr_excsave5, + 0, + Opcode_rsr_excsave5_encode_fns, 0, 0 }, + { "wsr.excsave5", ICLASS_xt_iclass_wsr_excsave5, + 0, + Opcode_wsr_excsave5_encode_fns, 0, 0 }, + { "xsr.excsave5", ICLASS_xt_iclass_xsr_excsave5, + 0, + Opcode_xsr_excsave5_encode_fns, 0, 0 }, + { "rsr.epc6", ICLASS_xt_iclass_rsr_epc6, + 0, + Opcode_rsr_epc6_encode_fns, 0, 0 }, + { "wsr.epc6", ICLASS_xt_iclass_wsr_epc6, + 0, + Opcode_wsr_epc6_encode_fns, 0, 0 }, + { "xsr.epc6", ICLASS_xt_iclass_xsr_epc6, + 0, + Opcode_xsr_epc6_encode_fns, 0, 0 }, + { "rsr.excsave6", ICLASS_xt_iclass_rsr_excsave6, + 0, + Opcode_rsr_excsave6_encode_fns, 0, 0 }, + { "wsr.excsave6", ICLASS_xt_iclass_wsr_excsave6, + 0, + Opcode_wsr_excsave6_encode_fns, 0, 0 }, + { "xsr.excsave6", ICLASS_xt_iclass_xsr_excsave6, + 0, + Opcode_xsr_excsave6_encode_fns, 0, 0 }, + { "rsr.epc7", ICLASS_xt_iclass_rsr_epc7, + 0, + Opcode_rsr_epc7_encode_fns, 0, 0 }, + { "wsr.epc7", ICLASS_xt_iclass_wsr_epc7, + 0, + Opcode_wsr_epc7_encode_fns, 0, 0 }, + { "xsr.epc7", ICLASS_xt_iclass_xsr_epc7, + 0, + Opcode_xsr_epc7_encode_fns, 0, 0 }, + { "rsr.excsave7", ICLASS_xt_iclass_rsr_excsave7, + 0, + Opcode_rsr_excsave7_encode_fns, 0, 0 }, + { "wsr.excsave7", ICLASS_xt_iclass_wsr_excsave7, + 0, + Opcode_wsr_excsave7_encode_fns, 0, 0 }, + { "xsr.excsave7", ICLASS_xt_iclass_xsr_excsave7, + 0, + Opcode_xsr_excsave7_encode_fns, 0, 0 }, + { "rsr.eps2", ICLASS_xt_iclass_rsr_eps2, + 0, + Opcode_rsr_eps2_encode_fns, 0, 0 }, + { "wsr.eps2", ICLASS_xt_iclass_wsr_eps2, + 0, + Opcode_wsr_eps2_encode_fns, 0, 0 }, + { "xsr.eps2", ICLASS_xt_iclass_xsr_eps2, + 0, + Opcode_xsr_eps2_encode_fns, 0, 0 }, + { "rsr.eps3", ICLASS_xt_iclass_rsr_eps3, + 0, + Opcode_rsr_eps3_encode_fns, 0, 0 }, + { "wsr.eps3", ICLASS_xt_iclass_wsr_eps3, + 0, + Opcode_wsr_eps3_encode_fns, 0, 0 }, + { "xsr.eps3", ICLASS_xt_iclass_xsr_eps3, + 0, + Opcode_xsr_eps3_encode_fns, 0, 0 }, + { "rsr.eps4", ICLASS_xt_iclass_rsr_eps4, + 0, + Opcode_rsr_eps4_encode_fns, 0, 0 }, + { "wsr.eps4", ICLASS_xt_iclass_wsr_eps4, + 0, + Opcode_wsr_eps4_encode_fns, 0, 0 }, + { "xsr.eps4", ICLASS_xt_iclass_xsr_eps4, + 0, + Opcode_xsr_eps4_encode_fns, 0, 0 }, + { "rsr.eps5", ICLASS_xt_iclass_rsr_eps5, + 0, + Opcode_rsr_eps5_encode_fns, 0, 0 }, + { "wsr.eps5", ICLASS_xt_iclass_wsr_eps5, + 0, + Opcode_wsr_eps5_encode_fns, 0, 0 }, + { "xsr.eps5", ICLASS_xt_iclass_xsr_eps5, + 0, + Opcode_xsr_eps5_encode_fns, 0, 0 }, + { "rsr.eps6", ICLASS_xt_iclass_rsr_eps6, + 0, + Opcode_rsr_eps6_encode_fns, 0, 0 }, + { "wsr.eps6", ICLASS_xt_iclass_wsr_eps6, + 0, + Opcode_wsr_eps6_encode_fns, 0, 0 }, + { "xsr.eps6", ICLASS_xt_iclass_xsr_eps6, + 0, + Opcode_xsr_eps6_encode_fns, 0, 0 }, + { "rsr.eps7", ICLASS_xt_iclass_rsr_eps7, + 0, + Opcode_rsr_eps7_encode_fns, 0, 0 }, + { "wsr.eps7", ICLASS_xt_iclass_wsr_eps7, + 0, + Opcode_wsr_eps7_encode_fns, 0, 0 }, + { "xsr.eps7", ICLASS_xt_iclass_xsr_eps7, + 0, + Opcode_xsr_eps7_encode_fns, 0, 0 }, + { "rsr.excvaddr", ICLASS_xt_iclass_rsr_excvaddr, + 0, + Opcode_rsr_excvaddr_encode_fns, 0, 0 }, + { "wsr.excvaddr", ICLASS_xt_iclass_wsr_excvaddr, + 0, + Opcode_wsr_excvaddr_encode_fns, 0, 0 }, + { "xsr.excvaddr", ICLASS_xt_iclass_xsr_excvaddr, + 0, + Opcode_xsr_excvaddr_encode_fns, 0, 0 }, + { "rsr.depc", ICLASS_xt_iclass_rsr_depc, + 0, + Opcode_rsr_depc_encode_fns, 0, 0 }, + { "wsr.depc", ICLASS_xt_iclass_wsr_depc, + 0, + Opcode_wsr_depc_encode_fns, 0, 0 }, + { "xsr.depc", ICLASS_xt_iclass_xsr_depc, + 0, + Opcode_xsr_depc_encode_fns, 0, 0 }, + { "rsr.exccause", ICLASS_xt_iclass_rsr_exccause, + 0, + Opcode_rsr_exccause_encode_fns, 0, 0 }, + { "wsr.exccause", ICLASS_xt_iclass_wsr_exccause, + 0, + Opcode_wsr_exccause_encode_fns, 0, 0 }, + { "xsr.exccause", ICLASS_xt_iclass_xsr_exccause, + 0, + Opcode_xsr_exccause_encode_fns, 0, 0 }, + { "rsr.misc0", ICLASS_xt_iclass_rsr_misc0, + 0, + Opcode_rsr_misc0_encode_fns, 0, 0 }, + { "wsr.misc0", ICLASS_xt_iclass_wsr_misc0, + 0, + Opcode_wsr_misc0_encode_fns, 0, 0 }, + { "xsr.misc0", ICLASS_xt_iclass_xsr_misc0, + 0, + Opcode_xsr_misc0_encode_fns, 0, 0 }, + { "rsr.misc1", ICLASS_xt_iclass_rsr_misc1, + 0, + Opcode_rsr_misc1_encode_fns, 0, 0 }, + { "wsr.misc1", ICLASS_xt_iclass_wsr_misc1, + 0, + Opcode_wsr_misc1_encode_fns, 0, 0 }, + { "xsr.misc1", ICLASS_xt_iclass_xsr_misc1, + 0, + Opcode_xsr_misc1_encode_fns, 0, 0 }, + { "rsr.misc2", ICLASS_xt_iclass_rsr_misc2, + 0, + Opcode_rsr_misc2_encode_fns, 0, 0 }, + { "wsr.misc2", ICLASS_xt_iclass_wsr_misc2, + 0, + Opcode_wsr_misc2_encode_fns, 0, 0 }, + { "xsr.misc2", ICLASS_xt_iclass_xsr_misc2, + 0, + Opcode_xsr_misc2_encode_fns, 0, 0 }, + { "rsr.misc3", ICLASS_xt_iclass_rsr_misc3, + 0, + Opcode_rsr_misc3_encode_fns, 0, 0 }, + { "wsr.misc3", ICLASS_xt_iclass_wsr_misc3, + 0, + Opcode_wsr_misc3_encode_fns, 0, 0 }, + { "xsr.misc3", ICLASS_xt_iclass_xsr_misc3, + 0, + Opcode_xsr_misc3_encode_fns, 0, 0 }, + { "rsr.prid", ICLASS_xt_iclass_rsr_prid, + 0, + Opcode_rsr_prid_encode_fns, 0, 0 }, + { "rsr.vecbase", ICLASS_xt_iclass_rsr_vecbase, + 0, + Opcode_rsr_vecbase_encode_fns, 0, 0 }, + { "wsr.vecbase", ICLASS_xt_iclass_wsr_vecbase, + 0, + Opcode_wsr_vecbase_encode_fns, 0, 0 }, + { "xsr.vecbase", ICLASS_xt_iclass_xsr_vecbase, + 0, + Opcode_xsr_vecbase_encode_fns, 0, 0 }, + { "mul16u", ICLASS_xt_mul16, + 0, + Opcode_mul16u_encode_fns, 0, 0 }, + { "mul16s", ICLASS_xt_mul16, + 0, + Opcode_mul16s_encode_fns, 0, 0 }, + { "mull", ICLASS_xt_mul32, + 0, + Opcode_mull_encode_fns, 0, 0 }, + { "muluh", ICLASS_xt_mul32h, + 0, + Opcode_muluh_encode_fns, 0, 0 }, + { "mulsh", ICLASS_xt_mul32h, + 0, + Opcode_mulsh_encode_fns, 0, 0 }, + { "mul.aa.ll", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_mul_aa_ll_encode_fns, 0, 0 }, + { "mul.aa.hl", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_mul_aa_hl_encode_fns, 0, 0 }, + { "mul.aa.lh", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_mul_aa_lh_encode_fns, 0, 0 }, + { "mul.aa.hh", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_mul_aa_hh_encode_fns, 0, 0 }, + { "umul.aa.ll", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_umul_aa_ll_encode_fns, 0, 0 }, + { "umul.aa.hl", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_umul_aa_hl_encode_fns, 0, 0 }, + { "umul.aa.lh", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_umul_aa_lh_encode_fns, 0, 0 }, + { "umul.aa.hh", ICLASS_xt_iclass_mac16_aa, + 0, + Opcode_umul_aa_hh_encode_fns, 0, 0 }, + { "mul.ad.ll", ICLASS_xt_iclass_mac16_ad, + 0, + Opcode_mul_ad_ll_encode_fns, 0, 0 }, + { "mul.ad.hl", ICLASS_xt_iclass_mac16_ad, + 0, + Opcode_mul_ad_hl_encode_fns, 0, 0 }, + { "mul.ad.lh", ICLASS_xt_iclass_mac16_ad, + 0, + Opcode_mul_ad_lh_encode_fns, 0, 0 }, + { "mul.ad.hh", ICLASS_xt_iclass_mac16_ad, + 0, + Opcode_mul_ad_hh_encode_fns, 0, 0 }, + { "mul.da.ll", ICLASS_xt_iclass_mac16_da, + 0, + Opcode_mul_da_ll_encode_fns, 0, 0 }, + { "mul.da.hl", ICLASS_xt_iclass_mac16_da, + 0, + Opcode_mul_da_hl_encode_fns, 0, 0 }, + { "mul.da.lh", ICLASS_xt_iclass_mac16_da, + 0, + Opcode_mul_da_lh_encode_fns, 0, 0 }, + { "mul.da.hh", ICLASS_xt_iclass_mac16_da, + 0, + Opcode_mul_da_hh_encode_fns, 0, 0 }, + { "mul.dd.ll", ICLASS_xt_iclass_mac16_dd, + 0, + Opcode_mul_dd_ll_encode_fns, 0, 0 }, + { "mul.dd.hl", ICLASS_xt_iclass_mac16_dd, + 0, + Opcode_mul_dd_hl_encode_fns, 0, 0 }, + { "mul.dd.lh", ICLASS_xt_iclass_mac16_dd, + 0, + Opcode_mul_dd_lh_encode_fns, 0, 0 }, + { "mul.dd.hh", ICLASS_xt_iclass_mac16_dd, + 0, + Opcode_mul_dd_hh_encode_fns, 0, 0 }, + { "mula.aa.ll", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_mula_aa_ll_encode_fns, 0, 0 }, + { "mula.aa.hl", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_mula_aa_hl_encode_fns, 0, 0 }, + { "mula.aa.lh", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_mula_aa_lh_encode_fns, 0, 0 }, + { "mula.aa.hh", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_mula_aa_hh_encode_fns, 0, 0 }, + { "muls.aa.ll", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_muls_aa_ll_encode_fns, 0, 0 }, + { "muls.aa.hl", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_muls_aa_hl_encode_fns, 0, 0 }, + { "muls.aa.lh", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_muls_aa_lh_encode_fns, 0, 0 }, + { "muls.aa.hh", ICLASS_xt_iclass_mac16a_aa, + 0, + Opcode_muls_aa_hh_encode_fns, 0, 0 }, + { "mula.ad.ll", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_mula_ad_ll_encode_fns, 0, 0 }, + { "mula.ad.hl", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_mula_ad_hl_encode_fns, 0, 0 }, + { "mula.ad.lh", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_mula_ad_lh_encode_fns, 0, 0 }, + { "mula.ad.hh", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_mula_ad_hh_encode_fns, 0, 0 }, + { "muls.ad.ll", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_muls_ad_ll_encode_fns, 0, 0 }, + { "muls.ad.hl", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_muls_ad_hl_encode_fns, 0, 0 }, + { "muls.ad.lh", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_muls_ad_lh_encode_fns, 0, 0 }, + { "muls.ad.hh", ICLASS_xt_iclass_mac16a_ad, + 0, + Opcode_muls_ad_hh_encode_fns, 0, 0 }, + { "mula.da.ll", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_mula_da_ll_encode_fns, 0, 0 }, + { "mula.da.hl", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_mula_da_hl_encode_fns, 0, 0 }, + { "mula.da.lh", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_mula_da_lh_encode_fns, 0, 0 }, + { "mula.da.hh", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_mula_da_hh_encode_fns, 0, 0 }, + { "muls.da.ll", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_muls_da_ll_encode_fns, 0, 0 }, + { "muls.da.hl", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_muls_da_hl_encode_fns, 0, 0 }, + { "muls.da.lh", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_muls_da_lh_encode_fns, 0, 0 }, + { "muls.da.hh", ICLASS_xt_iclass_mac16a_da, + 0, + Opcode_muls_da_hh_encode_fns, 0, 0 }, + { "mula.dd.ll", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_mula_dd_ll_encode_fns, 0, 0 }, + { "mula.dd.hl", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_mula_dd_hl_encode_fns, 0, 0 }, + { "mula.dd.lh", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_mula_dd_lh_encode_fns, 0, 0 }, + { "mula.dd.hh", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_mula_dd_hh_encode_fns, 0, 0 }, + { "muls.dd.ll", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_muls_dd_ll_encode_fns, 0, 0 }, + { "muls.dd.hl", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_muls_dd_hl_encode_fns, 0, 0 }, + { "muls.dd.lh", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_muls_dd_lh_encode_fns, 0, 0 }, + { "muls.dd.hh", ICLASS_xt_iclass_mac16a_dd, + 0, + Opcode_muls_dd_hh_encode_fns, 0, 0 }, + { "mula.da.ll.lddec", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_ll_lddec_encode_fns, 0, 0 }, + { "mula.da.ll.ldinc", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_ll_ldinc_encode_fns, 0, 0 }, + { "mula.da.hl.lddec", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_hl_lddec_encode_fns, 0, 0 }, + { "mula.da.hl.ldinc", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_hl_ldinc_encode_fns, 0, 0 }, + { "mula.da.lh.lddec", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_lh_lddec_encode_fns, 0, 0 }, + { "mula.da.lh.ldinc", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_lh_ldinc_encode_fns, 0, 0 }, + { "mula.da.hh.lddec", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_hh_lddec_encode_fns, 0, 0 }, + { "mula.da.hh.ldinc", ICLASS_xt_iclass_mac16al_da, + 0, + Opcode_mula_da_hh_ldinc_encode_fns, 0, 0 }, + { "mula.dd.ll.lddec", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_ll_lddec_encode_fns, 0, 0 }, + { "mula.dd.ll.ldinc", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_ll_ldinc_encode_fns, 0, 0 }, + { "mula.dd.hl.lddec", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_hl_lddec_encode_fns, 0, 0 }, + { "mula.dd.hl.ldinc", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_hl_ldinc_encode_fns, 0, 0 }, + { "mula.dd.lh.lddec", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_lh_lddec_encode_fns, 0, 0 }, + { "mula.dd.lh.ldinc", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_lh_ldinc_encode_fns, 0, 0 }, + { "mula.dd.hh.lddec", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_hh_lddec_encode_fns, 0, 0 }, + { "mula.dd.hh.ldinc", ICLASS_xt_iclass_mac16al_dd, + 0, + Opcode_mula_dd_hh_ldinc_encode_fns, 0, 0 }, + { "lddec", ICLASS_xt_iclass_mac16_l, + 0, + Opcode_lddec_encode_fns, 0, 0 }, + { "ldinc", ICLASS_xt_iclass_mac16_l, + 0, + Opcode_ldinc_encode_fns, 0, 0 }, + { "rsr.m0", ICLASS_xt_iclass_rsr_m0, + 0, + Opcode_rsr_m0_encode_fns, 0, 0 }, + { "wsr.m0", ICLASS_xt_iclass_wsr_m0, + 0, + Opcode_wsr_m0_encode_fns, 0, 0 }, + { "xsr.m0", ICLASS_xt_iclass_xsr_m0, + 0, + Opcode_xsr_m0_encode_fns, 0, 0 }, + { "rsr.m1", ICLASS_xt_iclass_rsr_m1, + 0, + Opcode_rsr_m1_encode_fns, 0, 0 }, + { "wsr.m1", ICLASS_xt_iclass_wsr_m1, + 0, + Opcode_wsr_m1_encode_fns, 0, 0 }, + { "xsr.m1", ICLASS_xt_iclass_xsr_m1, + 0, + Opcode_xsr_m1_encode_fns, 0, 0 }, + { "rsr.m2", ICLASS_xt_iclass_rsr_m2, + 0, + Opcode_rsr_m2_encode_fns, 0, 0 }, + { "wsr.m2", ICLASS_xt_iclass_wsr_m2, + 0, + Opcode_wsr_m2_encode_fns, 0, 0 }, + { "xsr.m2", ICLASS_xt_iclass_xsr_m2, + 0, + Opcode_xsr_m2_encode_fns, 0, 0 }, + { "rsr.m3", ICLASS_xt_iclass_rsr_m3, + 0, + Opcode_rsr_m3_encode_fns, 0, 0 }, + { "wsr.m3", ICLASS_xt_iclass_wsr_m3, + 0, + Opcode_wsr_m3_encode_fns, 0, 0 }, + { "xsr.m3", ICLASS_xt_iclass_xsr_m3, + 0, + Opcode_xsr_m3_encode_fns, 0, 0 }, + { "rsr.acclo", ICLASS_xt_iclass_rsr_acclo, + 0, + Opcode_rsr_acclo_encode_fns, 0, 0 }, + { "wsr.acclo", ICLASS_xt_iclass_wsr_acclo, + 0, + Opcode_wsr_acclo_encode_fns, 0, 0 }, + { "xsr.acclo", ICLASS_xt_iclass_xsr_acclo, + 0, + Opcode_xsr_acclo_encode_fns, 0, 0 }, + { "rsr.acchi", ICLASS_xt_iclass_rsr_acchi, + 0, + Opcode_rsr_acchi_encode_fns, 0, 0 }, + { "wsr.acchi", ICLASS_xt_iclass_wsr_acchi, + 0, + Opcode_wsr_acchi_encode_fns, 0, 0 }, + { "xsr.acchi", ICLASS_xt_iclass_xsr_acchi, + 0, + Opcode_xsr_acchi_encode_fns, 0, 0 }, + { "rfi", ICLASS_xt_iclass_rfi, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfi_encode_fns, 0, 0 }, + { "waiti", ICLASS_xt_iclass_wait, + 0, + Opcode_waiti_encode_fns, 0, 0 }, + { "rsr.interrupt", ICLASS_xt_iclass_rsr_interrupt, + 0, + Opcode_rsr_interrupt_encode_fns, 0, 0 }, + { "wsr.intset", ICLASS_xt_iclass_wsr_intset, + 0, + Opcode_wsr_intset_encode_fns, 0, 0 }, + { "wsr.intclear", ICLASS_xt_iclass_wsr_intclear, + 0, + Opcode_wsr_intclear_encode_fns, 0, 0 }, + { "rsr.intenable", ICLASS_xt_iclass_rsr_intenable, + 0, + Opcode_rsr_intenable_encode_fns, 0, 0 }, + { "wsr.intenable", ICLASS_xt_iclass_wsr_intenable, + 0, + Opcode_wsr_intenable_encode_fns, 0, 0 }, + { "xsr.intenable", ICLASS_xt_iclass_xsr_intenable, + 0, + Opcode_xsr_intenable_encode_fns, 0, 0 }, + { "break", ICLASS_xt_iclass_break, + 0, + Opcode_break_encode_fns, 0, 0 }, + { "break.n", ICLASS_xt_iclass_break_n, + 0, + Opcode_break_n_encode_fns, 0, 0 }, + { "rsr.dbreaka0", ICLASS_xt_iclass_rsr_dbreaka0, + 0, + Opcode_rsr_dbreaka0_encode_fns, 0, 0 }, + { "wsr.dbreaka0", ICLASS_xt_iclass_wsr_dbreaka0, + 0, + Opcode_wsr_dbreaka0_encode_fns, 0, 0 }, + { "xsr.dbreaka0", ICLASS_xt_iclass_xsr_dbreaka0, + 0, + Opcode_xsr_dbreaka0_encode_fns, 0, 0 }, + { "rsr.dbreakc0", ICLASS_xt_iclass_rsr_dbreakc0, + 0, + Opcode_rsr_dbreakc0_encode_fns, 0, 0 }, + { "wsr.dbreakc0", ICLASS_xt_iclass_wsr_dbreakc0, + 0, + Opcode_wsr_dbreakc0_encode_fns, 0, 0 }, + { "xsr.dbreakc0", ICLASS_xt_iclass_xsr_dbreakc0, + 0, + Opcode_xsr_dbreakc0_encode_fns, 0, 0 }, + { "rsr.dbreaka1", ICLASS_xt_iclass_rsr_dbreaka1, + 0, + Opcode_rsr_dbreaka1_encode_fns, 0, 0 }, + { "wsr.dbreaka1", ICLASS_xt_iclass_wsr_dbreaka1, + 0, + Opcode_wsr_dbreaka1_encode_fns, 0, 0 }, + { "xsr.dbreaka1", ICLASS_xt_iclass_xsr_dbreaka1, + 0, + Opcode_xsr_dbreaka1_encode_fns, 0, 0 }, + { "rsr.dbreakc1", ICLASS_xt_iclass_rsr_dbreakc1, + 0, + Opcode_rsr_dbreakc1_encode_fns, 0, 0 }, + { "wsr.dbreakc1", ICLASS_xt_iclass_wsr_dbreakc1, + 0, + Opcode_wsr_dbreakc1_encode_fns, 0, 0 }, + { "xsr.dbreakc1", ICLASS_xt_iclass_xsr_dbreakc1, + 0, + Opcode_xsr_dbreakc1_encode_fns, 0, 0 }, + { "rsr.ibreaka0", ICLASS_xt_iclass_rsr_ibreaka0, + 0, + Opcode_rsr_ibreaka0_encode_fns, 0, 0 }, + { "wsr.ibreaka0", ICLASS_xt_iclass_wsr_ibreaka0, + 0, + Opcode_wsr_ibreaka0_encode_fns, 0, 0 }, + { "xsr.ibreaka0", ICLASS_xt_iclass_xsr_ibreaka0, + 0, + Opcode_xsr_ibreaka0_encode_fns, 0, 0 }, + { "rsr.ibreaka1", ICLASS_xt_iclass_rsr_ibreaka1, + 0, + Opcode_rsr_ibreaka1_encode_fns, 0, 0 }, + { "wsr.ibreaka1", ICLASS_xt_iclass_wsr_ibreaka1, + 0, + Opcode_wsr_ibreaka1_encode_fns, 0, 0 }, + { "xsr.ibreaka1", ICLASS_xt_iclass_xsr_ibreaka1, + 0, + Opcode_xsr_ibreaka1_encode_fns, 0, 0 }, + { "rsr.ibreakenable", ICLASS_xt_iclass_rsr_ibreakenable, + 0, + Opcode_rsr_ibreakenable_encode_fns, 0, 0 }, + { "wsr.ibreakenable", ICLASS_xt_iclass_wsr_ibreakenable, + 0, + Opcode_wsr_ibreakenable_encode_fns, 0, 0 }, + { "xsr.ibreakenable", ICLASS_xt_iclass_xsr_ibreakenable, + 0, + Opcode_xsr_ibreakenable_encode_fns, 0, 0 }, + { "rsr.debugcause", ICLASS_xt_iclass_rsr_debugcause, + 0, + Opcode_rsr_debugcause_encode_fns, 0, 0 }, + { "wsr.debugcause", ICLASS_xt_iclass_wsr_debugcause, + 0, + Opcode_wsr_debugcause_encode_fns, 0, 0 }, + { "xsr.debugcause", ICLASS_xt_iclass_xsr_debugcause, + 0, + Opcode_xsr_debugcause_encode_fns, 0, 0 }, + { "rsr.icount", ICLASS_xt_iclass_rsr_icount, + 0, + Opcode_rsr_icount_encode_fns, 0, 0 }, + { "wsr.icount", ICLASS_xt_iclass_wsr_icount, + 0, + Opcode_wsr_icount_encode_fns, 0, 0 }, + { "xsr.icount", ICLASS_xt_iclass_xsr_icount, + 0, + Opcode_xsr_icount_encode_fns, 0, 0 }, + { "rsr.icountlevel", ICLASS_xt_iclass_rsr_icountlevel, + 0, + Opcode_rsr_icountlevel_encode_fns, 0, 0 }, + { "wsr.icountlevel", ICLASS_xt_iclass_wsr_icountlevel, + 0, + Opcode_wsr_icountlevel_encode_fns, 0, 0 }, + { "xsr.icountlevel", ICLASS_xt_iclass_xsr_icountlevel, + 0, + Opcode_xsr_icountlevel_encode_fns, 0, 0 }, + { "rsr.ddr", ICLASS_xt_iclass_rsr_ddr, + 0, + Opcode_rsr_ddr_encode_fns, 0, 0 }, + { "wsr.ddr", ICLASS_xt_iclass_wsr_ddr, + 0, + Opcode_wsr_ddr_encode_fns, 0, 0 }, + { "xsr.ddr", ICLASS_xt_iclass_xsr_ddr, + 0, + Opcode_xsr_ddr_encode_fns, 0, 0 }, + { "lddr32.p", ICLASS_xt_iclass_lddr32_p, + 0, + Opcode_lddr32_p_encode_fns, 0, 0 }, + { "sddr32.p", ICLASS_xt_iclass_sddr32_p, + 0, + Opcode_sddr32_p_encode_fns, 0, 0 }, + { "rfdo", ICLASS_xt_iclass_rfdo, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfdo_encode_fns, 0, 0 }, + { "rfdd", ICLASS_xt_iclass_rfdd, + XTENSA_OPCODE_IS_JUMP, + Opcode_rfdd_encode_fns, 0, 0 }, + { "wsr.mmid", ICLASS_xt_iclass_wsr_mmid, + 0, + Opcode_wsr_mmid_encode_fns, 0, 0 }, + { "andb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_andb_encode_fns, 0, 0 }, + { "andbc", ICLASS_xt_iclass_bbool1, + 0, + Opcode_andbc_encode_fns, 0, 0 }, + { "orb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_orb_encode_fns, 0, 0 }, + { "orbc", ICLASS_xt_iclass_bbool1, + 0, + Opcode_orbc_encode_fns, 0, 0 }, + { "xorb", ICLASS_xt_iclass_bbool1, + 0, + Opcode_xorb_encode_fns, 0, 0 }, + { "any4", ICLASS_xt_iclass_bbool4, + 0, + Opcode_any4_encode_fns, 0, 0 }, + { "all4", ICLASS_xt_iclass_bbool4, + 0, + Opcode_all4_encode_fns, 0, 0 }, + { "any8", ICLASS_xt_iclass_bbool8, + 0, + Opcode_any8_encode_fns, 0, 0 }, + { "all8", ICLASS_xt_iclass_bbool8, + 0, + Opcode_all8_encode_fns, 0, 0 }, + { "bf", ICLASS_xt_iclass_bbranch, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bf_encode_fns, 0, 0 }, + { "bt", ICLASS_xt_iclass_bbranch, + XTENSA_OPCODE_IS_BRANCH, + Opcode_bt_encode_fns, 0, 0 }, + { "movf", ICLASS_xt_iclass_bmove, + 0, + Opcode_movf_encode_fns, 0, 0 }, + { "movt", ICLASS_xt_iclass_bmove, + 0, + Opcode_movt_encode_fns, 0, 0 }, + { "rsr.br", ICLASS_xt_iclass_RSR_BR, + 0, + Opcode_rsr_br_encode_fns, 0, 0 }, + { "wsr.br", ICLASS_xt_iclass_WSR_BR, + 0, + Opcode_wsr_br_encode_fns, 0, 0 }, + { "xsr.br", ICLASS_xt_iclass_XSR_BR, + 0, + Opcode_xsr_br_encode_fns, 0, 0 }, + { "rsr.ccount", ICLASS_xt_iclass_rsr_ccount, + 0, + Opcode_rsr_ccount_encode_fns, 0, 0 }, + { "wsr.ccount", ICLASS_xt_iclass_wsr_ccount, + 0, + Opcode_wsr_ccount_encode_fns, 0, 0 }, + { "xsr.ccount", ICLASS_xt_iclass_xsr_ccount, + 0, + Opcode_xsr_ccount_encode_fns, 0, 0 }, + { "rsr.ccompare0", ICLASS_xt_iclass_rsr_ccompare0, + 0, + Opcode_rsr_ccompare0_encode_fns, 0, 0 }, + { "wsr.ccompare0", ICLASS_xt_iclass_wsr_ccompare0, + 0, + Opcode_wsr_ccompare0_encode_fns, 0, 0 }, + { "xsr.ccompare0", ICLASS_xt_iclass_xsr_ccompare0, + 0, + Opcode_xsr_ccompare0_encode_fns, 0, 0 }, + { "rsr.ccompare1", ICLASS_xt_iclass_rsr_ccompare1, + 0, + Opcode_rsr_ccompare1_encode_fns, 0, 0 }, + { "wsr.ccompare1", ICLASS_xt_iclass_wsr_ccompare1, + 0, + Opcode_wsr_ccompare1_encode_fns, 0, 0 }, + { "xsr.ccompare1", ICLASS_xt_iclass_xsr_ccompare1, + 0, + Opcode_xsr_ccompare1_encode_fns, 0, 0 }, + { "rsr.ccompare2", ICLASS_xt_iclass_rsr_ccompare2, + 0, + Opcode_rsr_ccompare2_encode_fns, 0, 0 }, + { "wsr.ccompare2", ICLASS_xt_iclass_wsr_ccompare2, + 0, + Opcode_wsr_ccompare2_encode_fns, 0, 0 }, + { "xsr.ccompare2", ICLASS_xt_iclass_xsr_ccompare2, + 0, + Opcode_xsr_ccompare2_encode_fns, 0, 0 }, + { "idtlb", ICLASS_xt_iclass_idtlb, + 0, + Opcode_idtlb_encode_fns, 0, 0 }, + { "pdtlb", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_pdtlb_encode_fns, 0, 0 }, + { "rdtlb0", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_rdtlb0_encode_fns, 0, 0 }, + { "rdtlb1", ICLASS_xt_iclass_rdtlb, + 0, + Opcode_rdtlb1_encode_fns, 0, 0 }, + { "wdtlb", ICLASS_xt_iclass_wdtlb, + 0, + Opcode_wdtlb_encode_fns, 0, 0 }, + { "iitlb", ICLASS_xt_iclass_iitlb, + 0, + Opcode_iitlb_encode_fns, 0, 0 }, + { "pitlb", ICLASS_xt_iclass_ritlb, + 0, + Opcode_pitlb_encode_fns, 0, 0 }, + { "ritlb0", ICLASS_xt_iclass_ritlb, + 0, + Opcode_ritlb0_encode_fns, 0, 0 }, + { "ritlb1", ICLASS_xt_iclass_ritlb, + 0, + Opcode_ritlb1_encode_fns, 0, 0 }, + { "witlb", ICLASS_xt_iclass_witlb, + 0, + Opcode_witlb_encode_fns, 0, 0 }, + { "rsr.cpenable", ICLASS_xt_iclass_rsr_cpenable, + 0, + Opcode_rsr_cpenable_encode_fns, 0, 0 }, + { "wsr.cpenable", ICLASS_xt_iclass_wsr_cpenable, + 0, + Opcode_wsr_cpenable_encode_fns, 0, 0 }, + { "xsr.cpenable", ICLASS_xt_iclass_xsr_cpenable, + 0, + Opcode_xsr_cpenable_encode_fns, 0, 0 }, + { "clamps", ICLASS_xt_iclass_clamp, + 0, + Opcode_clamps_encode_fns, 0, 0 }, + { "min", ICLASS_xt_iclass_minmax, + 0, + Opcode_min_encode_fns, 0, 0 }, + { "max", ICLASS_xt_iclass_minmax, + 0, + Opcode_max_encode_fns, 0, 0 }, + { "minu", ICLASS_xt_iclass_minmax, + 0, + Opcode_minu_encode_fns, 0, 0 }, + { "maxu", ICLASS_xt_iclass_minmax, + 0, + Opcode_maxu_encode_fns, 0, 0 }, + { "nsa", ICLASS_xt_iclass_nsa, + 0, + Opcode_nsa_encode_fns, 0, 0 }, + { "nsau", ICLASS_xt_iclass_nsa, + 0, + Opcode_nsau_encode_fns, 0, 0 }, + { "sext", ICLASS_xt_iclass_sx, + 0, + Opcode_sext_encode_fns, 0, 0 }, + { "l32ai", ICLASS_xt_iclass_l32ai, + 0, + Opcode_l32ai_encode_fns, 0, 0 }, + { "s32ri", ICLASS_xt_iclass_s32ri, + 0, + Opcode_s32ri_encode_fns, 0, 0 }, + { "s32c1i", ICLASS_xt_iclass_s32c1i, + 0, + Opcode_s32c1i_encode_fns, 0, 0 }, + { "rsr.scompare1", ICLASS_xt_iclass_rsr_scompare1, + 0, + Opcode_rsr_scompare1_encode_fns, 0, 0 }, + { "wsr.scompare1", ICLASS_xt_iclass_wsr_scompare1, + 0, + Opcode_wsr_scompare1_encode_fns, 0, 0 }, + { "xsr.scompare1", ICLASS_xt_iclass_xsr_scompare1, + 0, + Opcode_xsr_scompare1_encode_fns, 0, 0 }, + { "rsr.atomctl", ICLASS_xt_iclass_rsr_atomctl, + 0, + Opcode_rsr_atomctl_encode_fns, 0, 0 }, + { "wsr.atomctl", ICLASS_xt_iclass_wsr_atomctl, + 0, + Opcode_wsr_atomctl_encode_fns, 0, 0 }, + { "xsr.atomctl", ICLASS_xt_iclass_xsr_atomctl, + 0, + Opcode_xsr_atomctl_encode_fns, 0, 0 }, + { "quou", ICLASS_xt_iclass_div, + 0, + Opcode_quou_encode_fns, 0, 0 }, + { "quos", ICLASS_xt_iclass_div, + 0, + Opcode_quos_encode_fns, 0, 0 }, + { "remu", ICLASS_xt_iclass_div, + 0, + Opcode_remu_encode_fns, 0, 0 }, + { "rems", ICLASS_xt_iclass_div, + 0, + Opcode_rems_encode_fns, 0, 0 }, + { "rer", ICLASS_xt_iclass_rer, + 0, + Opcode_rer_encode_fns, 0, 0 }, + { "wer", ICLASS_xt_iclass_wer, + 0, + Opcode_wer_encode_fns, 0, 0 }, + { "f64iter", ICLASS_iclass_F64ITER, + 0, + Opcode_f64iter_encode_fns, 0, 0 }, + { "f64rnd", ICLASS_iclass_F64RND, + 0, + Opcode_f64rnd_encode_fns, 0, 0 }, + { "f64addc", ICLASS_iclass_F64ADDC_F64SUBC, + 0, + Opcode_f64addc_encode_fns, 0, 0 }, + { "f64subc", ICLASS_iclass_F64ADDC_F64SUBC, + 0, + Opcode_f64subc_encode_fns, 0, 0 }, + { "f64sig", ICLASS_iclass_F64SIG, + 0, + Opcode_f64sig_encode_fns, 0, 0 }, + { "f64cmpl", ICLASS_iclass_F64CMPL, + 0, + Opcode_f64cmpl_encode_fns, 0, 0 }, + { "f64cmph", ICLASS_iclass_F64CMPH, + 0, + Opcode_f64cmph_encode_fns, 0, 0 }, + { "f64norm", ICLASS_iclass_F64NORM, + 0, + Opcode_f64norm_encode_fns, 0, 0 }, + { "f64sexp", ICLASS_iclass_F64SEXP, + 0, + Opcode_f64sexp_encode_fns, 0, 0 }, + { "rf64r", ICLASS_iclass_RF64R, + 0, + Opcode_rf64r_encode_fns, 0, 0 }, + { "wf64r", ICLASS_iclass_WF64R, + 0, + Opcode_wf64r_encode_fns, 0, 0 }, + { "rur.f64r_lo", ICLASS_rur_f64r_lo, + 0, + Opcode_rur_f64r_lo_encode_fns, 0, 0 }, + { "wur.f64r_lo", ICLASS_wur_f64r_lo, + 0, + Opcode_wur_f64r_lo_encode_fns, 0, 0 }, + { "rur.f64r_hi", ICLASS_rur_f64r_hi, + 0, + Opcode_rur_f64r_hi_encode_fns, 0, 0 }, + { "wur.f64r_hi", ICLASS_wur_f64r_hi, + 0, + Opcode_wur_f64r_hi_encode_fns, 0, 0 }, + { "rur.f64s", ICLASS_rur_f64s, + 0, + Opcode_rur_f64s_encode_fns, 0, 0 }, + { "wur.f64s", ICLASS_wur_f64s, + 0, + Opcode_wur_f64s_encode_fns, 0, 0 }, + { "rur.fcr", ICLASS_rur_fcr, + 0, + Opcode_rur_fcr_encode_fns, 0, 0 }, + { "wur.fcr", ICLASS_wur_fcr, + 0, + Opcode_wur_fcr_encode_fns, 0, 0 }, + { "rur.fsr", ICLASS_rur_fsr, + 0, + Opcode_rur_fsr_encode_fns, 0, 0 }, + { "wur.fsr", ICLASS_wur_fsr, + 0, + Opcode_wur_fsr_encode_fns, 0, 0 }, + { "rur.expstate", ICLASS_rur_expstate, + 0, + Opcode_rur_expstate_encode_fns, 0, 0 }, + { "wur.expstate", ICLASS_wur_expstate, + 0, + Opcode_wur_expstate_encode_fns, 0, 0 }, + { "read_impwire", ICLASS_iclass_READ_IMPWIRE, + 0, + Opcode_read_impwire_encode_fns, 0, 0 }, + { "setb_expstate", ICLASS_iclass_SETB_EXPSTATE, + 0, + Opcode_setb_expstate_encode_fns, 0, 0 }, + { "clrb_expstate", ICLASS_iclass_CLRB_EXPSTATE, + 0, + Opcode_clrb_expstate_encode_fns, 0, 0 }, + { "wrmsk_expstate", ICLASS_iclass_WRMSK_EXPSTATE, + 0, + Opcode_wrmsk_expstate_encode_fns, 0, 0 } +}; + +enum xtensa_opcode_id { + OPCODE_LSI, + OPCODE_LSIP, + OPCODE_LSX, + OPCODE_LSXP, + OPCODE_SSI, + OPCODE_SSIP, + OPCODE_SSX, + OPCODE_SSXP, + OPCODE_ABS_S, + OPCODE_NEG_S, + OPCODE_MOV_S, + OPCODE_MOVEQZ_S, + OPCODE_MOVNEZ_S, + OPCODE_MOVLTZ_S, + OPCODE_MOVGEZ_S, + OPCODE_MOVF_S, + OPCODE_MOVT_S, + OPCODE_WFR, + OPCODE_RFR, + OPCODE_ROUND_S, + OPCODE_CEIL_S, + OPCODE_FLOOR_S, + OPCODE_TRUNC_S, + OPCODE_UTRUNC_S, + OPCODE_FLOAT_S, + OPCODE_UFLOAT_S, + OPCODE_UN_S, + OPCODE_ULT_S, + OPCODE_ULE_S, + OPCODE_UEQ_S, + OPCODE_OLT_S, + OPCODE_OLE_S, + OPCODE_OEQ_S, + OPCODE_ADD_S, + OPCODE_SUB_S, + OPCODE_MUL_S, + OPCODE_MADD_S, + OPCODE_MSUB_S, + OPCODE_SQRT0_S, + OPCODE_DIV0_S, + OPCODE_RECIP0_S, + OPCODE_RSQRT0_S, + OPCODE_MADDN_S, + OPCODE_DIVN_S, + OPCODE_CONST_S, + OPCODE_NEXP01_S, + OPCODE_ADDEXP_S, + OPCODE_ADDEXPM_S, + OPCODE_MKDADJ_S, + OPCODE_MKSADJ_S, + OPCODE_EXCW, + OPCODE_RFE, + OPCODE_RFDE, + OPCODE_SYSCALL, + OPCODE_CALL12, + OPCODE_CALL8, + OPCODE_CALL4, + OPCODE_CALLX12, + OPCODE_CALLX8, + OPCODE_CALLX4, + OPCODE_ENTRY, + OPCODE_MOVSP, + OPCODE_ROTW, + OPCODE_RETW, + OPCODE_RETW_N, + OPCODE_RFWO, + OPCODE_RFWU, + OPCODE_L32E, + OPCODE_S32E, + OPCODE_RSR_WINDOWBASE, + OPCODE_WSR_WINDOWBASE, + OPCODE_XSR_WINDOWBASE, + OPCODE_RSR_WINDOWSTART, + OPCODE_WSR_WINDOWSTART, + OPCODE_XSR_WINDOWSTART, + OPCODE_ADD_N, + OPCODE_ADDI_N, + OPCODE_BEQZ_N, + OPCODE_BNEZ_N, + OPCODE_ILL_N, + OPCODE_L32I_N, + OPCODE_MOV_N, + OPCODE_MOVI_N, + OPCODE_NOP_N, + OPCODE_RET_N, + OPCODE_S32I_N, + OPCODE_RUR_THREADPTR, + OPCODE_WUR_THREADPTR, + OPCODE_ADDI, + OPCODE_ADDMI, + OPCODE_ADD, + OPCODE_SUB, + OPCODE_ADDX2, + OPCODE_ADDX4, + OPCODE_ADDX8, + OPCODE_SUBX2, + OPCODE_SUBX4, + OPCODE_SUBX8, + OPCODE_AND, + OPCODE_OR, + OPCODE_XOR, + OPCODE_BEQI, + OPCODE_BNEI, + OPCODE_BGEI, + OPCODE_BLTI, + OPCODE_BBCI, + OPCODE_BBSI, + OPCODE_BGEUI, + OPCODE_BLTUI, + OPCODE_BEQ, + OPCODE_BNE, + OPCODE_BGE, + OPCODE_BLT, + OPCODE_BGEU, + OPCODE_BLTU, + OPCODE_BANY, + OPCODE_BNONE, + OPCODE_BALL, + OPCODE_BNALL, + OPCODE_BBC, + OPCODE_BBS, + OPCODE_BEQZ, + OPCODE_BNEZ, + OPCODE_BGEZ, + OPCODE_BLTZ, + OPCODE_CALL0, + OPCODE_CALLX0, + OPCODE_EXTUI, + OPCODE_ILL, + OPCODE_J, + OPCODE_JX, + OPCODE_L16UI, + OPCODE_L16SI, + OPCODE_L32I, + OPCODE_L32R, + OPCODE_L8UI, + OPCODE_LOOP, + OPCODE_LOOPNEZ, + OPCODE_LOOPGTZ, + OPCODE_MOVI, + OPCODE_MOVEQZ, + OPCODE_MOVNEZ, + OPCODE_MOVLTZ, + OPCODE_MOVGEZ, + OPCODE_NEG, + OPCODE_ABS, + OPCODE_NOP, + OPCODE_RET, + OPCODE_SIMCALL, + OPCODE_S16I, + OPCODE_S32I, + OPCODE_S32NB, + OPCODE_S8I, + OPCODE_SSR, + OPCODE_SSL, + OPCODE_SSA8L, + OPCODE_SSA8B, + OPCODE_SSAI, + OPCODE_SLL, + OPCODE_SRC, + OPCODE_SRL, + OPCODE_SRA, + OPCODE_SLLI, + OPCODE_SRAI, + OPCODE_SRLI, + OPCODE_MEMW, + OPCODE_EXTW, + OPCODE_ISYNC, + OPCODE_RSYNC, + OPCODE_ESYNC, + OPCODE_DSYNC, + OPCODE_RSIL, + OPCODE_RSR_LEND, + OPCODE_WSR_LEND, + OPCODE_XSR_LEND, + OPCODE_RSR_LCOUNT, + OPCODE_WSR_LCOUNT, + OPCODE_XSR_LCOUNT, + OPCODE_RSR_LBEG, + OPCODE_WSR_LBEG, + OPCODE_XSR_LBEG, + OPCODE_RSR_SAR, + OPCODE_WSR_SAR, + OPCODE_XSR_SAR, + OPCODE_RSR_MEMCTL, + OPCODE_WSR_MEMCTL, + OPCODE_XSR_MEMCTL, + OPCODE_RSR_LITBASE, + OPCODE_WSR_LITBASE, + OPCODE_XSR_LITBASE, + OPCODE_RSR_CONFIGID0, + OPCODE_WSR_CONFIGID0, + OPCODE_RSR_CONFIGID1, + OPCODE_RSR_PS, + OPCODE_WSR_PS, + OPCODE_XSR_PS, + OPCODE_RSR_EPC1, + OPCODE_WSR_EPC1, + OPCODE_XSR_EPC1, + OPCODE_RSR_EXCSAVE1, + OPCODE_WSR_EXCSAVE1, + OPCODE_XSR_EXCSAVE1, + OPCODE_RSR_EPC2, + OPCODE_WSR_EPC2, + OPCODE_XSR_EPC2, + OPCODE_RSR_EXCSAVE2, + OPCODE_WSR_EXCSAVE2, + OPCODE_XSR_EXCSAVE2, + OPCODE_RSR_EPC3, + OPCODE_WSR_EPC3, + OPCODE_XSR_EPC3, + OPCODE_RSR_EXCSAVE3, + OPCODE_WSR_EXCSAVE3, + OPCODE_XSR_EXCSAVE3, + OPCODE_RSR_EPC4, + OPCODE_WSR_EPC4, + OPCODE_XSR_EPC4, + OPCODE_RSR_EXCSAVE4, + OPCODE_WSR_EXCSAVE4, + OPCODE_XSR_EXCSAVE4, + OPCODE_RSR_EPC5, + OPCODE_WSR_EPC5, + OPCODE_XSR_EPC5, + OPCODE_RSR_EXCSAVE5, + OPCODE_WSR_EXCSAVE5, + OPCODE_XSR_EXCSAVE5, + OPCODE_RSR_EPC6, + OPCODE_WSR_EPC6, + OPCODE_XSR_EPC6, + OPCODE_RSR_EXCSAVE6, + OPCODE_WSR_EXCSAVE6, + OPCODE_XSR_EXCSAVE6, + OPCODE_RSR_EPC7, + OPCODE_WSR_EPC7, + OPCODE_XSR_EPC7, + OPCODE_RSR_EXCSAVE7, + OPCODE_WSR_EXCSAVE7, + OPCODE_XSR_EXCSAVE7, + OPCODE_RSR_EPS2, + OPCODE_WSR_EPS2, + OPCODE_XSR_EPS2, + OPCODE_RSR_EPS3, + OPCODE_WSR_EPS3, + OPCODE_XSR_EPS3, + OPCODE_RSR_EPS4, + OPCODE_WSR_EPS4, + OPCODE_XSR_EPS4, + OPCODE_RSR_EPS5, + OPCODE_WSR_EPS5, + OPCODE_XSR_EPS5, + OPCODE_RSR_EPS6, + OPCODE_WSR_EPS6, + OPCODE_XSR_EPS6, + OPCODE_RSR_EPS7, + OPCODE_WSR_EPS7, + OPCODE_XSR_EPS7, + OPCODE_RSR_EXCVADDR, + OPCODE_WSR_EXCVADDR, + OPCODE_XSR_EXCVADDR, + OPCODE_RSR_DEPC, + OPCODE_WSR_DEPC, + OPCODE_XSR_DEPC, + OPCODE_RSR_EXCCAUSE, + OPCODE_WSR_EXCCAUSE, + OPCODE_XSR_EXCCAUSE, + OPCODE_RSR_MISC0, + OPCODE_WSR_MISC0, + OPCODE_XSR_MISC0, + OPCODE_RSR_MISC1, + OPCODE_WSR_MISC1, + OPCODE_XSR_MISC1, + OPCODE_RSR_MISC2, + OPCODE_WSR_MISC2, + OPCODE_XSR_MISC2, + OPCODE_RSR_MISC3, + OPCODE_WSR_MISC3, + OPCODE_XSR_MISC3, + OPCODE_RSR_PRID, + OPCODE_RSR_VECBASE, + OPCODE_WSR_VECBASE, + OPCODE_XSR_VECBASE, + OPCODE_MUL16U, + OPCODE_MUL16S, + OPCODE_MULL, + OPCODE_MULUH, + OPCODE_MULSH, + OPCODE_MUL_AA_LL, + OPCODE_MUL_AA_HL, + OPCODE_MUL_AA_LH, + OPCODE_MUL_AA_HH, + OPCODE_UMUL_AA_LL, + OPCODE_UMUL_AA_HL, + OPCODE_UMUL_AA_LH, + OPCODE_UMUL_AA_HH, + OPCODE_MUL_AD_LL, + OPCODE_MUL_AD_HL, + OPCODE_MUL_AD_LH, + OPCODE_MUL_AD_HH, + OPCODE_MUL_DA_LL, + OPCODE_MUL_DA_HL, + OPCODE_MUL_DA_LH, + OPCODE_MUL_DA_HH, + OPCODE_MUL_DD_LL, + OPCODE_MUL_DD_HL, + OPCODE_MUL_DD_LH, + OPCODE_MUL_DD_HH, + OPCODE_MULA_AA_LL, + OPCODE_MULA_AA_HL, + OPCODE_MULA_AA_LH, + OPCODE_MULA_AA_HH, + OPCODE_MULS_AA_LL, + OPCODE_MULS_AA_HL, + OPCODE_MULS_AA_LH, + OPCODE_MULS_AA_HH, + OPCODE_MULA_AD_LL, + OPCODE_MULA_AD_HL, + OPCODE_MULA_AD_LH, + OPCODE_MULA_AD_HH, + OPCODE_MULS_AD_LL, + OPCODE_MULS_AD_HL, + OPCODE_MULS_AD_LH, + OPCODE_MULS_AD_HH, + OPCODE_MULA_DA_LL, + OPCODE_MULA_DA_HL, + OPCODE_MULA_DA_LH, + OPCODE_MULA_DA_HH, + OPCODE_MULS_DA_LL, + OPCODE_MULS_DA_HL, + OPCODE_MULS_DA_LH, + OPCODE_MULS_DA_HH, + OPCODE_MULA_DD_LL, + OPCODE_MULA_DD_HL, + OPCODE_MULA_DD_LH, + OPCODE_MULA_DD_HH, + OPCODE_MULS_DD_LL, + OPCODE_MULS_DD_HL, + OPCODE_MULS_DD_LH, + OPCODE_MULS_DD_HH, + OPCODE_MULA_DA_LL_LDDEC, + OPCODE_MULA_DA_LL_LDINC, + OPCODE_MULA_DA_HL_LDDEC, + OPCODE_MULA_DA_HL_LDINC, + OPCODE_MULA_DA_LH_LDDEC, + OPCODE_MULA_DA_LH_LDINC, + OPCODE_MULA_DA_HH_LDDEC, + OPCODE_MULA_DA_HH_LDINC, + OPCODE_MULA_DD_LL_LDDEC, + OPCODE_MULA_DD_LL_LDINC, + OPCODE_MULA_DD_HL_LDDEC, + OPCODE_MULA_DD_HL_LDINC, + OPCODE_MULA_DD_LH_LDDEC, + OPCODE_MULA_DD_LH_LDINC, + OPCODE_MULA_DD_HH_LDDEC, + OPCODE_MULA_DD_HH_LDINC, + OPCODE_LDDEC, + OPCODE_LDINC, + OPCODE_RSR_M0, + OPCODE_WSR_M0, + OPCODE_XSR_M0, + OPCODE_RSR_M1, + OPCODE_WSR_M1, + OPCODE_XSR_M1, + OPCODE_RSR_M2, + OPCODE_WSR_M2, + OPCODE_XSR_M2, + OPCODE_RSR_M3, + OPCODE_WSR_M3, + OPCODE_XSR_M3, + OPCODE_RSR_ACCLO, + OPCODE_WSR_ACCLO, + OPCODE_XSR_ACCLO, + OPCODE_RSR_ACCHI, + OPCODE_WSR_ACCHI, + OPCODE_XSR_ACCHI, + OPCODE_RFI, + OPCODE_WAITI, + OPCODE_RSR_INTERRUPT, + OPCODE_WSR_INTSET, + OPCODE_WSR_INTCLEAR, + OPCODE_RSR_INTENABLE, + OPCODE_WSR_INTENABLE, + OPCODE_XSR_INTENABLE, + OPCODE_BREAK, + OPCODE_BREAK_N, + OPCODE_RSR_DBREAKA0, + OPCODE_WSR_DBREAKA0, + OPCODE_XSR_DBREAKA0, + OPCODE_RSR_DBREAKC0, + OPCODE_WSR_DBREAKC0, + OPCODE_XSR_DBREAKC0, + OPCODE_RSR_DBREAKA1, + OPCODE_WSR_DBREAKA1, + OPCODE_XSR_DBREAKA1, + OPCODE_RSR_DBREAKC1, + OPCODE_WSR_DBREAKC1, + OPCODE_XSR_DBREAKC1, + OPCODE_RSR_IBREAKA0, + OPCODE_WSR_IBREAKA0, + OPCODE_XSR_IBREAKA0, + OPCODE_RSR_IBREAKA1, + OPCODE_WSR_IBREAKA1, + OPCODE_XSR_IBREAKA1, + OPCODE_RSR_IBREAKENABLE, + OPCODE_WSR_IBREAKENABLE, + OPCODE_XSR_IBREAKENABLE, + OPCODE_RSR_DEBUGCAUSE, + OPCODE_WSR_DEBUGCAUSE, + OPCODE_XSR_DEBUGCAUSE, + OPCODE_RSR_ICOUNT, + OPCODE_WSR_ICOUNT, + OPCODE_XSR_ICOUNT, + OPCODE_RSR_ICOUNTLEVEL, + OPCODE_WSR_ICOUNTLEVEL, + OPCODE_XSR_ICOUNTLEVEL, + OPCODE_RSR_DDR, + OPCODE_WSR_DDR, + OPCODE_XSR_DDR, + OPCODE_LDDR32_P, + OPCODE_SDDR32_P, + OPCODE_RFDO, + OPCODE_RFDD, + OPCODE_WSR_MMID, + OPCODE_ANDB, + OPCODE_ANDBC, + OPCODE_ORB, + OPCODE_ORBC, + OPCODE_XORB, + OPCODE_ANY4, + OPCODE_ALL4, + OPCODE_ANY8, + OPCODE_ALL8, + OPCODE_BF, + OPCODE_BT, + OPCODE_MOVF, + OPCODE_MOVT, + OPCODE_RSR_BR, + OPCODE_WSR_BR, + OPCODE_XSR_BR, + OPCODE_RSR_CCOUNT, + OPCODE_WSR_CCOUNT, + OPCODE_XSR_CCOUNT, + OPCODE_RSR_CCOMPARE0, + OPCODE_WSR_CCOMPARE0, + OPCODE_XSR_CCOMPARE0, + OPCODE_RSR_CCOMPARE1, + OPCODE_WSR_CCOMPARE1, + OPCODE_XSR_CCOMPARE1, + OPCODE_RSR_CCOMPARE2, + OPCODE_WSR_CCOMPARE2, + OPCODE_XSR_CCOMPARE2, + OPCODE_IDTLB, + OPCODE_PDTLB, + OPCODE_RDTLB0, + OPCODE_RDTLB1, + OPCODE_WDTLB, + OPCODE_IITLB, + OPCODE_PITLB, + OPCODE_RITLB0, + OPCODE_RITLB1, + OPCODE_WITLB, + OPCODE_RSR_CPENABLE, + OPCODE_WSR_CPENABLE, + OPCODE_XSR_CPENABLE, + OPCODE_CLAMPS, + OPCODE_MIN, + OPCODE_MAX, + OPCODE_MINU, + OPCODE_MAXU, + OPCODE_NSA, + OPCODE_NSAU, + OPCODE_SEXT, + OPCODE_L32AI, + OPCODE_S32RI, + OPCODE_S32C1I, + OPCODE_RSR_SCOMPARE1, + OPCODE_WSR_SCOMPARE1, + OPCODE_XSR_SCOMPARE1, + OPCODE_RSR_ATOMCTL, + OPCODE_WSR_ATOMCTL, + OPCODE_XSR_ATOMCTL, + OPCODE_QUOU, + OPCODE_QUOS, + OPCODE_REMU, + OPCODE_REMS, + OPCODE_RER, + OPCODE_WER, + OPCODE_F64ITER, + OPCODE_F64RND, + OPCODE_F64ADDC, + OPCODE_F64SUBC, + OPCODE_F64SIG, + OPCODE_F64CMPL, + OPCODE_F64CMPH, + OPCODE_F64NORM, + OPCODE_F64SEXP, + OPCODE_RF64R, + OPCODE_WF64R, + OPCODE_RUR_F64R_LO, + OPCODE_WUR_F64R_LO, + OPCODE_RUR_F64R_HI, + OPCODE_WUR_F64R_HI, + OPCODE_RUR_F64S, + OPCODE_WUR_F64S, + OPCODE_RUR_FCR, + OPCODE_WUR_FCR, + OPCODE_RUR_FSR, + OPCODE_WUR_FSR, + OPCODE_RUR_EXPSTATE, + OPCODE_WUR_EXPSTATE, + OPCODE_READ_IMPWIRE, + OPCODE_SETB_EXPSTATE, + OPCODE_CLRB_EXPSTATE, + OPCODE_WRMSK_EXPSTATE +}; + + +/* Slot-specific opcode decode functions. */ + +static int +Slot_inst_decode (const xtensa_insnbuf insn) +{ + if (Field_op0_Slot_inst_get (insn) == 0) + { + if (Field_op1_Slot_inst_get (insn) == 0) + { + if (Field_op2_Slot_inst_get (insn) == 0) + { + if (Field_r_Slot_inst_get (insn) == 0) + { + if (Field_m_Slot_inst_get (insn) == 0 && + Field_s_Slot_inst_get (insn) == 0 && + Field_n_Slot_inst_get (insn) == 0) + return OPCODE_ILL; + if (Field_m_Slot_inst_get (insn) == 2) + { + if (Field_n_Slot_inst_get (insn) == 0) + return OPCODE_RET; + if (Field_n_Slot_inst_get (insn) == 1) + return OPCODE_RETW; + if (Field_n_Slot_inst_get (insn) == 2) + return OPCODE_JX; + } + if (Field_m_Slot_inst_get (insn) == 3) + { + if (Field_n_Slot_inst_get (insn) == 0) + return OPCODE_CALLX0; + if (Field_n_Slot_inst_get (insn) == 1) + return OPCODE_CALLX4; + if (Field_n_Slot_inst_get (insn) == 2) + return OPCODE_CALLX8; + if (Field_n_Slot_inst_get (insn) == 3) + return OPCODE_CALLX12; + } + } + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_MOVSP; + if (Field_r_Slot_inst_get (insn) == 2) + { + if (Field_s_Slot_inst_get (insn) == 0) + { + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_ISYNC; + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_RSYNC; + if (Field_t_Slot_inst_get (insn) == 2) + return OPCODE_ESYNC; + if (Field_t_Slot_inst_get (insn) == 3) + return OPCODE_DSYNC; + if (Field_t_Slot_inst_get (insn) == 8) + return OPCODE_EXCW; + if (Field_t_Slot_inst_get (insn) == 12) + return OPCODE_MEMW; + if (Field_t_Slot_inst_get (insn) == 13) + return OPCODE_EXTW; + if (Field_t_Slot_inst_get (insn) == 15) + return OPCODE_NOP; + } + } + if (Field_r_Slot_inst_get (insn) == 3) + { + if (Field_t_Slot_inst_get (insn) == 0) + { + if (Field_s_Slot_inst_get (insn) == 0) + return OPCODE_RFE; + if (Field_s_Slot_inst_get (insn) == 2) + return OPCODE_RFDE; + if (Field_s_Slot_inst_get (insn) == 4) + return OPCODE_RFWO; + if (Field_s_Slot_inst_get (insn) == 5) + return OPCODE_RFWU; + } + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_RFI; + } + if (Field_r_Slot_inst_get (insn) == 4) + return OPCODE_BREAK; + if (Field_r_Slot_inst_get (insn) == 5) + { + if (Field_s_Slot_inst_get (insn) == 0 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SYSCALL; + if (Field_s_Slot_inst_get (insn) == 1 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SIMCALL; + } + if (Field_r_Slot_inst_get (insn) == 6) + return OPCODE_RSIL; + if (Field_r_Slot_inst_get (insn) == 7 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_WAITI; + if (Field_r_Slot_inst_get (insn) == 7) + { + if (Field_t_Slot_inst_get (insn) == 14) + return OPCODE_LDDR32_P; + if (Field_t_Slot_inst_get (insn) == 15) + return OPCODE_SDDR32_P; + } + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_ANY4; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_ALL4; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_ANY8; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_ALL8; + } + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_AND; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_OR; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_XOR; + if (Field_op2_Slot_inst_get (insn) == 4) + { + if (Field_r_Slot_inst_get (insn) == 0 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSR; + if (Field_r_Slot_inst_get (insn) == 1 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSL; + if (Field_r_Slot_inst_get (insn) == 2 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSA8L; + if (Field_r_Slot_inst_get (insn) == 3 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SSA8B; + if (Field_r_Slot_inst_get (insn) == 4 && + Field_thi3_Slot_inst_get (insn) == 0) + return OPCODE_SSAI; + if (Field_r_Slot_inst_get (insn) == 6) + return OPCODE_RER; + if (Field_r_Slot_inst_get (insn) == 7) + return OPCODE_WER; + if (Field_r_Slot_inst_get (insn) == 8 && + Field_s_Slot_inst_get (insn) == 0) + return OPCODE_ROTW; + if (Field_r_Slot_inst_get (insn) == 14) + return OPCODE_NSA; + if (Field_r_Slot_inst_get (insn) == 15) + return OPCODE_NSAU; + } + if (Field_op2_Slot_inst_get (insn) == 5) + { + if (Field_r_Slot_inst_get (insn) == 3) + return OPCODE_RITLB0; + if (Field_r_Slot_inst_get (insn) == 4 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_IITLB; + if (Field_r_Slot_inst_get (insn) == 5) + return OPCODE_PITLB; + if (Field_r_Slot_inst_get (insn) == 6) + return OPCODE_WITLB; + if (Field_r_Slot_inst_get (insn) == 7) + return OPCODE_RITLB1; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_RDTLB0; + if (Field_r_Slot_inst_get (insn) == 12 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_IDTLB; + if (Field_r_Slot_inst_get (insn) == 13) + return OPCODE_PDTLB; + if (Field_r_Slot_inst_get (insn) == 14) + return OPCODE_WDTLB; + if (Field_r_Slot_inst_get (insn) == 15) + return OPCODE_RDTLB1; + } + if (Field_op2_Slot_inst_get (insn) == 6) + { + if (Field_s_Slot_inst_get (insn) == 0) + return OPCODE_NEG; + if (Field_s_Slot_inst_get (insn) == 1) + return OPCODE_ABS; + } + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_ADD; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_ADDX2; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_ADDX4; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_ADDX8; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_SUB; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_SUBX2; + if (Field_op2_Slot_inst_get (insn) == 14) + return OPCODE_SUBX4; + if (Field_op2_Slot_inst_get (insn) == 15) + return OPCODE_SUBX8; + } + if (Field_op1_Slot_inst_get (insn) == 1) + { + if ((Field_op2_Slot_inst_get (insn) == 0 || + Field_op2_Slot_inst_get (insn) == 1)) + return OPCODE_SLLI; + if ((Field_op2_Slot_inst_get (insn) == 2 || + Field_op2_Slot_inst_get (insn) == 3)) + return OPCODE_SRAI; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_SRLI; + if (Field_op2_Slot_inst_get (insn) == 6) + { + if (Field_sr_Slot_inst_get (insn) == 0) + return OPCODE_XSR_LBEG; + if (Field_sr_Slot_inst_get (insn) == 1) + return OPCODE_XSR_LEND; + if (Field_sr_Slot_inst_get (insn) == 2) + return OPCODE_XSR_LCOUNT; + if (Field_sr_Slot_inst_get (insn) == 3) + return OPCODE_XSR_SAR; + if (Field_sr_Slot_inst_get (insn) == 4) + return OPCODE_XSR_BR; + if (Field_sr_Slot_inst_get (insn) == 5) + return OPCODE_XSR_LITBASE; + if (Field_sr_Slot_inst_get (insn) == 12) + return OPCODE_XSR_SCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 16) + return OPCODE_XSR_ACCLO; + if (Field_sr_Slot_inst_get (insn) == 17) + return OPCODE_XSR_ACCHI; + if (Field_sr_Slot_inst_get (insn) == 32) + return OPCODE_XSR_M0; + if (Field_sr_Slot_inst_get (insn) == 33) + return OPCODE_XSR_M1; + if (Field_sr_Slot_inst_get (insn) == 34) + return OPCODE_XSR_M2; + if (Field_sr_Slot_inst_get (insn) == 35) + return OPCODE_XSR_M3; + if (Field_sr_Slot_inst_get (insn) == 72) + return OPCODE_XSR_WINDOWBASE; + if (Field_sr_Slot_inst_get (insn) == 73) + return OPCODE_XSR_WINDOWSTART; + if (Field_sr_Slot_inst_get (insn) == 96) + return OPCODE_XSR_IBREAKENABLE; + if (Field_sr_Slot_inst_get (insn) == 97) + return OPCODE_XSR_MEMCTL; + if (Field_sr_Slot_inst_get (insn) == 99) + return OPCODE_XSR_ATOMCTL; + if (Field_sr_Slot_inst_get (insn) == 104) + return OPCODE_XSR_DDR; + if (Field_sr_Slot_inst_get (insn) == 128) + return OPCODE_XSR_IBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 129) + return OPCODE_XSR_IBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 144) + return OPCODE_XSR_DBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 145) + return OPCODE_XSR_DBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 160) + return OPCODE_XSR_DBREAKC0; + if (Field_sr_Slot_inst_get (insn) == 161) + return OPCODE_XSR_DBREAKC1; + if (Field_sr_Slot_inst_get (insn) == 177) + return OPCODE_XSR_EPC1; + if (Field_sr_Slot_inst_get (insn) == 178) + return OPCODE_XSR_EPC2; + if (Field_sr_Slot_inst_get (insn) == 179) + return OPCODE_XSR_EPC3; + if (Field_sr_Slot_inst_get (insn) == 180) + return OPCODE_XSR_EPC4; + if (Field_sr_Slot_inst_get (insn) == 181) + return OPCODE_XSR_EPC5; + if (Field_sr_Slot_inst_get (insn) == 182) + return OPCODE_XSR_EPC6; + if (Field_sr_Slot_inst_get (insn) == 183) + return OPCODE_XSR_EPC7; + if (Field_sr_Slot_inst_get (insn) == 192) + return OPCODE_XSR_DEPC; + if (Field_sr_Slot_inst_get (insn) == 194) + return OPCODE_XSR_EPS2; + if (Field_sr_Slot_inst_get (insn) == 195) + return OPCODE_XSR_EPS3; + if (Field_sr_Slot_inst_get (insn) == 196) + return OPCODE_XSR_EPS4; + if (Field_sr_Slot_inst_get (insn) == 197) + return OPCODE_XSR_EPS5; + if (Field_sr_Slot_inst_get (insn) == 198) + return OPCODE_XSR_EPS6; + if (Field_sr_Slot_inst_get (insn) == 199) + return OPCODE_XSR_EPS7; + if (Field_sr_Slot_inst_get (insn) == 209) + return OPCODE_XSR_EXCSAVE1; + if (Field_sr_Slot_inst_get (insn) == 210) + return OPCODE_XSR_EXCSAVE2; + if (Field_sr_Slot_inst_get (insn) == 211) + return OPCODE_XSR_EXCSAVE3; + if (Field_sr_Slot_inst_get (insn) == 212) + return OPCODE_XSR_EXCSAVE4; + if (Field_sr_Slot_inst_get (insn) == 213) + return OPCODE_XSR_EXCSAVE5; + if (Field_sr_Slot_inst_get (insn) == 214) + return OPCODE_XSR_EXCSAVE6; + if (Field_sr_Slot_inst_get (insn) == 215) + return OPCODE_XSR_EXCSAVE7; + if (Field_sr_Slot_inst_get (insn) == 224) + return OPCODE_XSR_CPENABLE; + if (Field_sr_Slot_inst_get (insn) == 228) + return OPCODE_XSR_INTENABLE; + if (Field_sr_Slot_inst_get (insn) == 230) + return OPCODE_XSR_PS; + if (Field_sr_Slot_inst_get (insn) == 231) + return OPCODE_XSR_VECBASE; + if (Field_sr_Slot_inst_get (insn) == 232) + return OPCODE_XSR_EXCCAUSE; + if (Field_sr_Slot_inst_get (insn) == 233) + return OPCODE_XSR_DEBUGCAUSE; + if (Field_sr_Slot_inst_get (insn) == 234) + return OPCODE_XSR_CCOUNT; + if (Field_sr_Slot_inst_get (insn) == 236) + return OPCODE_XSR_ICOUNT; + if (Field_sr_Slot_inst_get (insn) == 237) + return OPCODE_XSR_ICOUNTLEVEL; + if (Field_sr_Slot_inst_get (insn) == 238) + return OPCODE_XSR_EXCVADDR; + if (Field_sr_Slot_inst_get (insn) == 240) + return OPCODE_XSR_CCOMPARE0; + if (Field_sr_Slot_inst_get (insn) == 241) + return OPCODE_XSR_CCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 242) + return OPCODE_XSR_CCOMPARE2; + if (Field_sr_Slot_inst_get (insn) == 244) + return OPCODE_XSR_MISC0; + if (Field_sr_Slot_inst_get (insn) == 245) + return OPCODE_XSR_MISC1; + if (Field_sr_Slot_inst_get (insn) == 246) + return OPCODE_XSR_MISC2; + if (Field_sr_Slot_inst_get (insn) == 247) + return OPCODE_XSR_MISC3; + } + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_SRC; + if (Field_op2_Slot_inst_get (insn) == 9 && + Field_s_Slot_inst_get (insn) == 0) + return OPCODE_SRL; + if (Field_op2_Slot_inst_get (insn) == 10 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_SLL; + if (Field_op2_Slot_inst_get (insn) == 11 && + Field_s_Slot_inst_get (insn) == 0) + return OPCODE_SRA; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_MUL16U; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_MUL16S; + if (Field_op2_Slot_inst_get (insn) == 15) + { + if (Field_r_Slot_inst_get (insn) == 14 && + Field_t_Slot_inst_get (insn) == 0) + return OPCODE_RFDO; + if (Field_r_Slot_inst_get (insn) == 14 && + Field_t_Slot_inst_get (insn) == 1) + return OPCODE_RFDD; + } + } + if (Field_op1_Slot_inst_get (insn) == 2) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_ANDB; + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_ANDBC; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_ORB; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_ORBC; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_XORB; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_MULL; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_MULUH; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_MULSH; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_QUOU; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_QUOS; + if (Field_op2_Slot_inst_get (insn) == 14) + return OPCODE_REMU; + if (Field_op2_Slot_inst_get (insn) == 15) + return OPCODE_REMS; + } + if (Field_op1_Slot_inst_get (insn) == 3) + { + if (Field_op2_Slot_inst_get (insn) == 0) + { + if (Field_sr_Slot_inst_get (insn) == 0) + return OPCODE_RSR_LBEG; + if (Field_sr_Slot_inst_get (insn) == 1) + return OPCODE_RSR_LEND; + if (Field_sr_Slot_inst_get (insn) == 2) + return OPCODE_RSR_LCOUNT; + if (Field_sr_Slot_inst_get (insn) == 3) + return OPCODE_RSR_SAR; + if (Field_sr_Slot_inst_get (insn) == 4) + return OPCODE_RSR_BR; + if (Field_sr_Slot_inst_get (insn) == 5) + return OPCODE_RSR_LITBASE; + if (Field_sr_Slot_inst_get (insn) == 12) + return OPCODE_RSR_SCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 16) + return OPCODE_RSR_ACCLO; + if (Field_sr_Slot_inst_get (insn) == 17) + return OPCODE_RSR_ACCHI; + if (Field_sr_Slot_inst_get (insn) == 32) + return OPCODE_RSR_M0; + if (Field_sr_Slot_inst_get (insn) == 33) + return OPCODE_RSR_M1; + if (Field_sr_Slot_inst_get (insn) == 34) + return OPCODE_RSR_M2; + if (Field_sr_Slot_inst_get (insn) == 35) + return OPCODE_RSR_M3; + if (Field_sr_Slot_inst_get (insn) == 72) + return OPCODE_RSR_WINDOWBASE; + if (Field_sr_Slot_inst_get (insn) == 73) + return OPCODE_RSR_WINDOWSTART; + if (Field_sr_Slot_inst_get (insn) == 96) + return OPCODE_RSR_IBREAKENABLE; + if (Field_sr_Slot_inst_get (insn) == 97) + return OPCODE_RSR_MEMCTL; + if (Field_sr_Slot_inst_get (insn) == 99) + return OPCODE_RSR_ATOMCTL; + if (Field_sr_Slot_inst_get (insn) == 104) + return OPCODE_RSR_DDR; + if (Field_sr_Slot_inst_get (insn) == 128) + return OPCODE_RSR_IBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 129) + return OPCODE_RSR_IBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 144) + return OPCODE_RSR_DBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 145) + return OPCODE_RSR_DBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 160) + return OPCODE_RSR_DBREAKC0; + if (Field_sr_Slot_inst_get (insn) == 161) + return OPCODE_RSR_DBREAKC1; + if (Field_sr_Slot_inst_get (insn) == 176) + return OPCODE_RSR_CONFIGID0; + if (Field_sr_Slot_inst_get (insn) == 177) + return OPCODE_RSR_EPC1; + if (Field_sr_Slot_inst_get (insn) == 178) + return OPCODE_RSR_EPC2; + if (Field_sr_Slot_inst_get (insn) == 179) + return OPCODE_RSR_EPC3; + if (Field_sr_Slot_inst_get (insn) == 180) + return OPCODE_RSR_EPC4; + if (Field_sr_Slot_inst_get (insn) == 181) + return OPCODE_RSR_EPC5; + if (Field_sr_Slot_inst_get (insn) == 182) + return OPCODE_RSR_EPC6; + if (Field_sr_Slot_inst_get (insn) == 183) + return OPCODE_RSR_EPC7; + if (Field_sr_Slot_inst_get (insn) == 192) + return OPCODE_RSR_DEPC; + if (Field_sr_Slot_inst_get (insn) == 194) + return OPCODE_RSR_EPS2; + if (Field_sr_Slot_inst_get (insn) == 195) + return OPCODE_RSR_EPS3; + if (Field_sr_Slot_inst_get (insn) == 196) + return OPCODE_RSR_EPS4; + if (Field_sr_Slot_inst_get (insn) == 197) + return OPCODE_RSR_EPS5; + if (Field_sr_Slot_inst_get (insn) == 198) + return OPCODE_RSR_EPS6; + if (Field_sr_Slot_inst_get (insn) == 199) + return OPCODE_RSR_EPS7; + if (Field_sr_Slot_inst_get (insn) == 208) + return OPCODE_RSR_CONFIGID1; + if (Field_sr_Slot_inst_get (insn) == 209) + return OPCODE_RSR_EXCSAVE1; + if (Field_sr_Slot_inst_get (insn) == 210) + return OPCODE_RSR_EXCSAVE2; + if (Field_sr_Slot_inst_get (insn) == 211) + return OPCODE_RSR_EXCSAVE3; + if (Field_sr_Slot_inst_get (insn) == 212) + return OPCODE_RSR_EXCSAVE4; + if (Field_sr_Slot_inst_get (insn) == 213) + return OPCODE_RSR_EXCSAVE5; + if (Field_sr_Slot_inst_get (insn) == 214) + return OPCODE_RSR_EXCSAVE6; + if (Field_sr_Slot_inst_get (insn) == 215) + return OPCODE_RSR_EXCSAVE7; + if (Field_sr_Slot_inst_get (insn) == 224) + return OPCODE_RSR_CPENABLE; + if (Field_sr_Slot_inst_get (insn) == 226) + return OPCODE_RSR_INTERRUPT; + if (Field_sr_Slot_inst_get (insn) == 228) + return OPCODE_RSR_INTENABLE; + if (Field_sr_Slot_inst_get (insn) == 230) + return OPCODE_RSR_PS; + if (Field_sr_Slot_inst_get (insn) == 231) + return OPCODE_RSR_VECBASE; + if (Field_sr_Slot_inst_get (insn) == 232) + return OPCODE_RSR_EXCCAUSE; + if (Field_sr_Slot_inst_get (insn) == 233) + return OPCODE_RSR_DEBUGCAUSE; + if (Field_sr_Slot_inst_get (insn) == 234) + return OPCODE_RSR_CCOUNT; + if (Field_sr_Slot_inst_get (insn) == 235) + return OPCODE_RSR_PRID; + if (Field_sr_Slot_inst_get (insn) == 236) + return OPCODE_RSR_ICOUNT; + if (Field_sr_Slot_inst_get (insn) == 237) + return OPCODE_RSR_ICOUNTLEVEL; + if (Field_sr_Slot_inst_get (insn) == 238) + return OPCODE_RSR_EXCVADDR; + if (Field_sr_Slot_inst_get (insn) == 240) + return OPCODE_RSR_CCOMPARE0; + if (Field_sr_Slot_inst_get (insn) == 241) + return OPCODE_RSR_CCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 242) + return OPCODE_RSR_CCOMPARE2; + if (Field_sr_Slot_inst_get (insn) == 244) + return OPCODE_RSR_MISC0; + if (Field_sr_Slot_inst_get (insn) == 245) + return OPCODE_RSR_MISC1; + if (Field_sr_Slot_inst_get (insn) == 246) + return OPCODE_RSR_MISC2; + if (Field_sr_Slot_inst_get (insn) == 247) + return OPCODE_RSR_MISC3; + } + if (Field_op2_Slot_inst_get (insn) == 1) + { + if (Field_sr_Slot_inst_get (insn) == 0) + return OPCODE_WSR_LBEG; + if (Field_sr_Slot_inst_get (insn) == 1) + return OPCODE_WSR_LEND; + if (Field_sr_Slot_inst_get (insn) == 2) + return OPCODE_WSR_LCOUNT; + if (Field_sr_Slot_inst_get (insn) == 3) + return OPCODE_WSR_SAR; + if (Field_sr_Slot_inst_get (insn) == 4) + return OPCODE_WSR_BR; + if (Field_sr_Slot_inst_get (insn) == 5) + return OPCODE_WSR_LITBASE; + if (Field_sr_Slot_inst_get (insn) == 12) + return OPCODE_WSR_SCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 16) + return OPCODE_WSR_ACCLO; + if (Field_sr_Slot_inst_get (insn) == 17) + return OPCODE_WSR_ACCHI; + if (Field_sr_Slot_inst_get (insn) == 32) + return OPCODE_WSR_M0; + if (Field_sr_Slot_inst_get (insn) == 33) + return OPCODE_WSR_M1; + if (Field_sr_Slot_inst_get (insn) == 34) + return OPCODE_WSR_M2; + if (Field_sr_Slot_inst_get (insn) == 35) + return OPCODE_WSR_M3; + if (Field_sr_Slot_inst_get (insn) == 72) + return OPCODE_WSR_WINDOWBASE; + if (Field_sr_Slot_inst_get (insn) == 73) + return OPCODE_WSR_WINDOWSTART; + if (Field_sr_Slot_inst_get (insn) == 89) + return OPCODE_WSR_MMID; + if (Field_sr_Slot_inst_get (insn) == 96) + return OPCODE_WSR_IBREAKENABLE; + if (Field_sr_Slot_inst_get (insn) == 97) + return OPCODE_WSR_MEMCTL; + if (Field_sr_Slot_inst_get (insn) == 99) + return OPCODE_WSR_ATOMCTL; + if (Field_sr_Slot_inst_get (insn) == 104) + return OPCODE_WSR_DDR; + if (Field_sr_Slot_inst_get (insn) == 128) + return OPCODE_WSR_IBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 129) + return OPCODE_WSR_IBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 144) + return OPCODE_WSR_DBREAKA0; + if (Field_sr_Slot_inst_get (insn) == 145) + return OPCODE_WSR_DBREAKA1; + if (Field_sr_Slot_inst_get (insn) == 160) + return OPCODE_WSR_DBREAKC0; + if (Field_sr_Slot_inst_get (insn) == 161) + return OPCODE_WSR_DBREAKC1; + if (Field_sr_Slot_inst_get (insn) == 176) + return OPCODE_WSR_CONFIGID0; + if (Field_sr_Slot_inst_get (insn) == 177) + return OPCODE_WSR_EPC1; + if (Field_sr_Slot_inst_get (insn) == 178) + return OPCODE_WSR_EPC2; + if (Field_sr_Slot_inst_get (insn) == 179) + return OPCODE_WSR_EPC3; + if (Field_sr_Slot_inst_get (insn) == 180) + return OPCODE_WSR_EPC4; + if (Field_sr_Slot_inst_get (insn) == 181) + return OPCODE_WSR_EPC5; + if (Field_sr_Slot_inst_get (insn) == 182) + return OPCODE_WSR_EPC6; + if (Field_sr_Slot_inst_get (insn) == 183) + return OPCODE_WSR_EPC7; + if (Field_sr_Slot_inst_get (insn) == 192) + return OPCODE_WSR_DEPC; + if (Field_sr_Slot_inst_get (insn) == 194) + return OPCODE_WSR_EPS2; + if (Field_sr_Slot_inst_get (insn) == 195) + return OPCODE_WSR_EPS3; + if (Field_sr_Slot_inst_get (insn) == 196) + return OPCODE_WSR_EPS4; + if (Field_sr_Slot_inst_get (insn) == 197) + return OPCODE_WSR_EPS5; + if (Field_sr_Slot_inst_get (insn) == 198) + return OPCODE_WSR_EPS6; + if (Field_sr_Slot_inst_get (insn) == 199) + return OPCODE_WSR_EPS7; + if (Field_sr_Slot_inst_get (insn) == 209) + return OPCODE_WSR_EXCSAVE1; + if (Field_sr_Slot_inst_get (insn) == 210) + return OPCODE_WSR_EXCSAVE2; + if (Field_sr_Slot_inst_get (insn) == 211) + return OPCODE_WSR_EXCSAVE3; + if (Field_sr_Slot_inst_get (insn) == 212) + return OPCODE_WSR_EXCSAVE4; + if (Field_sr_Slot_inst_get (insn) == 213) + return OPCODE_WSR_EXCSAVE5; + if (Field_sr_Slot_inst_get (insn) == 214) + return OPCODE_WSR_EXCSAVE6; + if (Field_sr_Slot_inst_get (insn) == 215) + return OPCODE_WSR_EXCSAVE7; + if (Field_sr_Slot_inst_get (insn) == 224) + return OPCODE_WSR_CPENABLE; + if (Field_sr_Slot_inst_get (insn) == 226) + return OPCODE_WSR_INTSET; + if (Field_sr_Slot_inst_get (insn) == 227) + return OPCODE_WSR_INTCLEAR; + if (Field_sr_Slot_inst_get (insn) == 228) + return OPCODE_WSR_INTENABLE; + if (Field_sr_Slot_inst_get (insn) == 230) + return OPCODE_WSR_PS; + if (Field_sr_Slot_inst_get (insn) == 231) + return OPCODE_WSR_VECBASE; + if (Field_sr_Slot_inst_get (insn) == 232) + return OPCODE_WSR_EXCCAUSE; + if (Field_sr_Slot_inst_get (insn) == 233) + return OPCODE_WSR_DEBUGCAUSE; + if (Field_sr_Slot_inst_get (insn) == 234) + return OPCODE_WSR_CCOUNT; + if (Field_sr_Slot_inst_get (insn) == 236) + return OPCODE_WSR_ICOUNT; + if (Field_sr_Slot_inst_get (insn) == 237) + return OPCODE_WSR_ICOUNTLEVEL; + if (Field_sr_Slot_inst_get (insn) == 238) + return OPCODE_WSR_EXCVADDR; + if (Field_sr_Slot_inst_get (insn) == 240) + return OPCODE_WSR_CCOMPARE0; + if (Field_sr_Slot_inst_get (insn) == 241) + return OPCODE_WSR_CCOMPARE1; + if (Field_sr_Slot_inst_get (insn) == 242) + return OPCODE_WSR_CCOMPARE2; + if (Field_sr_Slot_inst_get (insn) == 244) + return OPCODE_WSR_MISC0; + if (Field_sr_Slot_inst_get (insn) == 245) + return OPCODE_WSR_MISC1; + if (Field_sr_Slot_inst_get (insn) == 246) + return OPCODE_WSR_MISC2; + if (Field_sr_Slot_inst_get (insn) == 247) + return OPCODE_WSR_MISC3; + } + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_SEXT; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_CLAMPS; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_MIN; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_MAX; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_MINU; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_MAXU; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_MOVEQZ; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_MOVNEZ; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_MOVLTZ; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_MOVGEZ; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_MOVF; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_MOVT; + if (Field_op2_Slot_inst_get (insn) == 14) + { + if (Field_st_Slot_inst_get (insn) == 230) + return OPCODE_RUR_EXPSTATE; + if (Field_st_Slot_inst_get (insn) == 231) + return OPCODE_RUR_THREADPTR; + if (Field_st_Slot_inst_get (insn) == 232) + return OPCODE_RUR_FCR; + if (Field_st_Slot_inst_get (insn) == 233) + return OPCODE_RUR_FSR; + if (Field_st_Slot_inst_get (insn) == 234) + return OPCODE_RUR_F64R_LO; + if (Field_st_Slot_inst_get (insn) == 235) + return OPCODE_RUR_F64R_HI; + if (Field_st_Slot_inst_get (insn) == 236) + return OPCODE_RUR_F64S; + } + if (Field_op2_Slot_inst_get (insn) == 15) + { + if (Field_sr_Slot_inst_get (insn) == 230) + return OPCODE_WUR_EXPSTATE; + if (Field_sr_Slot_inst_get (insn) == 231) + return OPCODE_WUR_THREADPTR; + if (Field_sr_Slot_inst_get (insn) == 232) + return OPCODE_WUR_FCR; + if (Field_sr_Slot_inst_get (insn) == 233) + return OPCODE_WUR_FSR; + if (Field_sr_Slot_inst_get (insn) == 234) + return OPCODE_WUR_F64R_LO; + if (Field_sr_Slot_inst_get (insn) == 235) + return OPCODE_WUR_F64R_HI; + if (Field_sr_Slot_inst_get (insn) == 236) + return OPCODE_WUR_F64S; + } + } + if ((Field_op1_Slot_inst_get (insn) == 4 || + Field_op1_Slot_inst_get (insn) == 5)) + return OPCODE_EXTUI; + if (Field_op1_Slot_inst_get (insn) == 8) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_LSX; + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_LSXP; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_SSX; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_SSXP; + } + if (Field_op1_Slot_inst_get (insn) == 9) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_L32E; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_S32E; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_S32NB; + } + if (Field_op1_Slot_inst_get (insn) == 10) + { + if (Field_op2_Slot_inst_get (insn) == 0) + return OPCODE_ADD_S; + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_SUB_S; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_MUL_S; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_MADD_S; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_MSUB_S; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_MADDN_S; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_DIVN_S; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_ROUND_S; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_TRUNC_S; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_FLOOR_S; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_CEIL_S; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_FLOAT_S; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_UFLOAT_S; + if (Field_op2_Slot_inst_get (insn) == 14) + return OPCODE_UTRUNC_S; + if (Field_op2_Slot_inst_get (insn) == 15) + { + if (Field_t_Slot_inst_get (insn) == 0) + return OPCODE_MOV_S; + if (Field_t_Slot_inst_get (insn) == 1) + return OPCODE_ABS_S; + if (Field_t_Slot_inst_get (insn) == 3) + return OPCODE_CONST_S; + if (Field_t_Slot_inst_get (insn) == 4) + return OPCODE_RFR; + if (Field_t_Slot_inst_get (insn) == 5) + return OPCODE_WFR; + if (Field_t_Slot_inst_get (insn) == 6) + return OPCODE_NEG_S; + if (Field_t_Slot_inst_get (insn) == 7) + return OPCODE_DIV0_S; + if (Field_t_Slot_inst_get (insn) == 8) + return OPCODE_RECIP0_S; + if (Field_t_Slot_inst_get (insn) == 9) + return OPCODE_SQRT0_S; + if (Field_t_Slot_inst_get (insn) == 10) + return OPCODE_RSQRT0_S; + if (Field_t_Slot_inst_get (insn) == 11) + return OPCODE_NEXP01_S; + if (Field_t_Slot_inst_get (insn) == 12) + return OPCODE_MKSADJ_S; + if (Field_t_Slot_inst_get (insn) == 13) + return OPCODE_MKDADJ_S; + if (Field_t_Slot_inst_get (insn) == 14) + return OPCODE_ADDEXP_S; + if (Field_t_Slot_inst_get (insn) == 15) + return OPCODE_ADDEXPM_S; + } + } + if (Field_op1_Slot_inst_get (insn) == 11) + { + if (Field_op2_Slot_inst_get (insn) == 1) + return OPCODE_UN_S; + if (Field_op2_Slot_inst_get (insn) == 2) + return OPCODE_OEQ_S; + if (Field_op2_Slot_inst_get (insn) == 3) + return OPCODE_UEQ_S; + if (Field_op2_Slot_inst_get (insn) == 4) + return OPCODE_OLT_S; + if (Field_op2_Slot_inst_get (insn) == 5) + return OPCODE_ULT_S; + if (Field_op2_Slot_inst_get (insn) == 6) + return OPCODE_OLE_S; + if (Field_op2_Slot_inst_get (insn) == 7) + return OPCODE_ULE_S; + if (Field_op2_Slot_inst_get (insn) == 8) + return OPCODE_MOVEQZ_S; + if (Field_op2_Slot_inst_get (insn) == 9) + return OPCODE_MOVNEZ_S; + if (Field_op2_Slot_inst_get (insn) == 10) + return OPCODE_MOVLTZ_S; + if (Field_op2_Slot_inst_get (insn) == 11) + return OPCODE_MOVGEZ_S; + if (Field_op2_Slot_inst_get (insn) == 12) + return OPCODE_MOVF_S; + if (Field_op2_Slot_inst_get (insn) == 13) + return OPCODE_MOVT_S; + } + if (Field_r_Slot_inst_get (insn) == 0 && + Field_s_Slot_inst_get (insn) == 0 && + Field_op2_Slot_inst_get (insn) == 0 && + Field_op1_Slot_inst_get (insn) == 14) + return OPCODE_READ_IMPWIRE; + if (Field_r_Slot_inst_get (insn) == 1 && + Field_s3to1_Slot_inst_get (insn) == 0 && + Field_op2_Slot_inst_get (insn) == 0 && + Field_op1_Slot_inst_get (insn) == 14) + return OPCODE_SETB_EXPSTATE; + if (Field_r_Slot_inst_get (insn) == 1 && + Field_s3to1_Slot_inst_get (insn) == 1 && + Field_op2_Slot_inst_get (insn) == 0 && + Field_op1_Slot_inst_get (insn) == 14) + return OPCODE_CLRB_EXPSTATE; + if (Field_r_Slot_inst_get (insn) == 2 && + Field_op2_Slot_inst_get (insn) == 0 && + Field_op1_Slot_inst_get (insn) == 14) + return OPCODE_WRMSK_EXPSTATE; + } + if (Field_op0_Slot_inst_get (insn) == 0) + { + if (Field_dfp_fld_op1_Slot_inst_get (insn) == 11) + { + if (Field_dfp_fld_op2_Slot_inst_get (insn) == 0) + { + if (Field_dfp_fld_r_3_1_Slot_inst_get (insn) == 7) + return OPCODE_WF64R; + if (Field_dfp_fld_s_3_1_Slot_inst_get (insn) == 7 && + Field_r_Slot_inst_get (insn) == 12) + return OPCODE_RF64R; + } + if (Field_dfp_fld_op2_Slot_inst_get (insn) == 14) + { + return OPCODE_F64CMPL; + } + if (Field_dfp_fld_op2_Slot_inst_get (insn) == 15) + { + if (Field_dfp_fld_r_3_Slot_inst_get (insn) == 0) + return OPCODE_F64ADDC; + if (Field_dfp_fld_r_3_Slot_inst_get (insn) == 1) + return OPCODE_F64SUBC; + } + } + if (Field_dfp_fld_op1_Slot_inst_get (insn) == 14) + { + if (Field_dfp_fld_op2_Slot_inst_get (insn) == 0) + { + if (Field_r_Slot_inst_get (insn) == 13) + return OPCODE_F64SIG; + } + if (Field_dfp_fld_op2_Slot_inst_get (insn) == 1) + { + return OPCODE_F64SEXP; + } + if (Field_dfp_fld_op2_3_Slot_inst_get (insn) == 1) + return OPCODE_F64ITER; + if (Field_dfp_fld_op2_3_1_Slot_inst_get (insn) == 1) + return OPCODE_F64NORM; + if (Field_dfp_fld_op2_3_2_Slot_inst_get (insn) == 1) + return OPCODE_F64RND; + } + if (Field_dfp_fld_op1_Slot_inst_get (insn) == 15) + { + return OPCODE_F64CMPH; + } + } + if (Field_op0_Slot_inst_get (insn) == 1) + return OPCODE_L32R; + if (Field_op0_Slot_inst_get (insn) == 2) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_L8UI; + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_L16UI; + if (Field_r_Slot_inst_get (insn) == 2) + return OPCODE_L32I; + if (Field_r_Slot_inst_get (insn) == 4) + return OPCODE_S8I; + if (Field_r_Slot_inst_get (insn) == 5) + return OPCODE_S16I; + if (Field_r_Slot_inst_get (insn) == 6) + return OPCODE_S32I; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_L16SI; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_MOVI; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_L32AI; + if (Field_r_Slot_inst_get (insn) == 12) + return OPCODE_ADDI; + if (Field_r_Slot_inst_get (insn) == 13) + return OPCODE_ADDMI; + if (Field_r_Slot_inst_get (insn) == 14) + return OPCODE_S32C1I; + if (Field_r_Slot_inst_get (insn) == 15) + return OPCODE_S32RI; + } + if (Field_op0_Slot_inst_get (insn) == 3) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_LSI; + if (Field_r_Slot_inst_get (insn) == 4) + return OPCODE_SSI; + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_LSIP; + if (Field_r_Slot_inst_get (insn) == 12) + return OPCODE_SSIP; + } + if (Field_op0_Slot_inst_get (insn) == 4) + { + if (Field_op2_Slot_inst_get (insn) == 0) + { + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LL_LDINC; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HL_LDINC; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LH_LDINC; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HH_LDINC; + } + if (Field_op2_Slot_inst_get (insn) == 1) + { + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LL_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HL_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LH_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HH_LDDEC; + } + if (Field_op2_Slot_inst_get (insn) == 2) + { + if (Field_op1_Slot_inst_get (insn) == 4 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DD_LL; + if (Field_op1_Slot_inst_get (insn) == 5 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DD_HL; + if (Field_op1_Slot_inst_get (insn) == 6 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DD_LH; + if (Field_op1_Slot_inst_get (insn) == 7 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DD_HH; + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LL; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HL; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_LH; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DD_HH; + if (Field_op1_Slot_inst_get (insn) == 12 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DD_LL; + if (Field_op1_Slot_inst_get (insn) == 13 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DD_HL; + if (Field_op1_Slot_inst_get (insn) == 14 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DD_LH; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DD_HH; + } + if (Field_op2_Slot_inst_get (insn) == 3) + { + if (Field_op1_Slot_inst_get (insn) == 4 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AD_LL; + if (Field_op1_Slot_inst_get (insn) == 5 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AD_HL; + if (Field_op1_Slot_inst_get (insn) == 6 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AD_LH; + if (Field_op1_Slot_inst_get (insn) == 7 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AD_HH; + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AD_LL; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AD_HL; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AD_LH; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AD_HH; + if (Field_op1_Slot_inst_get (insn) == 12 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AD_LL; + if (Field_op1_Slot_inst_get (insn) == 13 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AD_HL; + if (Field_op1_Slot_inst_get (insn) == 14 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AD_LH; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_r_Slot_inst_get (insn) == 0 && + Field_t3_Slot_inst_get (insn) == 0 && + Field_tlo_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AD_HH; + } + if (Field_op2_Slot_inst_get (insn) == 4) + { + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LL_LDINC; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HL_LDINC; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LH_LDINC; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HH_LDINC; + } + if (Field_op2_Slot_inst_get (insn) == 5) + { + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LL_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HL_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LH_LDDEC; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HH_LDDEC; + } + if (Field_op2_Slot_inst_get (insn) == 6) + { + if (Field_op1_Slot_inst_get (insn) == 4 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DA_LL; + if (Field_op1_Slot_inst_get (insn) == 5 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DA_HL; + if (Field_op1_Slot_inst_get (insn) == 6 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DA_LH; + if (Field_op1_Slot_inst_get (insn) == 7 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MUL_DA_HH; + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LL; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HL; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_LH; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULA_DA_HH; + if (Field_op1_Slot_inst_get (insn) == 12 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DA_LL; + if (Field_op1_Slot_inst_get (insn) == 13 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DA_HL; + if (Field_op1_Slot_inst_get (insn) == 14 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DA_LH; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_s_Slot_inst_get (insn) == 0 && + Field_w_Slot_inst_get (insn) == 0 && + Field_r3_Slot_inst_get (insn) == 0) + return OPCODE_MULS_DA_HH; + } + if (Field_op2_Slot_inst_get (insn) == 7) + { + if (Field_op1_Slot_inst_get (insn) == 0 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_UMUL_AA_LL; + if (Field_op1_Slot_inst_get (insn) == 1 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_UMUL_AA_HL; + if (Field_op1_Slot_inst_get (insn) == 2 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_UMUL_AA_LH; + if (Field_op1_Slot_inst_get (insn) == 3 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_UMUL_AA_HH; + if (Field_op1_Slot_inst_get (insn) == 4 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AA_LL; + if (Field_op1_Slot_inst_get (insn) == 5 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AA_HL; + if (Field_op1_Slot_inst_get (insn) == 6 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AA_LH; + if (Field_op1_Slot_inst_get (insn) == 7 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MUL_AA_HH; + if (Field_op1_Slot_inst_get (insn) == 8 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AA_LL; + if (Field_op1_Slot_inst_get (insn) == 9 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AA_HL; + if (Field_op1_Slot_inst_get (insn) == 10 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AA_LH; + if (Field_op1_Slot_inst_get (insn) == 11 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULA_AA_HH; + if (Field_op1_Slot_inst_get (insn) == 12 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AA_LL; + if (Field_op1_Slot_inst_get (insn) == 13 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AA_HL; + if (Field_op1_Slot_inst_get (insn) == 14 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AA_LH; + if (Field_op1_Slot_inst_get (insn) == 15 && + Field_r_Slot_inst_get (insn) == 0) + return OPCODE_MULS_AA_HH; + } + if (Field_op2_Slot_inst_get (insn) == 8) + { + if (Field_op1_Slot_inst_get (insn) == 0 && + Field_t_Slot_inst_get (insn) == 0 && + Field_rhi_Slot_inst_get (insn) == 0) + return OPCODE_LDINC; + } + if (Field_op2_Slot_inst_get (insn) == 9) + { + if (Field_op1_Slot_inst_get (insn) == 0 && + Field_t_Slot_inst_get (insn) == 0 && + Field_rhi_Slot_inst_get (insn) == 0) + return OPCODE_LDDEC; + } + } + if (Field_op0_Slot_inst_get (insn) == 5) + { + if (Field_n_Slot_inst_get (insn) == 0) + return OPCODE_CALL0; + if (Field_n_Slot_inst_get (insn) == 1) + return OPCODE_CALL4; + if (Field_n_Slot_inst_get (insn) == 2) + return OPCODE_CALL8; + if (Field_n_Slot_inst_get (insn) == 3) + return OPCODE_CALL12; + } + if (Field_op0_Slot_inst_get (insn) == 6) + { + if (Field_n_Slot_inst_get (insn) == 0) + return OPCODE_J; + if (Field_n_Slot_inst_get (insn) == 1) + { + if (Field_m_Slot_inst_get (insn) == 0) + return OPCODE_BEQZ; + if (Field_m_Slot_inst_get (insn) == 1) + return OPCODE_BNEZ; + if (Field_m_Slot_inst_get (insn) == 2) + return OPCODE_BLTZ; + if (Field_m_Slot_inst_get (insn) == 3) + return OPCODE_BGEZ; + } + if (Field_n_Slot_inst_get (insn) == 2) + { + if (Field_m_Slot_inst_get (insn) == 0) + return OPCODE_BEQI; + if (Field_m_Slot_inst_get (insn) == 1) + return OPCODE_BNEI; + if (Field_m_Slot_inst_get (insn) == 2) + return OPCODE_BLTI; + if (Field_m_Slot_inst_get (insn) == 3) + return OPCODE_BGEI; + } + if (Field_n_Slot_inst_get (insn) == 3) + { + if (Field_m_Slot_inst_get (insn) == 0) + return OPCODE_ENTRY; + if (Field_m_Slot_inst_get (insn) == 1) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_BF; + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_BT; + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_LOOP; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_LOOPNEZ; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_LOOPGTZ; + } + if (Field_m_Slot_inst_get (insn) == 2) + return OPCODE_BLTUI; + if (Field_m_Slot_inst_get (insn) == 3) + return OPCODE_BGEUI; + } + } + if (Field_op0_Slot_inst_get (insn) == 7) + { + if (Field_r_Slot_inst_get (insn) == 0) + return OPCODE_BNONE; + if (Field_r_Slot_inst_get (insn) == 1) + return OPCODE_BEQ; + if (Field_r_Slot_inst_get (insn) == 2) + return OPCODE_BLT; + if (Field_r_Slot_inst_get (insn) == 3) + return OPCODE_BLTU; + if (Field_r_Slot_inst_get (insn) == 4) + return OPCODE_BALL; + if (Field_r_Slot_inst_get (insn) == 5) + return OPCODE_BBC; + if ((Field_r_Slot_inst_get (insn) == 6 || + Field_r_Slot_inst_get (insn) == 7)) + return OPCODE_BBCI; + if (Field_r_Slot_inst_get (insn) == 8) + return OPCODE_BANY; + if (Field_r_Slot_inst_get (insn) == 9) + return OPCODE_BNE; + if (Field_r_Slot_inst_get (insn) == 10) + return OPCODE_BGE; + if (Field_r_Slot_inst_get (insn) == 11) + return OPCODE_BGEU; + if (Field_r_Slot_inst_get (insn) == 12) + return OPCODE_BNALL; + if (Field_r_Slot_inst_get (insn) == 13) + return OPCODE_BBS; + if ((Field_r_Slot_inst_get (insn) == 14 || + Field_r_Slot_inst_get (insn) == 15)) + return OPCODE_BBSI; + } + return XTENSA_UNDEFINED; +} + +static int +Slot_inst16b_decode (const xtensa_insnbuf insn) +{ + if (Field_op0_Slot_inst16b_get (insn) == 12) + { + if (Field_i_Slot_inst16b_get (insn) == 0) + return OPCODE_MOVI_N; + if (Field_i_Slot_inst16b_get (insn) == 1) + { + if (Field_z_Slot_inst16b_get (insn) == 0) + return OPCODE_BEQZ_N; + if (Field_z_Slot_inst16b_get (insn) == 1) + return OPCODE_BNEZ_N; + } + } + if (Field_op0_Slot_inst16b_get (insn) == 13) + { + if (Field_r_Slot_inst16b_get (insn) == 0) + return OPCODE_MOV_N; + if (Field_r_Slot_inst16b_get (insn) == 15) + { + if (Field_t_Slot_inst16b_get (insn) == 0) + return OPCODE_RET_N; + if (Field_t_Slot_inst16b_get (insn) == 1) + return OPCODE_RETW_N; + if (Field_t_Slot_inst16b_get (insn) == 2) + return OPCODE_BREAK_N; + if (Field_t_Slot_inst16b_get (insn) == 3 && + Field_s_Slot_inst16b_get (insn) == 0) + return OPCODE_NOP_N; + if (Field_t_Slot_inst16b_get (insn) == 6 && + Field_s_Slot_inst16b_get (insn) == 0) + return OPCODE_ILL_N; + } + } + return XTENSA_UNDEFINED; +} + +static int +Slot_inst16a_decode (const xtensa_insnbuf insn) +{ + if (Field_op0_Slot_inst16a_get (insn) == 8) + return OPCODE_L32I_N; + if (Field_op0_Slot_inst16a_get (insn) == 9) + return OPCODE_S32I_N; + if (Field_op0_Slot_inst16a_get (insn) == 10) + return OPCODE_ADD_N; + if (Field_op0_Slot_inst16a_get (insn) == 11) + return OPCODE_ADDI_N; + return XTENSA_UNDEFINED; +} + + +/* Instruction slots. */ + +static void +Slot_x24_Format_inst_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[0] = (insn[0] & 0xffffff); +} + +static void +Slot_x24_Format_inst_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffffff) | (slotbuf[0] & 0xffffff); +} + +static void +Slot_x16a_Format_inst16a_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[0] = (insn[0] & 0xffff); +} + +static void +Slot_x16a_Format_inst16a_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffff) | (slotbuf[0] & 0xffff); +} + +static void +Slot_x16b_Format_inst16b_0_get (const xtensa_insnbuf insn, + xtensa_insnbuf slotbuf) +{ + slotbuf[0] = (insn[0] & 0xffff); +} + +static void +Slot_x16b_Format_inst16b_0_set (xtensa_insnbuf insn, + const xtensa_insnbuf slotbuf) +{ + insn[0] = (insn[0] & ~0xffff) | (slotbuf[0] & 0xffff); +} + +static xtensa_get_field_fn +Slot_inst_get_field_fns[] = { + Field_t_Slot_inst_get, + Field_bbi4_Slot_inst_get, + Field_bbi_Slot_inst_get, + Field_imm12_Slot_inst_get, + Field_imm8_Slot_inst_get, + Field_s_Slot_inst_get, + Field_imm12b_Slot_inst_get, + Field_imm16_Slot_inst_get, + Field_m_Slot_inst_get, + Field_n_Slot_inst_get, + Field_offset_Slot_inst_get, + Field_op0_Slot_inst_get, + Field_op1_Slot_inst_get, + Field_op2_Slot_inst_get, + Field_r_Slot_inst_get, + Field_sa4_Slot_inst_get, + Field_sae4_Slot_inst_get, + Field_sae_Slot_inst_get, + Field_sal_Slot_inst_get, + Field_sargt_Slot_inst_get, + Field_sas4_Slot_inst_get, + Field_sas_Slot_inst_get, + Field_sr_Slot_inst_get, + Field_st_Slot_inst_get, + Field_thi3_Slot_inst_get, + Field_imm4_Slot_inst_get, + Field_mn_Slot_inst_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r3_Slot_inst_get, + Field_rbit2_Slot_inst_get, + Field_rhi_Slot_inst_get, + Field_t3_Slot_inst_get, + Field_tbit2_Slot_inst_get, + Field_tlo_Slot_inst_get, + Field_w_Slot_inst_get, + Field_y_Slot_inst_get, + Field_x_Slot_inst_get, + Field_t2_Slot_inst_get, + Field_s2_Slot_inst_get, + Field_r2_Slot_inst_get, + Field_t4_Slot_inst_get, + Field_s4_Slot_inst_get, + Field_r4_Slot_inst_get, + Field_t8_Slot_inst_get, + Field_s8_Slot_inst_get, + Field_r8_Slot_inst_get, + Field_xt_wbr15_imm_Slot_inst_get, + Field_xt_wbr18_imm_Slot_inst_get, + Field_dfp_fld_op1_Slot_inst_get, + Field_dfp_fld_op2_Slot_inst_get, + Field_dfp_fld_r_0_Slot_inst_get, + Field_dfp_fld_r_2_1_Slot_inst_get, + Field_dfp_fld_r_3_Slot_inst_get, + Field_dfp_fld_r_3_1_Slot_inst_get, + Field_dfp_fld_s_0_Slot_inst_get, + Field_dfp_fld_s_3_1_Slot_inst_get, + Field_dfp_fld_op2_0_Slot_inst_get, + Field_dfp_fld_op2_1_0_Slot_inst_get, + Field_dfp_fld_op2_2_Slot_inst_get, + Field_dfp_fld_op2_3_Slot_inst_get, + Field_dfp_fld_op2_3_2_Slot_inst_get, + Field_dfp_fld_op2_3_1_Slot_inst_get, + Field_bitindex_Slot_inst_get, + Field_s3to1_Slot_inst_get, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_mr0_get, + Implicit_Field_mr1_get, + Implicit_Field_mr2_get, + Implicit_Field_mr3_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst_set_field_fns[] = { + Field_t_Slot_inst_set, + Field_bbi4_Slot_inst_set, + Field_bbi_Slot_inst_set, + Field_imm12_Slot_inst_set, + Field_imm8_Slot_inst_set, + Field_s_Slot_inst_set, + Field_imm12b_Slot_inst_set, + Field_imm16_Slot_inst_set, + Field_m_Slot_inst_set, + Field_n_Slot_inst_set, + Field_offset_Slot_inst_set, + Field_op0_Slot_inst_set, + Field_op1_Slot_inst_set, + Field_op2_Slot_inst_set, + Field_r_Slot_inst_set, + Field_sa4_Slot_inst_set, + Field_sae4_Slot_inst_set, + Field_sae_Slot_inst_set, + Field_sal_Slot_inst_set, + Field_sargt_Slot_inst_set, + Field_sas4_Slot_inst_set, + Field_sas_Slot_inst_set, + Field_sr_Slot_inst_set, + Field_st_Slot_inst_set, + Field_thi3_Slot_inst_set, + Field_imm4_Slot_inst_set, + Field_mn_Slot_inst_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_r3_Slot_inst_set, + Field_rbit2_Slot_inst_set, + Field_rhi_Slot_inst_set, + Field_t3_Slot_inst_set, + Field_tbit2_Slot_inst_set, + Field_tlo_Slot_inst_set, + Field_w_Slot_inst_set, + Field_y_Slot_inst_set, + Field_x_Slot_inst_set, + Field_t2_Slot_inst_set, + Field_s2_Slot_inst_set, + Field_r2_Slot_inst_set, + Field_t4_Slot_inst_set, + Field_s4_Slot_inst_set, + Field_r4_Slot_inst_set, + Field_t8_Slot_inst_set, + Field_s8_Slot_inst_set, + Field_r8_Slot_inst_set, + Field_xt_wbr15_imm_Slot_inst_set, + Field_xt_wbr18_imm_Slot_inst_set, + Field_dfp_fld_op1_Slot_inst_set, + Field_dfp_fld_op2_Slot_inst_set, + Field_dfp_fld_r_0_Slot_inst_set, + Field_dfp_fld_r_2_1_Slot_inst_set, + Field_dfp_fld_r_3_Slot_inst_set, + Field_dfp_fld_r_3_1_Slot_inst_set, + Field_dfp_fld_s_0_Slot_inst_set, + Field_dfp_fld_s_3_1_Slot_inst_set, + Field_dfp_fld_op2_0_Slot_inst_set, + Field_dfp_fld_op2_1_0_Slot_inst_set, + Field_dfp_fld_op2_2_Slot_inst_set, + Field_dfp_fld_op2_3_Slot_inst_set, + Field_dfp_fld_op2_3_2_Slot_inst_set, + Field_dfp_fld_op2_3_1_Slot_inst_set, + Field_bitindex_Slot_inst_set, + Field_s3to1_Slot_inst_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_inst16a_get_field_fns[] = { + Field_t_Slot_inst16a_get, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16a_get, + 0, + 0, + Field_r_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_sr_Slot_inst16a_get, + Field_st_Slot_inst16a_get, + 0, + Field_imm4_Slot_inst16a_get, + 0, + Field_i_Slot_inst16a_get, + Field_imm6lo_Slot_inst16a_get, + Field_imm6hi_Slot_inst16a_get, + Field_imm7lo_Slot_inst16a_get, + Field_imm7hi_Slot_inst16a_get, + Field_z_Slot_inst16a_get, + Field_imm6_Slot_inst16a_get, + Field_imm7_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_t2_Slot_inst16a_get, + Field_s2_Slot_inst16a_get, + Field_r2_Slot_inst16a_get, + Field_t4_Slot_inst16a_get, + Field_s4_Slot_inst16a_get, + Field_r4_Slot_inst16a_get, + Field_t8_Slot_inst16a_get, + Field_s8_Slot_inst16a_get, + Field_r8_Slot_inst16a_get, + 0, + 0, + 0, + 0, + Field_dfp_fld_r_0_Slot_inst16a_get, + Field_dfp_fld_r_2_1_Slot_inst16a_get, + Field_dfp_fld_r_3_Slot_inst16a_get, + Field_dfp_fld_r_3_1_Slot_inst16a_get, + Field_dfp_fld_s_0_Slot_inst16a_get, + Field_dfp_fld_s_3_1_Slot_inst16a_get, + 0, + 0, + 0, + 0, + 0, + 0, + Field_bitindex_Slot_inst16a_get, + Field_s3to1_Slot_inst16a_get, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_mr0_get, + Implicit_Field_mr1_get, + Implicit_Field_mr2_get, + Implicit_Field_mr3_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst16a_set_field_fns[] = { + Field_t_Slot_inst16a_set, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16a_set, + 0, + 0, + Field_r_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_sr_Slot_inst16a_set, + Field_st_Slot_inst16a_set, + 0, + Field_imm4_Slot_inst16a_set, + 0, + Field_i_Slot_inst16a_set, + Field_imm6lo_Slot_inst16a_set, + Field_imm6hi_Slot_inst16a_set, + Field_imm7lo_Slot_inst16a_set, + Field_imm7hi_Slot_inst16a_set, + Field_z_Slot_inst16a_set, + Field_imm6_Slot_inst16a_set, + Field_imm7_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_t2_Slot_inst16a_set, + Field_s2_Slot_inst16a_set, + Field_r2_Slot_inst16a_set, + Field_t4_Slot_inst16a_set, + Field_s4_Slot_inst16a_set, + Field_r4_Slot_inst16a_set, + Field_t8_Slot_inst16a_set, + Field_s8_Slot_inst16a_set, + Field_r8_Slot_inst16a_set, + 0, + 0, + 0, + 0, + Field_dfp_fld_r_0_Slot_inst16a_set, + Field_dfp_fld_r_2_1_Slot_inst16a_set, + Field_dfp_fld_r_3_Slot_inst16a_set, + Field_dfp_fld_r_3_1_Slot_inst16a_set, + Field_dfp_fld_s_0_Slot_inst16a_set, + Field_dfp_fld_s_3_1_Slot_inst16a_set, + 0, + 0, + 0, + 0, + 0, + 0, + Field_bitindex_Slot_inst16a_set, + Field_s3to1_Slot_inst16a_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_get_field_fn +Slot_inst16b_get_field_fns[] = { + Field_t_Slot_inst16b_get, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16b_get, + 0, + 0, + Field_r_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_sr_Slot_inst16b_get, + Field_st_Slot_inst16b_get, + 0, + Field_imm4_Slot_inst16b_get, + 0, + Field_i_Slot_inst16b_get, + Field_imm6lo_Slot_inst16b_get, + Field_imm6hi_Slot_inst16b_get, + Field_imm7lo_Slot_inst16b_get, + Field_imm7hi_Slot_inst16b_get, + Field_z_Slot_inst16b_get, + Field_imm6_Slot_inst16b_get, + Field_imm7_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_t2_Slot_inst16b_get, + Field_s2_Slot_inst16b_get, + Field_r2_Slot_inst16b_get, + Field_t4_Slot_inst16b_get, + Field_s4_Slot_inst16b_get, + Field_r4_Slot_inst16b_get, + Field_t8_Slot_inst16b_get, + Field_s8_Slot_inst16b_get, + Field_r8_Slot_inst16b_get, + 0, + 0, + 0, + 0, + Field_dfp_fld_r_0_Slot_inst16b_get, + Field_dfp_fld_r_2_1_Slot_inst16b_get, + Field_dfp_fld_r_3_Slot_inst16b_get, + Field_dfp_fld_r_3_1_Slot_inst16b_get, + Field_dfp_fld_s_0_Slot_inst16b_get, + Field_dfp_fld_s_3_1_Slot_inst16b_get, + 0, + 0, + 0, + 0, + 0, + 0, + Field_bitindex_Slot_inst16b_get, + Field_s3to1_Slot_inst16b_get, + Implicit_Field_ar0_get, + Implicit_Field_ar4_get, + Implicit_Field_ar8_get, + Implicit_Field_ar12_get, + Implicit_Field_mr0_get, + Implicit_Field_mr1_get, + Implicit_Field_mr2_get, + Implicit_Field_mr3_get, + Implicit_Field_bt16_get, + Implicit_Field_bs16_get, + Implicit_Field_br16_get, + Implicit_Field_brall_get +}; + +static xtensa_set_field_fn +Slot_inst16b_set_field_fns[] = { + Field_t_Slot_inst16b_set, + 0, + 0, + 0, + 0, + Field_s_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + Field_op0_Slot_inst16b_set, + 0, + 0, + Field_r_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_sr_Slot_inst16b_set, + Field_st_Slot_inst16b_set, + 0, + Field_imm4_Slot_inst16b_set, + 0, + Field_i_Slot_inst16b_set, + Field_imm6lo_Slot_inst16b_set, + Field_imm6hi_Slot_inst16b_set, + Field_imm7lo_Slot_inst16b_set, + Field_imm7hi_Slot_inst16b_set, + Field_z_Slot_inst16b_set, + Field_imm6_Slot_inst16b_set, + Field_imm7_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + Field_t2_Slot_inst16b_set, + Field_s2_Slot_inst16b_set, + Field_r2_Slot_inst16b_set, + Field_t4_Slot_inst16b_set, + Field_s4_Slot_inst16b_set, + Field_r4_Slot_inst16b_set, + Field_t8_Slot_inst16b_set, + Field_s8_Slot_inst16b_set, + Field_r8_Slot_inst16b_set, + 0, + 0, + 0, + 0, + Field_dfp_fld_r_0_Slot_inst16b_set, + Field_dfp_fld_r_2_1_Slot_inst16b_set, + Field_dfp_fld_r_3_Slot_inst16b_set, + Field_dfp_fld_r_3_1_Slot_inst16b_set, + Field_dfp_fld_s_0_Slot_inst16b_set, + Field_dfp_fld_s_3_1_Slot_inst16b_set, + 0, + 0, + 0, + 0, + 0, + 0, + Field_bitindex_Slot_inst16b_set, + Field_s3to1_Slot_inst16b_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set, + Implicit_Field_set +}; + +static xtensa_slot_internal slots[] = { + { "Inst", "x24", 0, + Slot_x24_Format_inst_0_get, Slot_x24_Format_inst_0_set, + Slot_inst_get_field_fns, Slot_inst_set_field_fns, + Slot_inst_decode, "nop" }, + { "Inst16a", "x16a", 0, + Slot_x16a_Format_inst16a_0_get, Slot_x16a_Format_inst16a_0_set, + Slot_inst16a_get_field_fns, Slot_inst16a_set_field_fns, + Slot_inst16a_decode, "" }, + { "Inst16b", "x16b", 0, + Slot_x16b_Format_inst16b_0_get, Slot_x16b_Format_inst16b_0_set, + Slot_inst16b_get_field_fns, Slot_inst16b_set_field_fns, + Slot_inst16b_decode, "nop.n" } +}; + + +/* Instruction formats. */ + +static void +Format_x24_encode (xtensa_insnbuf insn) +{ + insn[0] = 0; +} + +static void +Format_x16a_encode (xtensa_insnbuf insn) +{ + insn[0] = 0x8; +} + +static void +Format_x16b_encode (xtensa_insnbuf insn) +{ + insn[0] = 0xc; +} + +static int Format_x24_slots[] = { 0 }; + +static int Format_x16a_slots[] = { 1 }; + +static int Format_x16b_slots[] = { 2 }; + +static xtensa_format_internal formats[] = { + { "x24", 3, Format_x24_encode, 1, Format_x24_slots }, + { "x16a", 2, Format_x16a_encode, 1, Format_x16a_slots }, + { "x16b", 2, Format_x16b_encode, 1, Format_x16b_slots } +}; + + +static int +format_decoder (const xtensa_insnbuf insn) +{ + if ((insn[0] & 0x8) == 0) + return 0; /* x24 */ + if ((insn[0] & 0xc) == 0x8) + return 1; /* x16a */ + if ((insn[0] & 0xe) == 0xc) + return 2; /* x16b */ + return -1; +} + +static int length_table[256] = { + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + -1, + -1 +}; + +static int +length_decoder (const unsigned char *insn) +{ + int l = insn[0]; + return length_table[l]; +} + + +/* Top-level ISA structure. */ + +static xtensa_isa_internal xtensa_modules = { + 0 /* little-endian */, + 3 /* insn_size */, 0, + 3, formats, format_decoder, length_decoder, + 3, slots, + 83 /* num_fields */, + 140, operands, + 390, iclasses, + 513, opcodes, 0, + 8, regfiles, + NUM_STATES, states, 0, + NUM_SYSREGS, sysregs, 0, + { MAX_SPECIAL_REG, MAX_USER_REG }, { 0, 0 }, + 6, interfaces, 0, + 0, funcUnits, 0 +}; diff --git a/target/xtensa/cores.list b/target/xtensa/cores.list index a526a71cfd98..a936b26914c8 100644 --- a/target/xtensa/cores.list +++ b/target/xtensa/cores.list @@ -8,3 +8,4 @@ core-lx106.c core-sample_controller.c core-test_kc705_be.c core-test_mmuhifi_c3.c +core-esp32.c From b1d87e7d52dfddce8c6e1ecd234299a900cd3b7e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:34:45 +0200 Subject: [PATCH 10/56] hw/char: add ESP32 UART --- hw/char/esp32_uart.c | 401 +++++++++++++++++++++++++++++++++++ hw/char/meson.build | 1 + include/hw/char/esp32_uart.h | 96 +++++++++ 3 files changed, 498 insertions(+) create mode 100644 hw/char/esp32_uart.c create mode 100644 include/hw/char/esp32_uart.h diff --git a/hw/char/esp32_uart.c b/hw/char/esp32_uart.c new file mode 100644 index 000000000000..c8c27275666d --- /dev/null +++ b/hw/char/esp32_uart.c @@ -0,0 +1,401 @@ +/* + * ESP32 UART emulation + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * The QEMU model of nRF51 UART by Julia Suvorova was used as a template. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "sysemu/sysemu.h" +#include "chardev/char-fe.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/char/esp32_uart.h" +#include "trace.h" + + +static gboolean uart_transmit(void *do_not_use, GIOCondition cond, void *opaque); +static void uart_receive(void *opaque, const uint8_t *buf, int size); +static void uart_set_rx_timeout(ESP32UARTState *s); + +static uint8_t fifo8_peek(Fifo8 *fifo) +{ + if (fifo->num == 0) { + abort(); + } + return fifo->data[fifo->head]; +} + +static void uart_update_irq(ESP32UARTState *s) +{ + bool irq = false; + + uint32_t tx_empty_threshold = FIELD_EX32(s->reg[R_UART_CONF1], UART_CONF1, TXFIFO_EMPTY_THRD); + uint32_t rx_full_threshold = FIELD_EX32(s->reg[R_UART_CONF1], UART_CONF1, RXFIFO_FULL_THRD); + + uint32_t tx_empty_raw = (fifo8_num_used(&s->tx_fifo) <= tx_empty_threshold); + uint32_t rx_full_raw = (fifo8_num_used(&s->rx_fifo) >= rx_full_threshold); + uint32_t tx_done_raw = (fifo8_num_used(&s->tx_fifo) == 0); + uint32_t rxfifo_tout_raw = (s->rxfifo_tout) ? 1 : 0; + + uint32_t int_raw = s->reg[R_UART_INT_RAW]; + int_raw = FIELD_DP32(int_raw, UART_INT_RAW, RXFIFO_FULL, rx_full_raw); + int_raw = FIELD_DP32(int_raw, UART_INT_RAW, TXFIFO_EMPTY, tx_empty_raw); + int_raw = FIELD_DP32(int_raw, UART_INT_RAW, TX_DONE, tx_done_raw); + int_raw = FIELD_DP32(int_raw, UART_INT_RAW, RXFIFO_TOUT, rxfifo_tout_raw); + s->reg[R_UART_INT_RAW] = int_raw; + + uint32_t int_st = s->reg[R_UART_INT_RAW] & s->reg[R_UART_INT_ENA]; + irq = int_st != 0; + s->reg[R_UART_INT_ST] = int_st; + + qemu_set_irq(s->irq, irq); +} + +static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32UARTState *s = ESP32_UART(opaque); + uint64_t r = 0; + + switch (addr) { + case A_UART_FIFO: + if (fifo8_num_used(&s->rx_fifo) == 0) { + r = 0xEE; + error_report("esp_uart: read UART FIFO while it is empty"); + } else { + r = fifo8_pop(&s->rx_fifo); + uart_update_irq(s); + qemu_chr_fe_accept_input(&s->chr); + } + break; + + case A_UART_STATUS: + r = FIELD_DP32(r, UART_STATUS, RXFIFO_CNT, fifo8_num_used(&s->rx_fifo)); + r = FIELD_DP32(r, UART_STATUS, TXFIFO_CNT, fifo8_num_used(&s->tx_fifo)); + break; + + case A_UART_LOWPULSE: + case A_UART_HIGHPULSE: + r = 337; /* FIXME: this should depend on the APB frequency */ + break; + case A_UART_MEM_CONF: + r = FIELD_DP32(r, UART_MEM_CONF, RX_SIZE, (unsigned char)(UART_FIFO_LENGTH/128)); + r = FIELD_DP32(r, UART_MEM_CONF, TX_SIZE, (unsigned char)(UART_FIFO_LENGTH/128)); + break; + case A_UART_MEM_RX_STATUS: { + uint32_t fifo_size = fifo8_num_used(&s->rx_fifo); + /* The software only cares about the differene between WR_ADDR and RD_ADDR; + * to keep things simpler, set RD_ADDR to 0 and WR_ADDR to the number of bytes + * in the FIFO. 128 is a special case — write and read pointers should be + * the same in this case. + */ + r = FIELD_DP32(0, UART_MEM_RX_STATUS, WR_ADDR, (fifo_size == 128) ? 0 : fifo_size); + } + break; + case A_UART_DATE: + r = 0x15122500; + break; + default: + r = s->reg[addr / 4]; + break; + } + + return r; +} + + +static void uart_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32UARTState *s = ESP32_UART(opaque); + + switch (addr) { + case A_UART_FIFO: + if (fifo8_num_free(&s->tx_fifo) == 0) { + error_report("esp_uart: write to UART FIFO while it is full"); + } else { + fifo8_push(&s->tx_fifo, (uint8_t) (value & 0xff)); + uart_transmit(NULL, G_IO_OUT, s); + } + break; + + case A_UART_INT_CLR: + s->reg[R_UART_INT_ST] &= ~((uint32_t) value); + s->reg[addr / 4] = value; + if (value & R_UART_INT_CLR_RXFIFO_TOUT_MASK) { + s->rxfifo_tout = false; + } + break; + + case A_UART_INT_ENA: + s->reg[addr / 4] = value; + break; + + case A_UART_CLKDIV: { + s->reg[addr / 4] = value; + unsigned clkdiv = (FIELD_EX32(s->reg[R_UART_CLKDIV], UART_CLKDIV, CLKDIV) << 4) + + FIELD_EX32(s->reg[R_UART_CLKDIV], UART_CLKDIV, CLKDIV_FRAG); + unsigned baud_rate = 115200; + if (clkdiv != 0) { + /* FIXME: this should depend on the APB frequency */ + baud_rate = (unsigned) ((40000000ULL << 4) / clkdiv); + } + s->baud_rate = baud_rate; + break; + } + + case A_UART_AUTOBAUD: + /* If autobaud is enabled, pretend that sufficient number of edges on the RXD line + * have been received instantly. Autobaud is only used in the ROM bootloader, + * and it doesn't care if the result is ready immediately. + */ + if (FIELD_EX32(value, UART_AUTOBAUD, EN)) { + s->reg[R_UART_RXD_CNT] = 0x3FF; + } else { + s->reg[R_UART_RXD_CNT] = 0; + } + s->reg[addr / 4] = value; + break; + + case A_UART_INT_RAW: + case A_UART_INT_ST: + case A_UART_STATUS: + /* no-op */ + break; + + case A_UART_CONF1: + s->reg[addr / 4] = value; + uart_set_rx_timeout(s); + uart_update_irq(s); + break; + + default: + if (addr > sizeof(s->reg)) { + error_report("esp_uart: write to addr=0x%x out of bounds\n", (uint32_t) addr); + } else { + s->reg[addr / 4] = value; + } + break; + + } + uart_update_irq(s); +} + + +static gboolean uart_transmit(void *do_not_use, GIOCondition cond, void *opaque) +{ + ESP32UARTState *s = ESP32_UART(opaque); + + s->tx_watch_handle = 0; + + /* drain the fifo instantly, if the char device backend is not connected */ + if (!qemu_chr_fe_backend_open(&s->chr)) { + fifo8_reset(&s->tx_fifo); + return FALSE; + } + + while (fifo8_num_used(&s->tx_fifo) > 0) { + uint8_t b = fifo8_peek(&s->tx_fifo); + int r = qemu_chr_fe_write(&s->chr, &b, 1); + if (r == 1) { + fifo8_pop(&s->tx_fifo); + } else { + s->tx_watch_handle = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP, + uart_transmit, s); + break; + } + } + + uart_update_irq(s); + + return FALSE; +} + +static void uart_receive(void *opaque, const uint8_t *buf, int size) +{ + ESP32UARTState *s = ESP32_UART(opaque); + + if (size == 0) { + return; + } + + /* If we can receive anything: cancel any pending RX timeout timer, + * and clear the receive timeout flag. + */ + if (fifo8_num_free(&s->rx_fifo) > 0) { + timer_del(&s->rx_timeout_timer); + s->rxfifo_tout = false; + } + + /* Move the data into the FIFO */ + for (int i = 0; i < size && fifo8_num_free(&s->rx_fifo) > 0; i++) { + fifo8_push(&s->rx_fifo, buf[i]); + } + + /* Receive throttling: some applications (in particular the ESP32 ROM bootloader) + * may work incorrectly if the data comes in much faster than what UART baud rate + * would allow. This code adds a delay every UART_FIFO_LENGTH bytes, to make the + * average data rate match the configured baud rate. + * This doesn't need to be very precise, so only add the delay if the FIFO is full + * (which most likely means that more data will come). + */ + if (fifo8_is_full(&s->rx_fifo)) { + s->throttle_rx = true; + const int bits_per_symbol = 10; + int64_t throttle_time_ns = (int64_t) UART_FIFO_LENGTH * bits_per_symbol * NANOSECONDS_PER_SECOND / s->baud_rate; + timer_mod_ns(&s->throttle_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + throttle_time_ns); + } + + uart_set_rx_timeout(s); + uart_update_irq(s); +} + +static void uart_set_rx_timeout(ESP32UARTState *s) +{ + if (FIELD_EX32(s->reg[R_UART_CONF1], UART_CONF1, TOUT_EN)) { + unsigned threshold_reg = FIELD_EX32(s->reg[R_UART_CONF1], UART_CONF1, TOUT_THRD); + /* On the ESP32, threshold_reg is in units of (bit_time * 8). + * Note this is different on later chips. + */ + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + int64_t rx_timeout_ns = now + threshold_reg * 8 * NANOSECONDS_PER_SECOND / s->baud_rate; + /* If throttling is done, make sure timeout doesn't happen before more data + * is allowed to come. Offset it by 1ms. + */ + if (rx_timeout_ns <= s->throttle_timer.expire_time) { + rx_timeout_ns = s->throttle_timer.expire_time + 10000000; + } + timer_mod_ns(&s->rx_timeout_timer, rx_timeout_ns); + } else { + timer_del(&s->rx_timeout_timer); + s->rxfifo_tout = false; + } +} + +static int uart_can_receive(void *opaque) +{ + ESP32UARTState *s = ESP32_UART(opaque); + if (s->throttle_rx) { + return 0; + } + return fifo8_num_free(&s->rx_fifo); +} + +static void uart_event(void *opaque, QEMUChrEvent event) +{ + /* TODO: handle UART break */ +} + + +static void uart_throttle_timer_cb(void* opaque) +{ + ESP32UARTState *s = ESP32_UART(opaque); + s->throttle_rx = false; + qemu_chr_fe_accept_input(&s->chr); +} + +static void uart_rx_timeout_timer_cb(void* opaque) +{ + ESP32UARTState *s = ESP32_UART(opaque); + s->rxfifo_tout = true; + uart_update_irq(s); +} + +static void esp32_uart_reset(DeviceState *dev) +{ + ESP32UARTState *s = ESP32_UART(dev); + + memset(s->reg, 0, sizeof(s->reg)); + s->reg[R_UART_RXD_CNT] = 0; + s->reg[R_UART_INT_ST] = 0; + s->reg[R_UART_INT_RAW] = 0; + s->reg[R_UART_INT_ENA] = 0; + s->reg[R_UART_AUTOBAUD] = 0; + /* Default baud rate divider after reset */ + s->reg[R_UART_CLKDIV] = FIELD_DP32(0, UART_CLKDIV, CLKDIV, 0x2B6); + s->baud_rate = 115200; + fifo8_reset(&s->tx_fifo); + fifo8_reset(&s->rx_fifo); + if (s->tx_watch_handle) { + g_source_remove(s->tx_watch_handle); + s->tx_watch_handle = 0; + } + timer_del(&s->throttle_timer); + s->throttle_rx = false; + qemu_irq_lower(s->irq); +} + + +static void esp32_uart_realize(DeviceState *dev, Error **errp) +{ + ESP32UARTState *s = ESP32_UART(dev); + + qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive, + uart_event, NULL, s, NULL, true); +} + + +static const MemoryRegionOps uart_ops = { + .read = uart_read, + .write = uart_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_uart_init(Object *obj) +{ + ESP32UARTState *s = ESP32_UART(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &uart_ops, s, + TYPE_ESP32_UART, UART_REG_CNT * sizeof(uint32_t)); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + fifo8_create(&s->tx_fifo, UART_FIFO_LENGTH); + fifo8_create(&s->rx_fifo, UART_FIFO_LENGTH); + timer_init_ns(&s->throttle_timer, QEMU_CLOCK_VIRTUAL, uart_throttle_timer_cb, s); + timer_init_ns(&s->rx_timeout_timer, QEMU_CLOCK_VIRTUAL, uart_rx_timeout_timer_cb, s); +} + + +static Property esp32_uart_properties[] = { + DEFINE_PROP_CHR("chardev", ESP32UARTState, chr), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_uart_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_uart_reset; + dc->realize = esp32_uart_realize; + device_class_set_props(dc, esp32_uart_properties); +} + +static const TypeInfo esp32_uart_info = { + .name = TYPE_ESP32_UART, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32UARTState), + .instance_init = esp32_uart_init, + .class_init = esp32_uart_class_init +}; + +static void esp32_uart_register_types(void) +{ + type_register_static(&esp32_uart_info); +} + +type_init(esp32_uart_register_types) diff --git a/hw/char/meson.build b/hw/char/meson.build index e02c60dd54d9..17385b58036a 100644 --- a/hw/char/meson.build +++ b/hw/char/meson.build @@ -32,6 +32,7 @@ softmmu_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c')) softmmu_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c')) softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c')) softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c')) +softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_uart.c')) specific_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c')) specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c')) diff --git a/include/hw/char/esp32_uart.h b/include/hw/char/esp32_uart.h new file mode 100644 index 000000000000..1f0a7bb21b49 --- /dev/null +++ b/include/hw/char/esp32_uart.h @@ -0,0 +1,96 @@ +#pragma once + +#include "qemu/fifo8.h" +#include "hw/sysbus.h" +#include "chardev/char-fe.h" +#include "hw/hw.h" +#include "hw/registerfields.h" + +#define UART_FIFO_LENGTH 128 + +#define TYPE_ESP32_UART "esp_soc.uart" +#define ESP32_UART(obj) OBJECT_CHECK(ESP32UARTState, (obj), TYPE_ESP32_UART) + +REG32(UART_FIFO, 0x0) +REG32(UART_INT_RAW, 0x4) + FIELD(UART_INT_RAW, RXFIFO_FULL, 0, 1) + FIELD(UART_INT_RAW, TXFIFO_EMPTY, 1, 1) + FIELD(UART_INT_RAW, RXFIFO_OVF, 4, 1) + FIELD(UART_INT_RAW, RXFIFO_TOUT, 8, 1) + FIELD(UART_INT_RAW, TX_DONE, 14, 1) +REG32(UART_INT_ST, 0x8) + FIELD(UART_INT_ST, RXFIFO_FULL, 0, 1) + FIELD(UART_INT_ST, TXFIFO_EMPTY, 1, 1) + FIELD(UART_INT_ST, RXFIFO_OVF, 4, 1) + FIELD(UART_INT_ST, RXFIFO_TOUT, 8, 1) + FIELD(UART_INT_ST, TX_DONE, 14, 1) +REG32(UART_INT_ENA, 0xC) + FIELD(UART_INT_ENA, RXFIFO_FULL, 0, 1) + FIELD(UART_INT_ENA, TXFIFO_EMPTY, 1, 1) + FIELD(UART_INT_ENA, RXFIFO_OVF, 4, 1) + FIELD(UART_INT_ENA, RXFIFO_TOUT, 8, 1) + FIELD(UART_INT_ENA, TX_DONE, 14, 1) +REG32(UART_INT_CLR, 0x10) + FIELD(UART_INT_CLR, RXFIFO_FULL, 0, 1) + FIELD(UART_INT_CLR, TXFIFO_EMPTY, 1, 1) + FIELD(UART_INT_CLR, RXFIFO_OVF, 4, 1) + FIELD(UART_INT_CLR, RXFIFO_TOUT, 8, 1) + FIELD(UART_INT_CLR, TX_DONE, 14, 1) + +/* TODO: implement */ +REG32(UART_CLKDIV, 0x14) + FIELD(UART_CLKDIV, CLKDIV, 0, 20) + FIELD(UART_CLKDIV, CLKDIV_FRAG, 20, 4) + +REG32(UART_AUTOBAUD, 0x18) + FIELD(UART_AUTOBAUD, EN, 0, 1) + +REG32(UART_STATUS, 0x1C) + FIELD(UART_STATUS, RXFIFO_CNT, 0, 8) + FIELD(UART_STATUS, ST_URX_OUT, 8, 4) + FIELD(UART_STATUS, TXFIFO_CNT, 16, 8) + FIELD(UART_STATUS, ST_UTX_OUT, 24, 4) + +REG32(UART_LOWPULSE, 0x28) +REG32(UART_HIGHPULSE, 0x2c) +REG32(UART_RXD_CNT, 0x30) + +/* TODO: implement */ +REG32(UART_CONF0, 0x20) +REG32(UART_CONF1, 0x24) + FIELD(UART_CONF1, TOUT_EN, 31, 1) + FIELD(UART_CONF1, TOUT_THRD, 24, 7) + FIELD(UART_CONF1, TXFIFO_EMPTY_THRD, 8, 7) + FIELD(UART_CONF1, RXFIFO_FULL_THRD, 0, 7) + +REG32(UART_MEM_CONF, 0x58); + FIELD(UART_MEM_CONF, RX_SIZE, 3, 4); + FIELD(UART_MEM_CONF, TX_SIZE, 7, 4); +REG32(UART_MEM_RX_STATUS, 0x60); + FIELD(UART_MEM_RX_STATUS, RD_ADDR, 2, 11); + FIELD(UART_MEM_RX_STATUS, WR_ADDR, 13, 11); +REG32(UART_DATE, 0x78) + +/* Size of the register file */ +#define UART_REG_CNT (R_UART_DATE + 1) + + +typedef struct ESPUARTState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + CharBackend chr; + qemu_irq irq; + QEMUTimer throttle_timer; + QEMUTimer rx_timeout_timer; + bool throttle_rx; + bool rxfifo_tout; + unsigned baud_rate; + + Fifo8 rx_fifo; + Fifo8 tx_fifo; + guint tx_watch_handle; + + uint32_t reg[UART_REG_CNT]; +} ESP32UARTState; + From aad3a7b47222e742c510844e1da5dcebeeef8ed2 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:34:56 +0200 Subject: [PATCH 11/56] hw/gpio: add ESP32 GPIO --- hw/gpio/esp32_gpio.c | 96 ++++++++++++++++++++++++++++++++++++ hw/gpio/meson.build | 1 + include/hw/gpio/esp32_gpio.h | 22 +++++++++ 3 files changed, 119 insertions(+) create mode 100644 hw/gpio/esp32_gpio.c create mode 100644 include/hw/gpio/esp32_gpio.h diff --git a/hw/gpio/esp32_gpio.c b/hw/gpio/esp32_gpio.c new file mode 100644 index 000000000000..190576499837 --- /dev/null +++ b/hw/gpio/esp32_gpio.c @@ -0,0 +1,96 @@ +/* + * ESP32 GPIO emulation + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/gpio/esp32_gpio.h" + + + +static uint64_t esp32_gpio_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32GpioState *s = ESP32_GPIO(opaque); + uint64_t r = 0; + switch (addr) { + case A_GPIO_STRAP: + r = s->strap_mode; + break; + + default: + break; + } + return r; +} + +static void esp32_gpio_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ +} + +static const MemoryRegionOps uart_ops = { + .read = esp32_gpio_read, + .write = esp32_gpio_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_gpio_reset(DeviceState *dev) +{ +} + +static void esp32_gpio_realize(DeviceState *dev, Error **errp) +{ +} + +static void esp32_gpio_init(Object *obj) +{ + Esp32GpioState *s = ESP32_GPIO(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &uart_ops, s, + TYPE_ESP32_GPIO, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); +} + +static Property esp32_gpio_properties[] = { + DEFINE_PROP_UINT32("strap_mode", Esp32GpioState, strap_mode, ESP32_STRAP_MODE_FLASH_BOOT), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_gpio_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_gpio_reset; + dc->realize = esp32_gpio_realize; + device_class_set_props(dc, esp32_gpio_properties); +} + +static const TypeInfo esp32_gpio_info = { + .name = TYPE_ESP32_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32GpioState), + .instance_init = esp32_gpio_init, + .class_init = esp32_gpio_class_init +}; + +static void esp32_gpio_register_types(void) +{ + type_register_static(&esp32_gpio_info); +} + +type_init(esp32_gpio_register_types) diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build index b726e6d27a41..ed4a9c99be1d 100644 --- a/hw/gpio/meson.build +++ b/hw/gpio/meson.build @@ -12,3 +12,4 @@ softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_gpio.c')) softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c')) softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c')) +softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_gpio.c')) diff --git a/include/hw/gpio/esp32_gpio.h b/include/hw/gpio/esp32_gpio.h new file mode 100644 index 000000000000..38632c3c08f1 --- /dev/null +++ b/include/hw/gpio/esp32_gpio.h @@ -0,0 +1,22 @@ +#pragma once + +#include "hw/sysbus.h" +#include "hw/hw.h" +#include "hw/registerfields.h" + +#define TYPE_ESP32_GPIO "esp32.gpio" +#define ESP32_GPIO(obj) OBJECT_CHECK(Esp32GpioState, (obj), TYPE_ESP32_GPIO) + +REG32(GPIO_STRAP, 0x0038) + +#define ESP32_STRAP_MODE_FLASH_BOOT 0x12 +#define ESP32_STRAP_MODE_UART_BOOT 0x0f + +typedef struct Esp32GpioState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + uint32_t strap_mode; +} Esp32GpioState; + From cc04899e2156cca8b3bbaffe5670e9fa32b2c7f8 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:35:10 +0200 Subject: [PATCH 12/56] hw/nvram: add ESP32 eFuse --- hw/nvram/esp32_efuse.c | 307 +++++++++++++++++++++++++++++++++ hw/nvram/meson.build | 1 + include/hw/nvram/esp32_efuse.h | 131 ++++++++++++++ 3 files changed, 439 insertions(+) create mode 100644 hw/nvram/esp32_efuse.c create mode 100644 include/hw/nvram/esp32_efuse.h diff --git a/hw/nvram/esp32_efuse.c b/hw/nvram/esp32_efuse.c new file mode 100644 index 000000000000..41c033e9020c --- /dev/null +++ b/hw/nvram/esp32_efuse.c @@ -0,0 +1,307 @@ +/* + * ESP32 eFuse emulation + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "sysemu/sysemu.h" +#include "chardev/char-fe.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/nvram/esp32_efuse.h" + +static void esp32_efuse_read_op(Esp32EfuseState *s); +static void esp32_efuse_program_op(Esp32EfuseState *s); +static void esp32_efuse_update_irq(Esp32EfuseState *s); +static void esp32_efuse_op_timer_start(Esp32EfuseState *s); + +static uint64_t esp32_efuse_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32EfuseState *s = ESP32_EFUSE(opaque); + uint64_t r = 0; + int idx; + switch (addr) { + case A_EFUSE_BLK0_RDATA0 ... A_EFUSE_BLK0_WDATA0 - 4: + idx = (addr - A_EFUSE_BLK0_RDATA0) / 4; + r = s->efuse_rd.blk0[idx] & ~(s->efuse_rd_dis.blk0[idx]); + break; + case A_EFUSE_BLK0_WDATA0 ... A_EFUSE_BLK1_RDATA0 - 4: + r = s->efuse_wr.blk0[(addr - A_EFUSE_BLK0_WDATA0) / 4]; + break; + case A_EFUSE_BLK1_RDATA0 ... A_EFUSE_BLK2_RDATA0 - 4: + idx = (addr - A_EFUSE_BLK1_RDATA0) / 4; + r = s->efuse_rd.blk1[idx] & ~(s->efuse_rd_dis.blk1[idx]); + break; + case A_EFUSE_BLK2_RDATA0 ... A_EFUSE_BLK3_RDATA0 - 4: + idx = (addr - A_EFUSE_BLK2_RDATA0) / 4; + r = s->efuse_rd.blk2[idx] & ~(s->efuse_rd_dis.blk2[idx]); + break; + case A_EFUSE_BLK3_RDATA0 ... A_EFUSE_BLK1_WDATA0 - 4: + idx = (addr - A_EFUSE_BLK3_RDATA0) / 4; + r = s->efuse_rd.blk3[idx] & ~(s->efuse_rd_dis.blk3[idx]); + break; + case A_EFUSE_BLK1_WDATA0 ... A_EFUSE_BLK2_WDATA0 - 4: + r = s->efuse_wr.blk1[(addr - A_EFUSE_BLK1_WDATA0) / 4]; + break; + case A_EFUSE_BLK2_WDATA0 ... A_EFUSE_BLK3_WDATA0 - 4: + r = s->efuse_wr.blk2[(addr - A_EFUSE_BLK2_WDATA0) / 4]; + break; + case A_EFUSE_BLK3_WDATA0 ... A_EFUSE_CLK - 4: + r = s->efuse_wr.blk3[(addr - A_EFUSE_BLK3_WDATA0) / 4]; + break; + case A_EFUSE_CLK: + r = s->clk_reg; + break; + case A_EFUSE_CONF: + r = s->conf_reg; + break; + case A_EFUSE_CMD: + r = s->cmd_reg; + break; + case A_EFUSE_STATUS: + r = 0; + break; + case A_EFUSE_DAC_CONF: + r = s->dac_conf_reg; + break; + case A_EFUSE_INT_RAW: + r = s->int_raw_reg; + break; + case A_EFUSE_INT_ST: + r = s->int_st_reg; + break; + case A_EFUSE_INT_ENA: + r = s->int_ena_reg; + break; + case A_EFUSE_DEC_STATUS: + r = 0; + break; + case A_EFUSE_DATE: + r = 0x16042600; + } + return r; +} + +static void esp32_efuse_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32EfuseState *s = ESP32_EFUSE(opaque); + switch (addr) { + case A_EFUSE_CLK: + s->clk_reg = value; + break; + case A_EFUSE_CONF: + s->conf_reg = value; + break; + case A_EFUSE_CMD: + if ((value & EFUSE_READ) && s->conf_reg == EFUSE_READ_OP_CODE) { + esp32_efuse_read_op(s); + } + if ((value & EFUSE_PGM) && s->conf_reg == EFUSE_PGM_OP_CODE) { + esp32_efuse_program_op(s); + } + break; + case A_EFUSE_DAC_CONF: + s->dac_conf_reg = value; + break; + case A_EFUSE_INT_ENA: + s->int_ena_reg = value; + esp32_efuse_update_irq(s); + break; + case A_EFUSE_INT_CLR: + s->int_raw_reg &= ~value; + esp32_efuse_update_irq(s); + break; + case A_EFUSE_BLK0_WDATA0 ... A_EFUSE_BLK1_RDATA0 - 4: + s->efuse_wr.blk0[(addr - A_EFUSE_BLK0_WDATA0) / 4] = value; + break; + case A_EFUSE_BLK1_WDATA0 ... A_EFUSE_BLK2_WDATA0 - 4: + s->efuse_wr.blk1[(addr - A_EFUSE_BLK1_WDATA0) / 4] = value; + break; + case A_EFUSE_BLK2_WDATA0 ... A_EFUSE_BLK3_WDATA0 - 4: + s->efuse_wr.blk2[(addr - A_EFUSE_BLK2_WDATA0) / 4] = value; + break; + case A_EFUSE_BLK3_WDATA0 ... A_EFUSE_CLK - 4: + s->efuse_wr.blk3[(addr - A_EFUSE_BLK3_WDATA0) / 4] = value; + break; + } +} + +#define APPLY_DIS(rdwr_, ctrl_field_, dest_field_) \ + if (s->efuse_ ## rdwr_ .blk0_d0.ctrl_field_) { \ + memset(&s->efuse_ ## rdwr_ ## _dis.dest_field_, 0xff, sizeof(s->efuse_ ## rdwr_ ## _dis.dest_field_)); \ + } + +#define APPLY_DIS_FIELD(rdwr_, ctrl_field_, dest_field_) \ + if (s->efuse_ ## rdwr_ .blk0_d0.ctrl_field_) { \ + s->efuse_ ## rdwr_ ## _dis.dest_field_ = 0; \ + s->efuse_ ## rdwr_ ## _dis.dest_field_ -= 1; \ + } + + +static void esp32_efuse_read_op(Esp32EfuseState *s) +{ + s->cmd_reg = EFUSE_READ; + if (s->blk != NULL) { + int ret = blk_pread(s->blk, 0, sizeof(s->efuse_rd), &s->efuse_rd, 0); + if (ret < 0) { + error_report("%s: failed to read the block device (%d)", __func__, ret); + return; + } + } + + memset(&s->efuse_rd_dis, 0, sizeof(s->efuse_rd_dis)); + memset(&s->efuse_wr_dis, 0, sizeof(s->efuse_wr_dis)); + + APPLY_DIS(rd, rd_dis_blk1, blk1); + APPLY_DIS(rd, rd_dis_blk2, blk2); + APPLY_DIS(rd, rd_dis_blk3, blk3); + APPLY_DIS_FIELD(rd, rd_dis_blk0_partial, blk0_d5.flash_crypt_config); + APPLY_DIS_FIELD(rd, rd_dis_blk0_partial, blk0_d6.coding_scheme); + APPLY_DIS_FIELD(rd, rd_dis_blk0_partial, blk0_d6.key_status); + + APPLY_DIS(wr, wr_dis_blk1, blk1); + APPLY_DIS(wr, wr_dis_blk2, blk2); + APPLY_DIS(wr, wr_dis_blk3, blk3); + + /* Other wr_dis bits are not emulated, but can be handled here if necessary */ + + esp32_efuse_op_timer_start(s); + qemu_irq_pulse(s->efuse_update_gpio); +} + +static void esp32_efuse_program_op(Esp32EfuseState *s) +{ + s->cmd_reg = EFUSE_PGM; + + Esp32EfuseRegs result; + uint32_t* dst = (uint32_t*) &result; + uint32_t* rd = (uint32_t*) &s->efuse_rd; + uint32_t* wr = (uint32_t*) &s->efuse_wr; + uint32_t* wr_dis = (uint32_t*) &s->efuse_wr_dis; + for (int i = 0; i < sizeof(result) / sizeof(uint32_t); ++i) { + uint32_t wr_word = wr[i]; + uint32_t wr_dis_word = wr_dis[i]; + uint32_t rd_word = rd[i]; + dst[i] = (wr_word & (~wr_dis_word)) | rd_word; + } + + if (s->blk != NULL) { + int ret = blk_pwrite(s->blk, 0, sizeof(result), &result, 0); + if (ret < 0) { + error_report("%s: failed to write to block device (%d)", __func__, ret); + } + } + + esp32_efuse_op_timer_start(s); +} + +static void esp32_efuse_update_irq(Esp32EfuseState *s) +{ + s->int_st_reg = s->int_ena_reg & s->int_raw_reg; + int level = s->int_st_reg != 0; + qemu_set_irq(s->irq, level); +} + +static void esp32_efuse_op_timer_start(Esp32EfuseState *s) +{ + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t interval_ns = 100000000; /* 10 ms, make this depend on EFUSE_CLK register */ + timer_mod_anticipate_ns(&s->op_timer, ns_now + interval_ns); +} + +static void esp32_efuse_timer_cb(void *opaque) +{ + Esp32EfuseState *s = ESP32_EFUSE(opaque); + uint32_t cmd = s->cmd_reg; + s->cmd_reg = 0; + s->int_raw_reg |= cmd; + esp32_efuse_update_irq(s); +} + +static const MemoryRegionOps esp32_efuse_ops = { + .read = esp32_efuse_read, + .write = esp32_efuse_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_efuse_reset(DeviceState *dev) +{ + Esp32EfuseState *s = ESP32_EFUSE(dev); + esp32_efuse_read_op(s); +} + +static void esp32_efuse_realize(DeviceState *dev, Error **errp) +{ + Esp32EfuseState *s = ESP32_EFUSE(dev); + if (s->blk != NULL) { + if (!blk_supports_write_perm(s->blk)) { + error_setg(errp, "%s: block device is not writeable", __func__); + return; + } + uint64_t perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE; + int ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, NULL); + if (ret != 0) { + error_setg(errp, "%s: failed to set permission (%d)", __func__, ret); + return; + } + } +} + +static void esp32_efuse_init(Object *obj) +{ + Esp32EfuseState *s = ESP32_EFUSE(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_efuse_ops, s, + TYPE_ESP32_EFUSE, A_EFUSE_DATE + 4); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + + timer_init_ns(&s->op_timer, QEMU_CLOCK_VIRTUAL, esp32_efuse_timer_cb, s); + qdev_init_gpio_out_named(DEVICE(sbd), &s->efuse_update_gpio, ESP32_EFUSE_UPDATE_GPIO, 1); + + memset(&s->efuse_rd, 0, sizeof(s->efuse_rd)); + memset(&s->efuse_wr, 0, sizeof(s->efuse_wr)); +} + +static Property esp32_efuse_properties[] = { + DEFINE_PROP_DRIVE("drive", Esp32EfuseState, blk), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_efuse_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_efuse_reset; + dc->realize = esp32_efuse_realize; + device_class_set_props(dc, esp32_efuse_properties); +} + +static const TypeInfo esp32_efuse_info = { + .name = TYPE_ESP32_EFUSE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32EfuseState), + .instance_init = esp32_efuse_init, + .class_init = esp32_efuse_class_init +}; + +static void esp32_efuse_register_types(void) +{ + type_register_static(&esp32_efuse_info); +} + +type_init(esp32_efuse_register_types) diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index f5ee9f6b88c4..123dbc9555f5 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -11,6 +11,7 @@ softmmu_ss.add(when: 'CONFIG_AT24C', if_true: files('eeprom_at24c.c')) softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c')) softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) +softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_CRC', if_true: files('xlnx-efuse-crc.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( diff --git a/include/hw/nvram/esp32_efuse.h b/include/hw/nvram/esp32_efuse.h new file mode 100644 index 000000000000..29bb99c01fcf --- /dev/null +++ b/include/hw/nvram/esp32_efuse.h @@ -0,0 +1,131 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_reg.h" +#include "sysemu/block-backend.h" + +#define TYPE_ESP32_EFUSE "nvram.esp32.efuse" +#define ESP32_EFUSE(obj) OBJECT_CHECK(Esp32EfuseState, (obj), TYPE_ESP32_EFUSE) + +REG32(EFUSE_BLK0_RDATA0, 0x00) +REG32(EFUSE_BLK0_WDATA0, 0x1c) +REG32(EFUSE_BLK1_RDATA0, 0x38) +REG32(EFUSE_BLK2_RDATA0, 0x58) +REG32(EFUSE_BLK3_RDATA0, 0x78) +REG32(EFUSE_BLK1_WDATA0, 0x98) +REG32(EFUSE_BLK2_WDATA0, 0xb8) +REG32(EFUSE_BLK3_WDATA0, 0xd8) +REG32(EFUSE_CLK, 0xf8) +REG32(EFUSE_CONF, 0xfc) + FIELD(EFUSE_CONF, OP_CODE, 0, 16) +REG32(EFUSE_STATUS, 0x100) +REG32(EFUSE_CMD, 0x104) +REG32(EFUSE_INT_RAW, 0x108) +REG32(EFUSE_INT_ST, 0x10c) +REG32(EFUSE_INT_ENA, 0x110) +REG32(EFUSE_INT_CLR, 0x114) +REG32(EFUSE_DAC_CONF, 0x118) +REG32(EFUSE_DEC_STATUS, 0x11c) +REG32(EFUSE_DATE, 0x1fc) + +/* the following bit masks apply to CMD, INT_RAW, INT_ST, INT_ENA, INT_CLR */ +#define EFUSE_READ 0x01 +#define EFUSE_PGM 0x02 + +/* expected values of EFUSE_CONF OP_CODE field */ +#define EFUSE_READ_OP_CODE 0x5AA5 +#define EFUSE_PGM_OP_CODE 0x5A5A + +#define ESP32_EFUSE_UPDATE_GPIO "efuse-update" + + +typedef struct Esp32EfuseRegs { + union { + struct { + struct { + uint32_t wr_dis_rd_dis : 1; + uint32_t wr_dis_wr_dis : 1; + uint32_t wr_dis_flash_crypt_cnt : 1; + uint32_t wr_dis_mac_spi_config : 1; + uint32_t wr_dis_unused1 : 1; + uint32_t wr_dis_xpd_sdio : 1; + uint32_t wr_dis_spi_pad_config : 1; + uint32_t wr_dis_blk1 : 1; + uint32_t wr_dis_blk2 : 1; + uint32_t wr_dis_blk3 : 1; + uint32_t wr_dis_flash_crypt_coding_scheme : 1; + uint32_t wr_dis_unused2 : 1; + uint32_t wr_dis_abs_done_0 : 1; + uint32_t wr_dis_abs_done_1 : 1; + uint32_t wr_dis_jtag_disable : 1; + uint32_t wr_dis_console_dl_disable : 1; + + uint32_t rd_dis_blk1 : 1; + uint32_t rd_dis_blk2 : 1; + uint32_t rd_dis_blk3 : 1; + uint32_t rd_dis_blk0_partial : 1; + + uint32_t flash_crypt_cnt : 7; + } blk0_d0; + uint32_t blk0_d1; + uint32_t blk0_d2; + uint32_t blk0_d3; + uint32_t blk0_d4; + struct { + uint32_t blk0_d5_misc : 28; + uint32_t flash_crypt_config : 4; + } blk0_d5; + struct { + uint32_t coding_scheme : 2; + uint32_t console_debug_dis : 1; + uint32_t dis_sdio_host : 1; + uint32_t abs_done_0 : 1; + uint32_t abs_done_1 : 1; + uint32_t dis_jtag : 1; + uint32_t dis_dl_encrypt : 1; + uint32_t dis_dl_decrypt : 1; + uint32_t dis_dl_cache : 1; + uint32_t key_status : 1; + } blk0_d6; + }; + uint32_t blk0[7]; + }; + uint32_t blk1[8]; + uint32_t blk2[8]; + uint32_t blk3[8]; +} Esp32EfuseRegs; + + +typedef struct Esp32EfuseState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + BlockBackend *blk; + QEMUTimer op_timer; + qemu_irq efuse_update_gpio; + + Esp32EfuseRegs efuse_wr; + Esp32EfuseRegs efuse_wr_dis; + Esp32EfuseRegs efuse_rd; + Esp32EfuseRegs efuse_rd_dis; + + uint32_t clk_reg; + uint32_t conf_reg; + uint32_t status_reg; + uint32_t cmd_reg; + uint32_t int_raw_reg; + uint32_t int_st_reg; + uint32_t int_ena_reg; + uint32_t dac_conf_reg; +} Esp32EfuseState; + +/* returns NULL unless there is exactly one device */ +static inline Esp32EfuseState *esp32_efuse_find(void) +{ + Object *o = object_resolve_path_type("", TYPE_ESP32_EFUSE, NULL); + + return o ? ESP32_EFUSE(o) : NULL; +} From 72d3396f90521bf8d74d4d4333290155f2fe839a Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:35:25 +0200 Subject: [PATCH 13/56] hw/ssi: add ESP32 SPI --- hw/ssi/esp32_spi.c | 365 +++++++++++++++++++++++++++++++++++++ hw/ssi/meson.build | 1 + include/hw/ssi/esp32_spi.h | 94 ++++++++++ 3 files changed, 460 insertions(+) create mode 100644 hw/ssi/esp32_spi.c create mode 100644 include/hw/ssi/esp32_spi.h diff --git a/hw/ssi/esp32_spi.c b/hw/ssi/esp32_spi.c new file mode 100644 index 000000000000..03bef4e1a4f3 --- /dev/null +++ b/hw/ssi/esp32_spi.c @@ -0,0 +1,365 @@ +/* + * ESP32 SPI controller + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "sysemu/sysemu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/ssi/ssi.h" +#include "hw/ssi/esp32_spi.h" +#include "hw/misc/esp32_flash_enc.h" + + + +enum { + CMD_RES = 0xab, + CMD_DP = 0xb9, + CMD_CE = 0x60, + CMD_BE = 0xD8, + CMD_SE = 0x20, + CMD_PP = 0x02, + CMD_WRSR = 0x1, + CMD_RDSR = 0x5, + CMD_RDID = 0x9f, + CMD_WRDI = 0x4, + CMD_WREN = 0x6, + CMD_READ = 0x03, +}; + + +#define ESP32_SPI_REG_SIZE 0x1000 + +static void esp32_spi_do_command(Esp32SpiState* state, uint32_t cmd_reg); + +static uint64_t esp32_spi_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32SpiState *s = ESP32_SPI(opaque); + uint64_t r = 0; + switch (addr) { + case A_SPI_ADDR: + r = s->addr_reg; + break; + case A_SPI_CTRL: + r = s->ctrl_reg; + break; + case A_SPI_STATUS: + r = s->status_reg; + break; + case A_SPI_CTRL1: + r = s->ctrl1_reg; + break; + case A_SPI_CTRL2: + r = s->ctrl2_reg; + break; + case A_SPI_USER: + r = s->user_reg; + break; + case A_SPI_USER1: + r = s->user1_reg; + break; + case A_SPI_USER2: + r = s->user2_reg; + break; + case A_SPI_MOSI_DLEN: + r = s->mosi_dlen_reg; + break; + case A_SPI_MISO_DLEN: + r = s->miso_dlen_reg; + break; + case A_SPI_PIN: + r = s->pin_reg; + break; + case A_SPI_W0 ... A_SPI_W0 + (ESP32_SPI_BUF_WORDS - 1) * sizeof(uint32_t): + r = s->data_reg[(addr - A_SPI_W0) / sizeof(uint32_t)]; + break; + case A_SPI_EXT2: + r = 0; + break; + case A_SPI_SLAVE: + r = BIT(R_SPI_SLAVE_TRANS_DONE_SHIFT) | BIT(R_SPI_SLAVE_TRANS_INTEN_SHIFT); + break; + } + return r; +} + +static void esp32_spi_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32SpiState *s = ESP32_SPI(opaque); + switch (addr) { + case A_SPI_W0 ... A_SPI_W0 + (ESP32_SPI_BUF_WORDS - 1) * sizeof(uint32_t): + s->data_reg[(addr - A_SPI_W0) / sizeof(uint32_t)] = value; + break; + case A_SPI_ADDR: + s->addr_reg = value; + break; + case A_SPI_CTRL: + s->ctrl_reg = value; + break; + case A_SPI_STATUS: + s->status_reg = value; + break; + case A_SPI_CTRL1: + s->ctrl1_reg = value; + break; + case A_SPI_CTRL2: + s->ctrl2_reg = value; + break; + case A_SPI_USER: + s->user_reg = value; + break; + case A_SPI_USER1: + s->user1_reg = value; + break; + case A_SPI_USER2: + s->user2_reg = value; + break; + case A_SPI_MOSI_DLEN: + s->mosi_dlen_reg = value; + break; + case A_SPI_MISO_DLEN: + s->miso_dlen_reg = value; + break; + case A_SPI_PIN: + s->pin_reg = value; + break; + case A_SPI_CMD: + esp32_spi_do_command(s, value); + break; + } +} + +typedef struct Esp32SpiTransaction { + int cmd_bytes; + uint32_t cmd; + int addr_bytes; + uint32_t addr; + int data_tx_bytes; + int data_rx_bytes; + uint32_t* data; +} Esp32SpiTransaction; + +static void esp32_spi_txrx_buffer(Esp32SpiState *s, void *buf, int tx_bytes, int rx_bytes) +{ + int bytes = MAX(tx_bytes, rx_bytes); + uint8_t *c_buf = (uint8_t*) buf; + for (int i = 0; i < bytes; ++i) { + uint8_t byte = 0; + if (byte < tx_bytes) { + memcpy(&byte, c_buf + i, 1); + } + uint32_t res = ssi_transfer(s->spi, byte); + if (byte < rx_bytes) { + memcpy(c_buf + i, &res, 1); + } + } +} + +static void esp32_spi_cs_set(Esp32SpiState *s, int value) +{ + for (int i = 0; i < ESP32_SPI_CS_COUNT; ++i) { + qemu_set_irq(s->cs_gpio[i], ((s->pin_reg & (1 << i)) == 0) ? value : 1); + } +} + +static void esp32_spi_transaction(Esp32SpiState *s, Esp32SpiTransaction *t) +{ + esp32_spi_cs_set(s, 0); + esp32_spi_txrx_buffer(s, &t->cmd, t->cmd_bytes, 0); + esp32_spi_txrx_buffer(s, &t->addr, t->addr_bytes, 0); + esp32_spi_txrx_buffer(s, t->data, t->data_tx_bytes, t->data_rx_bytes); + esp32_spi_cs_set(s, 1); +} + +/* Convert one of the hardware "bitlen" registers to a byte count */ +static inline int bitlen_to_bytes(uint32_t val) +{ + return (val + 1 + 7) / 8; /* bitlen registers hold number of bits, minus one */ +} + +static void maybe_encrypt_data(Esp32SpiState *s) +{ + Esp32FlashEncryptionState* flash_enc = esp32_flash_encryption_find(); + if (esp32_flash_encryption_enabled(flash_enc)) { + esp32_flash_encryption_get_result(flash_enc, &s->data_reg[0], 8); + } +} + +static void esp32_spi_do_command(Esp32SpiState* s, uint32_t cmd_reg) +{ + Esp32SpiTransaction t = { + .cmd_bytes = 1 + }; + switch (cmd_reg) { + case R_SPI_CMD_READ_MASK: + t.cmd = CMD_READ; + t.addr_bytes = bitlen_to_bytes(FIELD_EX32(s->user1_reg, SPI_USER1, ADDR_BITLEN)); + t.addr = bswap32(s->addr_reg) >> (32 - t.addr_bytes * 8); + t.data = &s->data_reg[0]; + t.data_rx_bytes = bitlen_to_bytes(s->miso_dlen_reg); + break; + + case R_SPI_CMD_WREN_MASK: + t.cmd = CMD_WREN; + break; + + case R_SPI_CMD_WRDI_MASK: + t.cmd = CMD_WRDI; + break; + + case R_SPI_CMD_RDID_MASK: + t.cmd = CMD_RDID; + t.data = &s->data_reg[0]; + t.data_rx_bytes = 3; + break; + + case R_SPI_CMD_RDSR_MASK: + t.cmd = CMD_RDSR; + t.data = &s->status_reg; + t.data_rx_bytes = 1; + break; + + case R_SPI_CMD_WRSR_MASK: + t.cmd = CMD_WRSR; + t.data = &s->status_reg; + t.data_tx_bytes = 1; + break; + + case R_SPI_CMD_PP_MASK: + maybe_encrypt_data(s); + t.cmd = CMD_PP; + t.data = &s->data_reg[0]; + t.addr_bytes = bitlen_to_bytes(FIELD_EX32(s->user1_reg, SPI_USER1, ADDR_BITLEN)); + t.addr = bswap32(s->addr_reg) >> 8; + t.data = &s->data_reg[0]; + t.data_tx_bytes = s->addr_reg >> 24; + break; + + case R_SPI_CMD_SE_MASK: + t.cmd = CMD_SE; + t.addr_bytes = bitlen_to_bytes(FIELD_EX32(s->user1_reg, SPI_USER1, ADDR_BITLEN)); + t.addr = bswap32(s->addr_reg) >> (32 - t.addr_bytes * 8); + break; + + case R_SPI_CMD_BE_MASK: + t.cmd = CMD_BE; + t.addr_bytes = bitlen_to_bytes(FIELD_EX32(s->user1_reg, SPI_USER1, ADDR_BITLEN)); + t.addr = bswap32(s->addr_reg) >> (32 - t.addr_bytes * 8); + break; + + case R_SPI_CMD_CE_MASK: + t.cmd = CMD_CE; + break; + + case R_SPI_CMD_DP_MASK: + t.cmd = CMD_DP; + break; + + case R_SPI_CMD_RES_MASK: + t.cmd = CMD_RES; + t.data = &s->data_reg[0]; + t.data_rx_bytes = 3; + break; + + case R_SPI_CMD_USR_MASK: + maybe_encrypt_data(s); + if (FIELD_EX32(s->user_reg, SPI_USER, COMMAND) || FIELD_EX32(s->user2_reg, SPI_USER2, COMMAND_BITLEN)) { + t.cmd = FIELD_EX32(s->user2_reg, SPI_USER2, COMMAND_VALUE); + t.cmd_bytes = bitlen_to_bytes(FIELD_EX32(s->user2_reg, SPI_USER2, COMMAND_BITLEN)); + } else { + t.cmd_bytes = 0; + } + if (FIELD_EX32(s->user_reg, SPI_USER, ADDR)) { + t.addr_bytes = bitlen_to_bytes(FIELD_EX32(s->user1_reg, SPI_USER1, ADDR_BITLEN)); + t.addr = bswap32(s->addr_reg); + } + if (FIELD_EX32(s->user_reg, SPI_USER, MOSI)) { + t.data = &s->data_reg[0]; + t.data_tx_bytes = bitlen_to_bytes(s->mosi_dlen_reg); + } + if (FIELD_EX32(s->user_reg, SPI_USER, MISO)) { + t.data = &s->data_reg[0]; + t.data_rx_bytes = bitlen_to_bytes(s->miso_dlen_reg); + } + break; + default: + return; + } + esp32_spi_transaction(s, &t); +} + + +static const MemoryRegionOps esp32_spi_ops = { + .read = esp32_spi_read, + .write = esp32_spi_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_spi_reset(DeviceState *dev) +{ + Esp32SpiState *s = ESP32_SPI(dev); + s->pin_reg = 0x6; + s->user1_reg = FIELD_DP32(0, SPI_USER1, ADDR_BITLEN, 23); + s->user1_reg = FIELD_DP32(s->user1_reg, SPI_USER1, DUMMY_CYCLELEN, 7); + s->user2_reg = FIELD_DP32(0, SPI_USER2, COMMAND_BITLEN, 4); + s->user2_reg = FIELD_DP32(s->user2_reg, SPI_USER2, COMMAND_VALUE, 0); + s->status_reg = 0; +} + +static void esp32_spi_realize(DeviceState *dev, Error **errp) +{ +} + +static void esp32_spi_init(Object *obj) +{ + Esp32SpiState *s = ESP32_SPI(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_spi_ops, s, + TYPE_ESP32_SPI, ESP32_SPI_REG_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + + s->spi = ssi_create_bus(DEVICE(s), "spi"); + qdev_init_gpio_out_named(DEVICE(s), &s->cs_gpio[0], SSI_GPIO_CS, ESP32_SPI_CS_COUNT); +} + +static Property esp32_spi_properties[] = { + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_spi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_spi_reset; + dc->realize = esp32_spi_realize; + device_class_set_props(dc, esp32_spi_properties); +} + +static const TypeInfo esp32_spi_info = { + .name = TYPE_ESP32_SPI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32SpiState), + .instance_init = esp32_spi_init, + .class_init = esp32_spi_class_init +}; + +static void esp32_spi_register_types(void) +{ + type_register_static(&esp32_spi_info); +} + +type_init(esp32_spi_register_types) diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build index 904a47161a45..ed3dcb26cbd9 100644 --- a/hw/ssi/meson.build +++ b/hw/ssi/meson.build @@ -10,4 +10,5 @@ softmmu_ss.add(when: 'CONFIG_XILINX_SPIPS', if_true: files('xilinx_spips.c')) softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-ospi.c')) softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_spi.c')) softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_spi.c')) +softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_spi.c')) softmmu_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_spi_host.c')) diff --git a/include/hw/ssi/esp32_spi.h b/include/hw/ssi/esp32_spi.h new file mode 100644 index 000000000000..dcf9bc88d2d4 --- /dev/null +++ b/include/hw/ssi/esp32_spi.h @@ -0,0 +1,94 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/ssi/ssi.h" + +#define TYPE_ESP32_SPI "ssi.esp32.spi" +#define ESP32_SPI(obj) OBJECT_CHECK(Esp32SpiState, (obj), TYPE_ESP32_SPI) + +#define ESP32_SPI_CS_COUNT 3 +#define ESP32_SPI_BUF_WORDS 16 + +typedef struct Esp32SpiState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + qemu_irq cs_gpio[ESP32_SPI_CS_COUNT]; + int num_cs; + SSIBus *spi; + + uint32_t addr_reg; + uint32_t ctrl_reg; + uint32_t status_reg; + uint32_t ctrl1_reg; + uint32_t ctrl2_reg; + uint32_t user_reg; + uint32_t user1_reg; + uint32_t user2_reg; + uint32_t mosi_dlen_reg; + uint32_t miso_dlen_reg; + uint32_t pin_reg; + uint32_t data_reg[ESP32_SPI_BUF_WORDS]; +} Esp32SpiState; + + +REG32(SPI_CMD, 0x00) + FIELD(SPI_CMD, READ, 31, 1) + FIELD(SPI_CMD, WREN, 30, 1) + FIELD(SPI_CMD, WRDI, 29, 1) + FIELD(SPI_CMD, RDID, 28, 1) + FIELD(SPI_CMD, RDSR, 27, 1) + FIELD(SPI_CMD, WRSR, 26, 1) + FIELD(SPI_CMD, PP, 25, 1) + FIELD(SPI_CMD, SE, 24, 1) + FIELD(SPI_CMD, BE, 23, 1) + FIELD(SPI_CMD, CE, 22, 1) + FIELD(SPI_CMD, DP, 21, 1) + FIELD(SPI_CMD, RES, 20, 1) + FIELD(SPI_CMD, HPM, 19, 1) + FIELD(SPI_CMD, USR, 18, 1) + FIELD(SPI_CMD, PES, 17, 1) + FIELD(SPI_CMD, PER, 16, 1) + +REG32(SPI_ADDR, 0x04) +REG32(SPI_CTRL, 0x08) +REG32(SPI_STATUS, 0x10) + FIELD(SPI_STATUS, STATUS, 0, 16) + +REG32(SPI_CTRL1, 0x0c) +REG32(SPI_CTRL2, 0x14) +REG32(SPI_USER, 0x1C) + FIELD(SPI_USER, COMMAND, 31, 1) + FIELD(SPI_USER, ADDR, 30, 1) + FIELD(SPI_USER, DUMMY, 29, 1) + FIELD(SPI_USER, MISO, 28, 1) + FIELD(SPI_USER, MOSI, 27, 1) + FIELD(SPI_USER, SIO, 16, 1) + FIELD(SPI_USER, DOUTDIN, 0, 1) + +REG32(SPI_USER1, 0x20) + FIELD(SPI_USER1, ADDR_BITLEN, 26, 6) + FIELD(SPI_USER1, DUMMY_CYCLELEN, 0, 8) + +REG32(SPI_USER2, 0x24) + FIELD(SPI_USER2, COMMAND_BITLEN, 28, 4) + FIELD(SPI_USER2, COMMAND_VALUE, 0, 16) + +REG32(SPI_MOSI_DLEN, 0x28) +REG32(SPI_MISO_DLEN, 0x2c) +REG32(SPI_PIN, 0x34) +REG32(SPI_SLAVE, 0x38) + FIELD(SPI_SLAVE, TRANS_DONE, 4, 1) + FIELD(SPI_SLAVE, TRANS_INTEN, 9, 1) + FIELD(SPI_SLAVE, TRANS_CNT, 22, 4) + FIELD(SPI_SLAVE, SLAVE_MODE, 30, 1) + +REG32(SPI_W0, 0x80) +REG32(SPI_EXT0, 0xF0) +REG32(SPI_EXT1, 0xF4) +REG32(SPI_EXT2, 0xF8) +REG32(SPI_EXT3, 0xFC) + + From f379725be8db0bd879895b7c8579acc853f72fce Mon Sep 17 00:00:00 2001 From: Peter Buchegger Date: Mon, 28 Sep 2020 21:52:55 +0200 Subject: [PATCH 14/56] hw/i2c: add ESP32 I2C --- hw/i2c/esp32_i2c.c | 283 +++++++++++++++++++++++++++++++++++++ hw/i2c/meson.build | 1 + include/hw/i2c/esp32_i2c.h | 109 ++++++++++++++ 3 files changed, 393 insertions(+) create mode 100644 hw/i2c/esp32_i2c.c create mode 100644 include/hw/i2c/esp32_i2c.h diff --git a/hw/i2c/esp32_i2c.c b/hw/i2c/esp32_i2c.c new file mode 100644 index 000000000000..1d36b8ad5704 --- /dev/null +++ b/hw/i2c/esp32_i2c.c @@ -0,0 +1,283 @@ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/i2c/esp32_i2c.h" +#include "hw/irq.h" + +static void esp32_i2c_do_transaction(Esp32I2CState * s); +static void esp32_i2c_update_irq(Esp32I2CState * s); + +static void esp32_i2c_reset(DeviceState * dev) +{ + Esp32I2CState * s = Esp32_I2C(dev); + + fifo8_reset(&s->rx_fifo); + fifo8_reset(&s->tx_fifo); + s->trans_ongoing = false; + s->ctr_reg = 0; + s->timeout_reg = 0; + s->int_ena_reg = 0; + s->int_raw_reg = 0; + s->sda_hold_reg = 0; + s->sda_sample_reg = 0; + s->high_period_reg = 0; + s->low_period_reg = 0; + s->start_hold_reg = 0; + s->rstart_setup_reg = 0; + s->stop_hold_reg = 0; + s->stop_setup_reg = 0; + memset(s->cmd_reg, 0, sizeof(s->cmd_reg)); + + fifo8_reset(&s->tx_fifo); + fifo8_reset(&s->rx_fifo); +} + +static uint32_t esp32_i2c_get_status_reg(Esp32I2CState* s) +{ + uint32_t res = 0; + res = FIELD_DP32(res, I2C_STATUS, BUS_BUSY, s->trans_ongoing); + res = FIELD_DP32(res, I2C_STATUS, RXFIFO_CNT, fifo8_num_used(&s->rx_fifo)); + res = FIELD_DP32(res, I2C_STATUS, TXFIFO_CNT, fifo8_num_used(&s->tx_fifo)); + return res; +} + +static void esp32_i2c_update_irq(Esp32I2CState * s) +{ + int irq_state = !!(s->int_raw_reg & s->int_ena_reg); + qemu_set_irq(s->irq, irq_state); +} + +static uint64_t esp32_i2c_read(void * opaque, hwaddr addr, unsigned int size) +{ + Esp32I2CState * s = Esp32_I2C(opaque); + + switch(addr) { + case A_I2C_CTR: + return s->ctr_reg; + case A_I2C_STATUS: + return esp32_i2c_get_status_reg(s); + case A_I2C_FIFO_DATA: { + if (fifo8_num_used(&s->rx_fifo) == 0) { + error_report("esp32_i2c: read I2C FIFO while it is empty"); + return 0xee; + } + uint8_t res = fifo8_pop(&s->rx_fifo); + return res; + } + case A_I2C_INT_RAW: + return s->int_raw_reg; + case A_I2C_INT_ENA: + return s->int_ena_reg; + case A_I2C_INT_ST: + return s->int_raw_reg & s->int_ena_reg; + case A_I2C_CMD ... (A_I2C_CMD + ESP32_I2C_CMD_COUNT * 4): + return s->cmd_reg[(addr - A_I2C_CMD) / 4]; + case A_I2C_TIMEOUT: + return s->timeout_reg; + case A_I2C_SDA_HOLD: + return s->sda_hold_reg; + case A_I2C_SDA_SAMPLE: + return s->sda_sample_reg; + case A_I2C_HIGH_PERIOD: + return s->high_period_reg; + case A_I2C_LOW_PERIOD: + return s->low_period_reg; + case A_I2C_START_HOLD: + return s->start_hold_reg; + case A_I2C_RSTART_SETUP: + return s->rstart_setup_reg; + case A_I2C_STOP_HOLD: + return s->stop_hold_reg; + case A_I2C_STOP_SETUP: + return s->stop_setup_reg; + default: + return 0; + } +} + +static void esp32_i2c_write(void * opaque, hwaddr addr, uint64_t value, unsigned int size) +{ + Esp32I2CState * s = Esp32_I2C(opaque); + + switch(addr) { + case A_I2C_CTR: + if (FIELD_EX32(value, I2C_CTR, MS_MODE) != 1) { + error_report("esp32_i2c: slave mode not implemented"); + } + if (FIELD_EX32(value, I2C_CTR, TRANS_START)) { + esp32_i2c_do_transaction(s); + value &= ~ R_I2C_CTR_TRANS_START_MASK; + } + s->ctr_reg = value; + break; + case A_I2C_FIFO_CONF: + if (FIELD_EX32(value, I2C_FIFO_CONF, NONFIFO_EN)) { + error_report("esp32_i2c: APB mode not implemented"); + } + if (FIELD_EX32(value, I2C_FIFO_CONF, RX_FIFO_RST)) { + fifo8_reset(&s->rx_fifo); + } + if (FIELD_EX32(value, I2C_FIFO_CONF, TX_FIFO_RST)) { + fifo8_reset(&s->tx_fifo); + } + break; + case A_I2C_FIFO_DATA: + if (fifo8_num_free(&s->tx_fifo) == 0) { + error_report("esp32_i2c: write to I2C TX FIFO while it is full"); + } else { + fifo8_push(&s->tx_fifo, value); + } + break; + case A_I2C_INT_CLR: + s->int_raw_reg &= ~value; + esp32_i2c_update_irq(s); + break; + case A_I2C_INT_ENA: + s->int_ena_reg = value; + esp32_i2c_update_irq(s); + break; + case A_I2C_CMD ... (A_I2C_CMD + ESP32_I2C_CMD_COUNT * 4): + s->cmd_reg[(addr - A_I2C_CMD) / 4] = value; + break; + case A_I2C_TIMEOUT: + s->timeout_reg = value; + break; + case A_I2C_SDA_HOLD: + s->sda_hold_reg = value; + break; + case A_I2C_SDA_SAMPLE: + s->sda_sample_reg = value; + break; + case A_I2C_HIGH_PERIOD: + s->high_period_reg = value; + break; + case A_I2C_LOW_PERIOD: + s->low_period_reg = value; + break; + case A_I2C_START_HOLD: + s->start_hold_reg = value; + break; + case A_I2C_RSTART_SETUP: + s->rstart_setup_reg = value; + break; + case A_I2C_STOP_HOLD: + s->stop_hold_reg = value; + break; + case A_I2C_STOP_SETUP: + s->stop_setup_reg = value; + break; + default: + break; + } +} + +static void esp32_i2c_do_transaction(Esp32I2CState * s) +{ + bool stop_or_end = false; + for (int i_cmd = 0; i_cmd < ESP32_I2C_CMD_COUNT && !stop_or_end; ++i_cmd) { + uint32_t cmd = s->cmd_reg[i_cmd]; + char opcode = FIELD_EX32(cmd, I2C_CMD, OPCODE); + switch (opcode) { + case I2C_OPCODE_RSTART: + i2c_end_transfer(s->bus); + s->trans_ongoing = false; + break; + case I2C_OPCODE_WRITE: { + size_t length = FIELD_EX32(cmd, I2C_CMD, BYTE_NUM); + if (!s->trans_ongoing) { + s->trans_ongoing = true; + uint8_t data = fifo8_pop(&s->tx_fifo); + uint8_t addr = data >> 1; + uint8_t is_read = data & 0x1; + if (i2c_start_transfer(s->bus, addr, is_read) != 0) { + /* NACK */ + if (FIELD_EX32(cmd, I2C_CMD, ACK_CHECK_EN) + && FIELD_EX32(cmd, I2C_CMD, ACK_EXP) == 0) { + s->int_raw_reg = FIELD_DP32(s->int_raw_reg, I2C_INT_RAW, ACK_ERR, 1); + stop_or_end = true; + } + s->trans_ongoing = false; + break; + } + s->int_raw_reg = FIELD_DP32(s->int_raw_reg, I2C_INT_RAW, ACK_ERR, 0); + length -= 1; + } + for (size_t nbytes = 0; nbytes < length; ++nbytes) { + uint8_t data = fifo8_pop(&s->tx_fifo); + i2c_send(s->bus, data); + } + break; + } + case I2C_OPCODE_READ: { + size_t length = FIELD_EX32(cmd, I2C_CMD, BYTE_NUM); + for (size_t nbytes = 0; nbytes < length; ++nbytes) { + if (fifo8_num_free(&s->rx_fifo) == 0) { + error_report("esp32_i2c: RX FIFO overflow"); + } else { + uint8_t data = i2c_recv(s->bus); + fifo8_push(&s->rx_fifo, data); + } + } + break; + } + case I2C_OPCODE_STOP: + i2c_end_transfer(s->bus); + s->trans_ongoing = false; + s->int_raw_reg = FIELD_DP32(s->int_raw_reg, I2C_INT_RAW, TRANS_COMPLETE, 1); + stop_or_end = true; + break; + case I2C_OPCODE_END: + s->int_raw_reg = FIELD_DP32(s->int_raw_reg, I2C_INT_RAW, END_DETECT, 1); + stop_or_end = true; + break; + default: + error_report("esp32_i2c: Invalid command %d opcode %d", i_cmd, opcode); + break; + } + s->cmd_reg[i_cmd] = FIELD_DP32(s->cmd_reg[i_cmd], I2C_CMD, DONE, 1); + } + esp32_i2c_update_irq(s); +} + +static const MemoryRegionOps esp32_i2c_ops = { + .read = esp32_i2c_read, + .write = esp32_i2c_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_i2c_init(Object * obj) +{ + Esp32I2CState *s = Esp32_I2C(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_i2c_ops, s, TYPE_ESP32_I2C, ESP32_I2C_MEM_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + + s->bus = i2c_init_bus(DEVICE(s), "i2c"); + + fifo8_create(&s->tx_fifo, ESP32_I2C_FIFO_LENGTH); + fifo8_create(&s->rx_fifo, ESP32_I2C_FIFO_LENGTH); +} + +static void esp32_i2c_class_init(ObjectClass * klass, void * data) +{ + DeviceClass * dc = DEVICE_CLASS(klass); + dc->reset = esp32_i2c_reset; +} + +static const TypeInfo esp32_i2c_type_info = { + .name = TYPE_ESP32_I2C, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32I2CState), + .instance_init = esp32_i2c_init, + .class_init = esp32_i2c_class_init, +}; + +static void esp32_i2c_register_types(void) +{ + type_register_static(&esp32_i2c_type_info); +} + +type_init(esp32_i2c_register_types) diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build index 3996564c25c6..31b924225657 100644 --- a/hw/i2c/meson.build +++ b/hw/i2c/meson.build @@ -15,6 +15,7 @@ i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c')) i2c_ss.add(when: 'CONFIG_ARM_SBCON_I2C', if_true: files('arm_sbcon_i2c.c')) i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c')) i2c_ss.add(when: 'CONFIG_PPC4XX', if_true: files('ppc4xx_i2c.c')) +i2c_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_i2c.c')) i2c_ss.add(when: 'CONFIG_PCA954X', if_true: files('i2c_mux_pca954x.c')) i2c_ss.add(when: 'CONFIG_PMBUS', if_true: files('pmbus_device.c')) softmmu_ss.add_all(when: 'CONFIG_I2C', if_true: i2c_ss) diff --git a/include/hw/i2c/esp32_i2c.h b/include/hw/i2c/esp32_i2c.h new file mode 100644 index 000000000000..b17dc75c8de4 --- /dev/null +++ b/include/hw/i2c/esp32_i2c.h @@ -0,0 +1,109 @@ +#ifndef ESP32_I2C_H +#define ESP32_I2C_H + +#include "hw/sysbus.h" +#include "qemu/fifo8.h" +#include "hw/i2c/i2c.h" +#include "hw/registerfields.h" + +#define TYPE_ESP32_I2C "esp32.i2c" +#define Esp32_I2C(obj) OBJECT_CHECK(Esp32I2CState, (obj), TYPE_ESP32_I2C) + + +#define ESP32_I2C_MEM_SIZE 0x100 +#define ESP32_I2C_FIFO_LENGTH 32 +#define ESP32_I2C_CMD_COUNT 16 + + +typedef struct Esp32I2CState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + I2CBus *bus; + Fifo8 rx_fifo; + Fifo8 tx_fifo; + bool trans_ongoing; + + uint32_t ctr_reg; + uint32_t timeout_reg; + uint32_t int_ena_reg; + uint32_t int_raw_reg; + uint32_t sda_hold_reg; + uint32_t sda_sample_reg; + uint32_t high_period_reg; + uint32_t low_period_reg; + uint32_t start_hold_reg; + uint32_t rstart_setup_reg; + uint32_t stop_hold_reg; + uint32_t stop_setup_reg; + uint32_t cmd_reg[ESP32_I2C_CMD_COUNT]; +} Esp32I2CState; + + +REG32(I2C_CTR, 0x04); + FIELD(I2C_CTR, MS_MODE, 4, 1); + FIELD(I2C_CTR, TRANS_START, 5, 1); + +REG32(I2C_STATUS, 0x08); + FIELD(I2C_STATUS, BUS_BUSY, 4, 1); + FIELD(I2C_STATUS, RXFIFO_CNT, 8, 6); + FIELD(I2C_STATUS, TXFIFO_CNT, 18, 6); + +REG32(I2C_TIMEOUT, 0x0c); + +REG32(I2C_FIFO_CONF, 0x18); + FIELD(I2C_FIFO_CONF, NONFIFO_EN, 10, 1); + FIELD(I2C_FIFO_CONF, RX_FIFO_RST, 12, 1); + FIELD(I2C_FIFO_CONF, TX_FIFO_RST, 13, 1); + +REG32(I2C_FIFO_DATA, 0x1c); + +REG32(I2C_INT_RAW, 0x20); + FIELD(I2C_INT_RAW, ACK_ERR, 10, 1); + FIELD(I2C_INT_RAW, TRANS_COMPLETE, 7, 1); + FIELD(I2C_INT_RAW, END_DETECT, 3, 1); + +REG32(I2C_INT_CLR, 0x24); + FIELD(I2C_INT_CLR, ACK_ERR, 10, 1); + FIELD(I2C_INT_CLR, TRANS_COMPLETE, 7, 1); + FIELD(I2C_INT_CLR, END_DETECT, 3, 1); + +REG32(I2C_INT_ENA, 0x28); + FIELD(I2C_INT_ENA, ACK_ERR, 10, 1); + FIELD(I2C_INT_ENA, TRANS_COMPLETE, 7, 1); + FIELD(I2C_INT_ENA, END_DETECT, 3, 1); + +REG32(I2C_INT_ST, 0x2c); + FIELD(I2C_INT_ST, ACK_ERR, 10, 1); + FIELD(I2C_INT_ST, TRANS_COMPLETE, 7, 1); + FIELD(I2C_INT_ST, END_DETECT, 3, 1); + +REG32(I2C_SDA_HOLD, 0x30); +REG32(I2C_SDA_SAMPLE, 0x34); +REG32(I2C_HIGH_PERIOD, 0x38); +REG32(I2C_LOW_PERIOD, 0x00); // 0x00 is not a typo +REG32(I2C_START_HOLD, 0x40); +REG32(I2C_RSTART_SETUP, 0x44); +REG32(I2C_STOP_HOLD, 0x48); +REG32(I2C_STOP_SETUP, 0x4c); + +REG32(I2C_CMD, 0x58); + FIELD(I2C_CMD, BYTE_NUM, 0, 8); + FIELD(I2C_CMD, ACK_CHECK_EN, 8, 1); + FIELD(I2C_CMD, ACK_EXP, 9, 1); + FIELD(I2C_CMD, ACK_VAL, 10, 1); + FIELD(I2C_CMD, OPCODE, 11, 3); + FIELD(I2C_CMD, DONE, 31, 1); +/* 15 more command registers omitted */ + +/* I2C_CMD.OPCODE values */ +typedef enum { + I2C_OPCODE_RSTART = 0, + I2C_OPCODE_WRITE = 1, + I2C_OPCODE_READ = 2, + I2C_OPCODE_STOP = 3, + I2C_OPCODE_END = 4, +} i2c_opcode_t; + +#endif /* ESP32_I2C_H */ From 9377b12bd9d927db4daae8388335509a899ce897 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:37:31 +0200 Subject: [PATCH 15/56] hw/misc: add ESP32 DPORT peripheral, cache, cross-core interrupt --- hw/misc/esp32_crosscore_int.c | 91 +++++ hw/misc/esp32_dport.c | 475 ++++++++++++++++++++++++++ hw/misc/meson.build | 4 + include/hw/misc/esp32_crosscore_int.h | 17 + include/hw/misc/esp32_dport.h | 178 ++++++++++ 5 files changed, 765 insertions(+) create mode 100644 hw/misc/esp32_crosscore_int.c create mode 100644 hw/misc/esp32_dport.c create mode 100644 include/hw/misc/esp32_crosscore_int.h create mode 100644 include/hw/misc/esp32_dport.h diff --git a/hw/misc/esp32_crosscore_int.c b/hw/misc/esp32_crosscore_int.c new file mode 100644 index 000000000000..9b2c4fc55f83 --- /dev/null +++ b/hw/misc/esp32_crosscore_int.c @@ -0,0 +1,91 @@ +/* + * ESP32 Cross-core interrupt + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "hw/misc/esp32_reg.h" +#include "hw/misc/esp32_crosscore_int.h" + + +static uint64_t esp32_crosscore_int_read(void *opaque, hwaddr addr, unsigned int size) +{ + return 0; +} + +static void esp32_crosscore_int_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32CrosscoreInt *s = ESP32_CROSSCORE_INT(opaque); + int index = addr / 4; + assert(index < s->n_irqs); + qemu_set_irq(s->irqs[index], value & 0x1); +} + +static const MemoryRegionOps esp32_crosscore_int_ops = { + .read = esp32_crosscore_int_read, + .write = esp32_crosscore_int_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_crosscore_int_realize(DeviceState *dev, Error **errp) +{ + Esp32CrosscoreInt *s = ESP32_CROSSCORE_INT(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + s->irqs = g_malloc0_n(s->n_irqs, sizeof(qemu_irq)); + assert(s->irqs); + for (int i = 0; i < s->n_irqs; ++i) { + sysbus_init_irq(sbd, &s->irqs[i]); + } + + memory_region_init_io(&s->iomem, OBJECT(dev), &esp32_crosscore_int_ops, s, + TYPE_ESP32_CROSSCORE_INT, + s->n_irqs * sizeof(uint32_t)); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void esp32_crosscore_int_init(Object *obj) +{ + +} + +static Property esp32_crosscore_int_properties[] = { + DEFINE_PROP_INT32("n_irqs", Esp32CrosscoreInt, n_irqs, 4), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_crosscore_int_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = esp32_crosscore_int_realize; + device_class_set_props(dc, esp32_crosscore_int_properties); +} + +static const TypeInfo esp32_crosscore_int_info = { + .name = TYPE_ESP32_CROSSCORE_INT, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32CrosscoreInt), + .instance_init = esp32_crosscore_int_init, + .class_init = esp32_crosscore_int_class_init +}; + +static void esp32_crosscore_int_register_types(void) +{ + type_register_static(&esp32_crosscore_int_info); +} + +type_init(esp32_crosscore_int_register_types) diff --git a/hw/misc/esp32_dport.c b/hw/misc/esp32_dport.c new file mode 100644 index 000000000000..d73b6281a230 --- /dev/null +++ b/hw/misc/esp32_dport.c @@ -0,0 +1,475 @@ +/* + * ESP32 "DPORT" device + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/registerfields.h" +#include "hw/boards.h" +#include "hw/misc/esp32_reg.h" +#include "hw/misc/esp32_dport.h" + +#include "hw/misc/esp32_flash_enc.h" +#include "hw/nvram/esp32_efuse.h" + + +#define ESP32_DPORT_SIZE (DR_REG_DPORT_APB_BASE - DR_REG_DPORT_BASE) + +#define MMU_RANGE_SIZE (ESP32_CACHE_PAGES_PER_REGION * sizeof(uint32_t)) +#define MMU_RANGE_LAST (MMU_RANGE_SIZE - sizeof(uint32_t)) + +#define PRO_DROM0_MMU_FIRST (DR_REG_FLASH_MMU_TABLE_PRO - DR_REG_DPORT_BASE) +#define PRO_DROM0_MMU_LAST (PRO_DROM0_MMU_FIRST + MMU_RANGE_LAST) +#define PRO_IRAM0_MMU_FIRST (DR_REG_FLASH_MMU_TABLE_PRO - DR_REG_DPORT_BASE + MMU_RANGE_SIZE) +#define PRO_IRAM0_MMU_LAST (PRO_IRAM0_MMU_FIRST + MMU_RANGE_LAST) +#define APP_DROM0_MMU_FIRST (DR_REG_FLASH_MMU_TABLE_APP - DR_REG_DPORT_BASE) +#define APP_DROM0_MMU_LAST (APP_DROM0_MMU_FIRST + MMU_RANGE_LAST) +#define APP_IRAM0_MMU_FIRST (DR_REG_FLASH_MMU_TABLE_APP - DR_REG_DPORT_BASE + MMU_RANGE_SIZE) +#define APP_IRAM0_MMU_LAST (APP_IRAM0_MMU_FIRST + MMU_RANGE_LAST) +#define MMU_ENTRY_MASK 0x1ff + +static void esp32_cache_state_update(Esp32CacheState* cs); +static void esp32_cache_data_sync(Esp32CacheRegionState* crs); +static void esp32_cache_invalidate_all_entries(Esp32CacheRegionState* crs); + +static inline uint32_t get_mmu_entry(Esp32CacheRegionState* crs, hwaddr base, hwaddr addr) +{ + return crs->mmu_table[(addr - base)/sizeof(uint32_t)] & MMU_ENTRY_MASK; +} + +static inline void set_mmu_entry(Esp32CacheRegionState* crs, hwaddr base, hwaddr addr, uint64_t val) +{ + uint32_t old_val = crs->mmu_table[(addr - base)/sizeof(uint32_t)]; + if (val != old_val) { + crs->mmu_table[(addr - base)/sizeof(uint32_t)] = (val & MMU_ENTRY_MASK) | ESP32_CACHE_MMU_ENTRY_CHANGED; + } +} + +static uint64_t esp32_dport_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32DportState *s = ESP32_DPORT(opaque); + uint64_t r = 0; + switch (addr) { + case A_DPORT_APPCPU_RESET: + r = s->appcpu_reset_state; + break; + case A_DPORT_APPCPU_CLK: + r = s->appcpu_clkgate_state; + break; + case A_DPORT_APPCPU_RUNSTALL: + r = s->appcpu_stall_state; + break; + case A_DPORT_APPCPU_BOOT_ADDR: + r = s->appcpu_boot_addr; + break; + case A_DPORT_CPU_PER_CONF: + r = s->cpuperiod_sel; + break; + case A_DPORT_PRO_CACHE_CTRL: + r = s->cache_state[0].cache_ctrl_reg; + break; + case A_DPORT_PRO_CACHE_CTRL1: + r = s->cache_state[0].cache_ctrl1_reg; + break; + case A_DPORT_APP_CACHE_CTRL: + r = s->cache_state[1].cache_ctrl_reg; + break; + case A_DPORT_APP_CACHE_CTRL1: + r = s->cache_state[1].cache_ctrl1_reg; + break; + case A_DPORT_PRO_DCACHE_DBUG0: + case A_DPORT_APP_DCACHE_DBUG0: + /* in idle state */ + r = FIELD_DP32(0, DPORT_PRO_DCACHE_DBUG0, CACHE_STATE, 1); + break; + case A_DPORT_CACHE_IA_INT_EN: + r = s->cache_ill_trap_en_reg; + break; + case A_DPORT_PRO_DCACHE_DBUG3: + r = 0; + r = FIELD_DP32(r, DPORT_PRO_DCACHE_DBUG3, IA_INT_DROM0, s->cache_state[0].drom0.illegal_access_status); + r = FIELD_DP32(r, DPORT_PRO_DCACHE_DBUG3, IA_INT_IRAM0, s->cache_state[0].iram0.illegal_access_status); + break; + case A_DPORT_APP_DCACHE_DBUG3: + r = 0; + r = FIELD_DP32(r, DPORT_APP_DCACHE_DBUG3, IA_INT_DROM0, s->cache_state[1].drom0.illegal_access_status); + r = FIELD_DP32(r, DPORT_APP_DCACHE_DBUG3, IA_INT_IRAM0, s->cache_state[1].iram0.illegal_access_status); + break; + case PRO_DROM0_MMU_FIRST ... PRO_DROM0_MMU_LAST: + r = get_mmu_entry(&s->cache_state[0].drom0, PRO_DROM0_MMU_FIRST, addr); + break; + case PRO_IRAM0_MMU_FIRST ... PRO_IRAM0_MMU_LAST: + r = get_mmu_entry(&s->cache_state[0].iram0, PRO_IRAM0_MMU_FIRST, addr); + break; + case APP_DROM0_MMU_FIRST ... APP_DROM0_MMU_LAST: + r = get_mmu_entry(&s->cache_state[1].drom0, APP_DROM0_MMU_FIRST, addr); + break; + case APP_IRAM0_MMU_FIRST ... APP_IRAM0_MMU_LAST: + r = get_mmu_entry(&s->cache_state[1].iram0, APP_IRAM0_MMU_FIRST, addr); + break; + case A_DPORT_SLAVE_SPI_CONFIG: + r = s->slave_spi_config_reg; + break; + } + + return r; +} + +static void esp32_dport_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32DportState *s = ESP32_DPORT(opaque); + bool old_state; + uint32_t old_val; + switch (addr) { + case A_DPORT_APPCPU_RESET: + old_state = s->appcpu_reset_state; + s->appcpu_reset_state = value & 1; + if (old_state && !s->appcpu_reset_state) { + qemu_irq_pulse(s->appcpu_reset_req); + } + break; + case A_DPORT_APPCPU_CLK: + s->appcpu_clkgate_state = value & 1; + qemu_set_irq(s->appcpu_stall_req, s->appcpu_stall_state || !s->appcpu_clkgate_state); + break; + case A_DPORT_APPCPU_RUNSTALL: + s->appcpu_stall_state = value & 1; + qemu_set_irq(s->appcpu_stall_req, s->appcpu_stall_state || !s->appcpu_clkgate_state); + break; + case A_DPORT_APPCPU_BOOT_ADDR: + s->appcpu_boot_addr = value; + break; + case A_DPORT_CPU_PER_CONF: + s->cpuperiod_sel = value & R_DPORT_CPU_PER_CONF_CPUPERIOD_SEL_MASK; + qemu_irq_pulse(s->clk_update_req); + break; + case A_DPORT_PRO_CACHE_CTRL: + if (FIELD_EX32(value, DPORT_PRO_CACHE_CTRL, CACHE_FLUSH_ENA)) { + value |= R_DPORT_PRO_CACHE_CTRL_CACHE_FLUSH_DONE_MASK; + value &= ~R_DPORT_PRO_CACHE_CTRL_CACHE_FLUSH_ENA_MASK; + esp32_cache_invalidate_all_entries(&s->cache_state[0].drom0); + esp32_cache_data_sync(&s->cache_state[0].drom0); + esp32_cache_invalidate_all_entries(&s->cache_state[0].iram0); + esp32_cache_data_sync(&s->cache_state[0].iram0); + } + old_val = s->cache_state[0].cache_ctrl_reg; + s->cache_state[0].cache_ctrl_reg = value; + if (value != old_val) { + esp32_cache_state_update(&s->cache_state[0]); + } + break; + case A_DPORT_PRO_CACHE_CTRL1: + old_val = s->cache_state[0].cache_ctrl1_reg; + s->cache_state[0].cache_ctrl1_reg = value; + if (value != old_val) { + esp32_cache_state_update(&s->cache_state[0]); + } + break; + case A_DPORT_APP_CACHE_CTRL: + if (FIELD_EX32(value, DPORT_APP_CACHE_CTRL, CACHE_FLUSH_ENA)) { + value |= R_DPORT_APP_CACHE_CTRL_CACHE_FLUSH_DONE_MASK; + value &= ~R_DPORT_APP_CACHE_CTRL_CACHE_FLUSH_ENA_MASK; + esp32_cache_invalidate_all_entries(&s->cache_state[1].drom0); + esp32_cache_data_sync(&s->cache_state[1].drom0); + esp32_cache_invalidate_all_entries(&s->cache_state[1].iram0); + esp32_cache_data_sync(&s->cache_state[1].iram0); + } + old_val = s->cache_state[1].cache_ctrl_reg; + s->cache_state[1].cache_ctrl_reg = value; + if (value != old_val) { + esp32_cache_state_update(&s->cache_state[1]); + } + break; + case A_DPORT_APP_CACHE_CTRL1: + old_val = s->cache_state[1].cache_ctrl1_reg; + s->cache_state[1].cache_ctrl1_reg = value; + if (value != old_val) { + esp32_cache_state_update(&s->cache_state[1]); + } + break; + case A_DPORT_CACHE_IA_INT_EN: + s->cache_ill_trap_en_reg = value; + s->cache_state[0].drom0.illegal_access_trap_en = (FIELD_EX32(value, DPORT_CACHE_IA_INT_EN, IA_INT_PRO_DROM0)); + s->cache_state[0].iram0.illegal_access_trap_en = (FIELD_EX32(value, DPORT_CACHE_IA_INT_EN, IA_INT_PRO_IRAM0)); + s->cache_state[1].drom0.illegal_access_trap_en = (FIELD_EX32(value, DPORT_CACHE_IA_INT_EN, IA_INT_APP_DROM0)); + s->cache_state[1].iram0.illegal_access_trap_en = (FIELD_EX32(value, DPORT_CACHE_IA_INT_EN, IA_INT_APP_IRAM0)); + s->cache_state[0].dram1.illegal_access_trap_en = (FIELD_EX32(value, DPORT_CACHE_IA_INT_EN, IA_INT_PRO_DRAM1)); + s->cache_state[1].dram1.illegal_access_trap_en = (FIELD_EX32(value, DPORT_CACHE_IA_INT_EN, IA_INT_APP_DRAM1)); + break; + case PRO_DROM0_MMU_FIRST ... PRO_DROM0_MMU_LAST: + set_mmu_entry(&s->cache_state[0].drom0, PRO_DROM0_MMU_FIRST, addr, value); + break; + case PRO_IRAM0_MMU_FIRST ... PRO_IRAM0_MMU_LAST: + set_mmu_entry(&s->cache_state[0].iram0, PRO_IRAM0_MMU_FIRST, addr, value); + break; + case APP_DROM0_MMU_FIRST ... APP_DROM0_MMU_LAST: + set_mmu_entry(&s->cache_state[1].drom0, APP_DROM0_MMU_FIRST, addr, value); + break; + case APP_IRAM0_MMU_FIRST ... APP_IRAM0_MMU_LAST: + set_mmu_entry(&s->cache_state[1].iram0, APP_IRAM0_MMU_FIRST, addr, value); + break; + case A_DPORT_SLAVE_SPI_CONFIG: + s->slave_spi_config_reg = value; + qemu_set_irq(s->flash_enc_en_gpio, FIELD_EX32(value, DPORT_SLAVE_SPI_CONFIG, SLAVE_SPI_ENCRYPT_ENABLE)); + qemu_set_irq(s->flash_dec_en_gpio, FIELD_EX32(value, DPORT_SLAVE_SPI_CONFIG, SLAVE_SPI_DECRYPT_ENABLE)); + break; + } +} + +static const MemoryRegionOps esp32_dport_ops = { + .read = esp32_dport_read, + .write = esp32_dport_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_cache_data_sync(Esp32CacheRegionState* crs) +{ + if (crs->cache->dport->flash_blk == NULL) { + return; + } + + Esp32FlashEncryptionState * flash_enc = esp32_flash_encryption_find(); + bool decrypt = (flash_enc != NULL && esp32_flash_decryption_enabled(flash_enc)); + + uint8_t* cache_data = (uint8_t*) memory_region_get_ram_ptr(&crs->mem); + int n = 0; + for (int i = 0; i < ESP32_CACHE_PAGES_PER_REGION; ++i) { + uint32_t* cache_page = (uint32_t*) (cache_data + i * ESP32_CACHE_PAGE_SIZE); + uint32_t mmu_entry = crs->mmu_table[i]; + if (!(mmu_entry & ESP32_CACHE_MMU_ENTRY_CHANGED)) { + continue; + } + mmu_entry &= MMU_ENTRY_MASK; + if (mmu_entry & ESP32_CACHE_MMU_INVALID_VAL) { + uint32_t fill_val = crs->illegal_access_retval; + for (int word = 0; word < ESP32_CACHE_PAGE_SIZE / sizeof(uint32_t); ++word) { + cache_page[word] = fill_val; + } + } else { + uint32_t phys_addr = mmu_entry * ESP32_CACHE_PAGE_SIZE; + blk_pread(crs->cache->dport->flash_blk, phys_addr, ESP32_CACHE_PAGE_SIZE, cache_page, 0); + if (decrypt) { + esp32_flash_decrypt_inplace(flash_enc, phys_addr, cache_page, ESP32_CACHE_PAGE_SIZE/4); + } + } + crs->mmu_table[i] &= ~ESP32_CACHE_MMU_ENTRY_CHANGED; + n++; + } + memory_region_flush_rom_device(&crs->mem, 0, ESP32_CACHE_REGION_SIZE); +} + +static void esp32_cache_invalidate_all_entries(Esp32CacheRegionState* crs) +{ + for (int i = 0; i < ESP32_CACHE_PAGES_PER_REGION; ++i) { + crs->mmu_table[i] |= ESP32_CACHE_MMU_ENTRY_CHANGED; + } +} + +static void esp32_cache_state_update(Esp32CacheState* cs) +{ + bool cache_enabled = FIELD_EX32(cs->cache_ctrl_reg, DPORT_PRO_CACHE_CTRL, CACHE_ENA) != 0; + + bool drom0_enabled = cache_enabled && + FIELD_EX32(cs->cache_ctrl1_reg, DPORT_PRO_CACHE_CTRL1, MASK_DROM0) == 0; + if (!cs->drom0.mem.enabled && drom0_enabled) { + esp32_cache_data_sync(&cs->drom0); + } + memory_region_set_enabled(&cs->drom0.mem, drom0_enabled); + + bool iram0_enabled = cache_enabled && + FIELD_EX32(cs->cache_ctrl1_reg, DPORT_PRO_CACHE_CTRL1, MASK_IRAM0) == 0; + if (!cs->iram0.mem.enabled && iram0_enabled) { + esp32_cache_data_sync(&cs->iram0); + } + memory_region_set_enabled(&cs->iram0.mem, iram0_enabled); + + if (cs->dport->has_psram) { + bool dram1_enabled = cache_enabled && + FIELD_EX32(cs->cache_ctrl1_reg, DPORT_PRO_CACHE_CTRL1, MASK_DRAM1) == 0; + memory_region_set_enabled(&cs->dram1.mem, dram1_enabled); + } +} + +static void esp32_cache_region_reset(Esp32CacheRegionState *crs) +{ + for (int i = 0; i < ESP32_CACHE_PAGES_PER_REGION; ++i) { + crs->mmu_table[i] = ESP32_CACHE_MMU_ENTRY_CHANGED; + } + crs->illegal_access_trap_en = false; +} + +static void esp32_cache_reset(Esp32CacheState *cs) +{ + esp32_cache_region_reset(&cs->drom0); + esp32_cache_region_reset(&cs->iram0); +} + +static uint64_t esp32_cache_ill_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32CacheRegionState *crs = (Esp32CacheRegionState*) opaque; + uint32_t ill_data[] = { crs->illegal_access_retval, crs->illegal_access_retval }; + uint32_t result; + memcpy(&result, ((uint8_t*) ill_data) + (addr % 4), size); + if (crs->illegal_access_trap_en) { + crs->illegal_access_status = true; + qemu_irq_raise(crs->cache->dport->cache_ill_irq); + } + return result; +} + +static void esp32_cache_ill_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ +} + +static bool esp32_cache_ill_accepts(void *opaque, hwaddr addr, + unsigned size, bool is_write, + MemTxAttrs attrs) +{ + return !is_write; +} + + +void esp32_dport_clear_ill_trap_state(Esp32DportState* s) +{ + s->cache_state[0].drom0.illegal_access_status = false; + s->cache_state[1].drom0.illegal_access_status = false; + s->cache_state[0].iram0.illegal_access_status = false; + s->cache_state[1].iram0.illegal_access_status = false; + s->cache_state[0].dram1.illegal_access_status = false; + s->cache_state[1].dram1.illegal_access_status = false; + qemu_irq_lower(s->cache_ill_irq); +} + +static const MemoryRegionOps esp32_cache_ops = { + .write = NULL, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid.accepts = esp32_cache_ill_accepts, +}; + + +static const MemoryRegionOps esp32_cache_ill_trap_ops = { + .read = esp32_cache_ill_read, + .write = esp32_cache_ill_write, +}; + +static void esp32_dport_reset(DeviceState *dev) +{ + Esp32DportState *s = ESP32_DPORT(dev); + + s->appcpu_boot_addr = 0; + s->appcpu_clkgate_state = false; + s->appcpu_reset_state = true; + s->appcpu_stall_state = false; + s->cache_ill_trap_en_reg = 0; + esp32_cache_reset(&s->cache_state[0]); + esp32_cache_reset(&s->cache_state[1]); + qemu_irq_lower(s->appcpu_stall_req); +} + +static void esp32_dport_realize(DeviceState *dev, Error **errp) +{ + Esp32DportState *s = ESP32_DPORT(dev); + MachineState *ms = MACHINE(qdev_get_machine()); + + s->cpu_count = ms->smp.cpus; +} + +static void esp32_cache_init_region(Esp32CacheState *cs, + Esp32CacheRegionState *crs, + Esp32CacheRegionType type, + const char* name, hwaddr base, + uint32_t illegal_access_retval) +{ + char desc[16]; + crs->cache = cs; + crs->type = type; + crs->base = base; + crs->illegal_access_retval = illegal_access_retval; + snprintf(desc, sizeof(desc), "cpu%d-%s", cs->core_id, name); + if (type == ESP32_DCACHE_PSRAM) { + memory_region_init_ram(&crs->mem, OBJECT(cs->dport), desc, + ESP32_CACHE_REGION_SIZE, &error_abort); + } else { + memory_region_init_rom_device(&crs->mem, OBJECT(cs->dport), + &esp32_cache_ops, crs, + desc, ESP32_CACHE_REGION_SIZE, &error_abort); + } + + snprintf(desc, sizeof(desc), "cpu%d-%s-ill", cs->core_id, name); + memory_region_init_io(&crs->illegal_access_trap_mem, OBJECT(cs->dport), + &esp32_cache_ill_trap_ops, crs, + desc, ESP32_CACHE_REGION_SIZE); +} + +static void esp32_dport_init(Object *obj) +{ + Esp32DportState *s = ESP32_DPORT(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_dport_ops, s, + TYPE_ESP32_DPORT, ESP32_DPORT_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + Esp32CacheState* cs = &s->cache_state[i]; + cs->core_id = i; + cs->dport = s; + esp32_cache_init_region(cs, &cs->drom0, ESP32_DCACHE_FLASH, "drom0", + 0x3F400000, 0xbaadbaad); + esp32_cache_init_region(cs, &cs->iram0, ESP32_ICACHE_FLASH, "iram0", + 0x40000000, 0x00000000); + esp32_cache_init_region(cs, &cs->dram1, ESP32_DCACHE_PSRAM, "dram1", + 0x3F800000, 0xbaadbaad); + } + + qdev_init_gpio_out_named(DEVICE(sbd), &s->appcpu_stall_req, ESP32_DPORT_APPCPU_STALL_GPIO, 1); + qdev_init_gpio_out_named(DEVICE(sbd), &s->appcpu_reset_req, ESP32_DPORT_APPCPU_RESET_GPIO, 1); + qdev_init_gpio_out_named(DEVICE(sbd), &s->clk_update_req, ESP32_DPORT_CLK_UPDATE_GPIO, 1); + qdev_init_gpio_out_named(DEVICE(sbd), &s->cache_ill_irq, ESP32_DPORT_CACHE_ILL_IRQ_GPIO, 1); + qdev_init_gpio_out_named(DEVICE(sbd), &s->flash_enc_en_gpio, ESP32_DPORT_FLASH_ENC_EN_GPIO, 1); + qdev_init_gpio_out_named(DEVICE(sbd), &s->flash_dec_en_gpio, ESP32_DPORT_FLASH_DEC_EN_GPIO, 1); +} + +static Property esp32_dport_properties[] = { + DEFINE_PROP_DRIVE("flash", Esp32DportState, flash_blk), + DEFINE_PROP_BOOL("has_psram", Esp32DportState, has_psram, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_dport_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_dport_reset; + dc->realize = esp32_dport_realize; + device_class_set_props(dc, esp32_dport_properties); +} + +static const TypeInfo esp32_dport_info = { + .name = TYPE_ESP32_DPORT, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32DportState), + .instance_init = esp32_dport_init, + .class_init = esp32_dport_class_init +}; + +static void esp32_dport_register_types(void) +{ + type_register_static(&esp32_dport_info); +} + +type_init(esp32_dport_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index a40245ad44f2..662cd4250d91 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -125,6 +125,10 @@ softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-sysreg.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c')) +softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( + 'esp32_crosscore_int.c', + 'esp32_dport.c', +)) softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_ahb_apb_pnp.c')) diff --git a/include/hw/misc/esp32_crosscore_int.h b/include/hw/misc/esp32_crosscore_int.h new file mode 100644 index 000000000000..35c8739dda71 --- /dev/null +++ b/include/hw/misc/esp32_crosscore_int.h @@ -0,0 +1,17 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "sysemu/block-backend.h" + + +#define TYPE_ESP32_CROSSCORE_INT "misc.esp32.crosscoreint" +#define ESP32_CROSSCORE_INT(obj) OBJECT_CHECK(Esp32CrosscoreInt, (obj), TYPE_ESP32_CROSSCORE_INT) + +typedef struct Esp32CrosscoreInt { + SysBusDevice parent_obj; + MemoryRegion iomem; + int n_irqs; + qemu_irq *irqs; +} Esp32CrosscoreInt; diff --git a/include/hw/misc/esp32_dport.h b/include/hw/misc/esp32_dport.h new file mode 100644 index 000000000000..988c6ab36891 --- /dev/null +++ b/include/hw/misc/esp32_dport.h @@ -0,0 +1,178 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_reg.h" +#include "sysemu/block-backend.h" +#include "hw/misc/esp32_flash_enc.h" + +typedef struct Esp32DportState Esp32DportState; +typedef struct Esp32CacheState Esp32CacheState; + +#define TYPE_ESP32_DPORT "misc.esp32.dport" +#define ESP32_DPORT(obj) OBJECT_CHECK(Esp32DportState, (obj), TYPE_ESP32_DPORT) + +#define ESP32_CACHE_PAGE_SIZE 0x10000 +#define ESP32_CACHE_PAGES_PER_REGION 64 +#define ESP32_CACHE_REGION_SIZE (ESP32_CACHE_PAGE_SIZE * ESP32_CACHE_PAGES_PER_REGION) +#define ESP32_CACHE_MMU_INVALID_VAL 0x100 +#define ESP32_CACHE_MMU_ENTRY_CHANGED 0x200 /* not a hardware flag; used here to check if the page data needs to be updated */ +#define ESP32_CACHE_MAX_PHYS_PAGES 0x100 + +typedef enum Esp32CacheRegionType { + ESP32_DCACHE_FLASH, + ESP32_ICACHE_FLASH, + ESP32_DCACHE_PSRAM, +} Esp32CacheRegionType; + +typedef struct Esp32CacheRegionState { + Esp32CacheState* cache; + MemoryRegion mem; + MemoryRegion illegal_access_trap_mem; + Esp32CacheRegionType type; + hwaddr base; + uint32_t illegal_access_retval; + bool illegal_access_trap_en; + bool illegal_access_status; + uint16_t mmu_table[ESP32_CACHE_PAGES_PER_REGION]; +} Esp32CacheRegionState; + +typedef struct Esp32CacheState { + Esp32DportState* dport; + int core_id; + + uint32_t cache_ctrl_reg; + uint32_t cache_ctrl1_reg; + /* Using only the first 4MB range. + * TODO: add memory regions for other ports: iram1, irom0 + */ + Esp32CacheRegionState iram0; + Esp32CacheRegionState drom0; + Esp32CacheRegionState dram1; /* PSRAM */ +} Esp32CacheState; + +typedef struct Esp32DportState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + bool has_psram; + int cpu_count; + Esp32CacheState cache_state[ESP32_CPU_COUNT]; + BlockBackend *flash_blk; + qemu_irq appcpu_stall_req; + qemu_irq appcpu_reset_req; + qemu_irq clk_update_req; + qemu_irq cache_ill_irq; + qemu_irq flash_enc_en_gpio; + qemu_irq flash_dec_en_gpio; + + bool appcpu_reset_state; + bool appcpu_stall_state; + bool appcpu_clkgate_state; + uint32_t appcpu_boot_addr; + uint32_t cpuperiod_sel; + uint32_t cache_ill_trap_en_reg; + uint32_t slave_spi_config_reg; + +} Esp32DportState; + +void esp32_dport_clear_ill_trap_state(Esp32DportState* s); + +#define ESP32_DPORT_APPCPU_STALL_GPIO "appcpu-stall" +#define ESP32_DPORT_APPCPU_RESET_GPIO "appcpu-reset" +#define ESP32_DPORT_CLK_UPDATE_GPIO "clk-update" +#define ESP32_DPORT_CACHE_ILL_IRQ_GPIO "cache-ill-irq" +#define ESP32_DPORT_FLASH_ENC_EN_GPIO "flash-enc-en" +#define ESP32_DPORT_FLASH_DEC_EN_GPIO "flash-dec-en" + + +REG32(DPORT_APPCPU_RESET, 0x2c) +REG32(DPORT_APPCPU_CLK, 0x30) +REG32(DPORT_APPCPU_RUNSTALL, 0x34) +REG32(DPORT_APPCPU_BOOT_ADDR, 0x38) + +REG32(DPORT_CPU_PER_CONF, 0x3c) + FIELD(DPORT_CPU_PER_CONF, CPUPERIOD_SEL, 0, 2) + +REG32(DPORT_PRO_CACHE_CTRL, 0x40) + FIELD(DPORT_PRO_CACHE_CTRL, CACHE_FLUSH_DONE, 5, 1) + FIELD(DPORT_PRO_CACHE_CTRL, CACHE_FLUSH_ENA, 4, 1) + FIELD(DPORT_PRO_CACHE_CTRL, CACHE_ENA, 3, 1) + +REG32(DPORT_PRO_CACHE_CTRL1, 0x44) + FIELD(DPORT_PRO_CACHE_CTRL1, MMU_IA_CLR, 13, 1) + FIELD(DPORT_PRO_CACHE_CTRL1, MASK_OPSDRAM, 5, 1) + FIELD(DPORT_PRO_CACHE_CTRL1, MASK_DROM0, 4, 1) + FIELD(DPORT_PRO_CACHE_CTRL1, MASK_DRAM1, 3, 1) + FIELD(DPORT_PRO_CACHE_CTRL1, MASK_IROM0, 2, 1) + FIELD(DPORT_PRO_CACHE_CTRL1, MASK_IRAM1, 1, 1) + FIELD(DPORT_PRO_CACHE_CTRL1, MASK_IRAM0, 0, 1) + +REG32(DPORT_APP_CACHE_CTRL, 0x58) + FIELD(DPORT_APP_CACHE_CTRL, CACHE_FLUSH_DONE, 5, 1) + FIELD(DPORT_APP_CACHE_CTRL, CACHE_FLUSH_ENA, 4, 1) + FIELD(DPORT_APP_CACHE_CTRL, CACHE_ENA, 3, 1) + +REG32(DPORT_APP_CACHE_CTRL1, 0x5C) + FIELD(DPORT_APP_CACHE_CTRL1, MMU_IA_CLR, 13, 1) + FIELD(DPORT_APP_CACHE_CTRL1, MASK_OPSDRAM, 5, 1) + FIELD(DPORT_APP_CACHE_CTRL1, MASK_DROM0, 4, 1) + FIELD(DPORT_APP_CACHE_CTRL1, MASK_DRAM1, 3, 1) + FIELD(DPORT_APP_CACHE_CTRL1, MASK_IROM0, 2, 1) + FIELD(DPORT_APP_CACHE_CTRL1, MASK_IRAM1, 1, 1) + FIELD(DPORT_APP_CACHE_CTRL1, MASK_IRAM0, 0, 1) + +REG32(DPORT_SLAVE_SPI_CONFIG, 0xC8) + FIELD(DPORT_SLAVE_SPI_CONFIG, SLAVE_SPI_ENCRYPT_ENABLE, 8, 1) + FIELD(DPORT_SLAVE_SPI_CONFIG, SLAVE_SPI_DECRYPT_ENABLE, 12, 1) + +REG32(DPORT_CPU_INTR_FROM_CPU_0, 0xdc) +REG32(DPORT_CPU_INTR_FROM_CPU_1, 0xe0) +REG32(DPORT_CPU_INTR_FROM_CPU_2, 0xe4) +REG32(DPORT_CPU_INTR_FROM_CPU_3, 0xe8) + +REG32(DPORT_PRO_MAC_INTR_MAP, 0x104) +REG32(DPORT_APP_MAC_INTR_MAP, 0x218) + +REG32(DPORT_PRO_DCACHE_DBUG0, 0x3f0) + FIELD(DPORT_PRO_DCACHE_DBUG0, CACHE_STATE, 7, 12) + +REG32(DPORT_PRO_DCACHE_DBUG3, 0x3FC) + FIELD(DPORT_PRO_DCACHE_DBUG3, IA_INT_OPPOSITE, 9, 1) + FIELD(DPORT_PRO_DCACHE_DBUG3, IA_INT_DRAM1, 10, 1) + FIELD(DPORT_PRO_DCACHE_DBUG3, IA_INT_IROM0, 11, 1) + FIELD(DPORT_PRO_DCACHE_DBUG3, IA_INT_IRAM1, 12, 1) + FIELD(DPORT_PRO_DCACHE_DBUG3, IA_INT_IRAM0, 13, 1) + FIELD(DPORT_PRO_DCACHE_DBUG3, IA_INT_DROM0, 14, 1) + +REG32(DPORT_APP_DCACHE_DBUG0, 0x418) + FIELD(DPORT_APP_DCACHE_DBUG0, CACHE_STATE, 7, 12) + +REG32(DPORT_APP_DCACHE_DBUG3, 0x424) + FIELD(DPORT_APP_DCACHE_DBUG3, IA_INT_OPPOSITE, 9, 1) + FIELD(DPORT_APP_DCACHE_DBUG3, IA_INT_DRAM1, 10, 1) + FIELD(DPORT_APP_DCACHE_DBUG3, IA_INT_IROM0, 11, 1) + FIELD(DPORT_APP_DCACHE_DBUG3, IA_INT_IRAM1, 12, 1) + FIELD(DPORT_APP_DCACHE_DBUG3, IA_INT_IRAM0, 13, 1) + FIELD(DPORT_APP_DCACHE_DBUG3, IA_INT_DROM0, 14, 1) + +REG32(DPORT_CACHE_IA_INT_EN, 0x5A0) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_PRO_OPPOSITE, 19, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_PRO_DRAM1, 18, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_PRO_IROM0, 17, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_PRO_IRAM1, 16, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_PRO_IRAM0, 15, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_PRO_DROM0, 14, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_APP_OPPOSITE, 5, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_APP_DRAM1, 4, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_APP_IROM0, 3, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_APP_IRAM1, 2, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_APP_IRAM0, 1, 1) + FIELD(DPORT_CACHE_IA_INT_EN, IA_INT_APP_DROM0, 0, 1) + + +#define ESP32_DPORT_PRO_INTMATRIX_BASE A_DPORT_PRO_MAC_INTR_MAP +#define ESP32_DPORT_APP_INTMATRIX_BASE A_DPORT_APP_MAC_INTR_MAP +#define ESP32_DPORT_CROSSCORE_INT_BASE A_DPORT_CPU_INTR_FROM_CPU_0 + From a5a01e6fdd2f164d38e7654b0886ae462f1a3fa5 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:38:22 +0200 Subject: [PATCH 16/56] hw/misc: ESP32 RNG --- hw/misc/esp32_rng.c | 56 +++++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/misc/esp32_rng.h | 17 +++++++++++ 3 files changed, 74 insertions(+) create mode 100644 hw/misc/esp32_rng.c create mode 100644 include/hw/misc/esp32_rng.h diff --git a/hw/misc/esp32_rng.c b/hw/misc/esp32_rng.c new file mode 100644 index 000000000000..9df49de9a527 --- /dev/null +++ b/hw/misc/esp32_rng.c @@ -0,0 +1,56 @@ +/* + * ESP32 Random Number Generator peripheral + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_rng.h" + + +static uint64_t esp32_rng_read(void *opaque, hwaddr addr, unsigned int size) +{ + uint32_t r = 0; + qemu_guest_getrandom_nofail(&r, sizeof(r)); + return r; +} + +static const MemoryRegionOps esp32_rng_ops = { + .read = esp32_rng_read, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_rng_init(Object *obj) +{ + Esp32RngState *s = ESP32_RNG(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_rng_ops, s, + TYPE_ESP32_RNG, sizeof(uint32_t)); + sysbus_init_mmio(sbd, &s->iomem); +} + + +static const TypeInfo esp32_rng_info = { + .name = TYPE_ESP32_RNG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32RngState), + .instance_init = esp32_rng_init, +}; + +static void esp32_rng_register_types(void) +{ + type_register_static(&esp32_rng_info); +} + +type_init(esp32_rng_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 662cd4250d91..39de9d5dea1f 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -128,6 +128,7 @@ softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_rng.c')) softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_crosscore_int.c', 'esp32_dport.c', + 'esp32_rng.c', )) softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_ahb_apb_pnp.c')) diff --git a/include/hw/misc/esp32_rng.h b/include/hw/misc/esp32_rng.h new file mode 100644 index 000000000000..1065310a3c16 --- /dev/null +++ b/include/hw/misc/esp32_rng.h @@ -0,0 +1,17 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_reg.h" + + +#define TYPE_ESP32_RNG "misc.esp32.rng" +#define ESP32_RNG(obj) OBJECT_CHECK(Esp32RngState, (obj), TYPE_ESP32_RNG) + +typedef struct Esp32RngState { + SysBusDevice parent_obj; + MemoryRegion iomem; +} Esp32RngState; + +#define ESP32_RNG_BASE (DR_REG_WDEV_BASE + 0x144) + From 2fd9ccd9238d08e84dd38518be39e8cc5333a3cc Mon Sep 17 00:00:00 2001 From: Sachin Billore Date: Sat, 22 Aug 2020 19:32:45 +0530 Subject: [PATCH 17/56] hw/misc: add ESP32 RSA --- hw/misc/esp32_rsa.c | 365 ++++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 6 + include/hw/misc/esp32_rsa.h | 46 +++++ 3 files changed, 417 insertions(+) create mode 100644 hw/misc/esp32_rsa.c create mode 100644 include/hw/misc/esp32_rsa.h diff --git a/hw/misc/esp32_rsa.c b/hw/misc/esp32_rsa.c new file mode 100644 index 000000000000..a996833085a8 --- /dev/null +++ b/hw/misc/esp32_rsa.c @@ -0,0 +1,365 @@ +/* + * ESP32 RSA accelerator + * + * Copyright (c) 2020 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/boards.h" +#include "hw/misc/esp32_rsa.h" +#include + + +#define ESP32_RSA_REGS_SIZE (A_RSA_QUERY_CLEAN_REG + 4) + +static void copy_reversed(unsigned char* dest, size_t dst_size, const unsigned char* src, size_t src_size); +static bool mpi_block_to_gcrypt(const uint32_t* mem_block, size_t n_bytes, gcry_mpi_t *out); +static bool mpi_gcrypt_to_block(gcry_mpi_t in, uint32_t* mem_block); +static void esp32_rsa_exp_mod(Esp32RsaState *s); +static void esp32_rsa_mul_start(Esp32RsaState *s); +static void esp32_rsa_mul_op(Esp32RsaState *s); +static void esp32_rsa_mod_mul_op(Esp32RsaState *s); + + +/** + * Convert between libgcrypt big-endian representation and little-endian hardware, or vice versa. + * src_size should not exceed dst_size. The remaining part of dst is filled with 0. + */ +static void copy_reversed(unsigned char* dst, size_t dst_size, const unsigned char* src, size_t src_size) +{ + assert(src_size <= dst_size); + size_t i; + for (i = 0; i < src_size; ++i) { + dst[i] = src[src_size - i - 1]; + } + for (; i < dst_size; ++i) { + dst[i] = 0; + } +} + +/** + * Converts the little-endian memory block of the RSA peripheral to a new gcry_mpi_t object. + * The caller is responsible for freeing the returned object. + */ +static bool mpi_block_to_gcrypt(const uint32_t* mem_block, size_t n_bytes, gcry_mpi_t *out) +{ + size_t scanned; + const unsigned char* mem_u8 = (const unsigned char*) mem_block; + unsigned char temp_buffer[ESP32_RSA_MEM_BLK_SIZE] = {}; + copy_reversed(temp_buffer, n_bytes, mem_u8, n_bytes); + gcry_error_t err = gcry_mpi_scan(out, GCRYMPI_FMT_USG, temp_buffer, n_bytes, &scanned); + if (err) { + fprintf(stderr, "%s: gcry_mpi_scan failed with error: %s (%d)", __func__, gcry_strerror(err), err); + return false; + } + if (scanned != n_bytes) { + fprintf(stderr, "%s: gcry_mpi_scan scanned %zu, expected %zu", __func__, scanned, n_bytes); + return false; + } + return true; +} + +/** + * Copies an MPI from gcry_mpi_t object to the RSA peripheral memory block. + */ +static bool mpi_gcrypt_to_block(gcry_mpi_t in, uint32_t* mem_block) +{ + size_t written; + unsigned char* mem_u8 = (unsigned char*) mem_block; + unsigned char temp_buffer[ESP32_RSA_MEM_BLK_SIZE] = {}; + gcry_error_t err = gcry_mpi_print(GCRYMPI_FMT_USG, temp_buffer, ESP32_RSA_MEM_BLK_SIZE, &written, in); + if (err) { + fprintf(stderr, "%s: gcry_mpi_print failed with error: %s (%d)", __func__, gcry_strerror(err), err); + return false; + } + copy_reversed(mem_u8, ESP32_RSA_MEM_BLK_SIZE, temp_buffer, written); + return true; +} + +/** Calculates Z_MEM = X_MEM ^ Y_MEM mod M_MEM. + * Unlike the real hardware, doesn't use the mprime register. + */ +static void esp32_rsa_exp_mod(Esp32RsaState *s) +{ + gcry_mpi_t x, y, z, m; + + size_t n_bytes = (s->rsa_modexp_mode_reg + 1) * 64; + + /* convert inputs to gcry_mpi_t */ + if (!mpi_block_to_gcrypt(s->rsa_x_mem, n_bytes, &x) || + !mpi_block_to_gcrypt(s->rsa_y_mem, n_bytes, &y) || + !mpi_block_to_gcrypt(s->rsa_m_mem, n_bytes, &m)) { + return; + } + + /* calculate the result and write it back */ + z = gcry_mpi_new(n_bytes); + gcry_mpi_powm(z, x, y, m); + mpi_gcrypt_to_block(z, s->rsa_z_mem); + + /* clean up */ + gcry_mpi_release(x); + gcry_mpi_release(y); + gcry_mpi_release(z); + gcry_mpi_release(m); + + /* indicate that the operation is complete */ + s->rsa_q_int_reg = 1; +} + + +static void esp32_rsa_mul_start(Esp32RsaState *s) +{ + /* Hardware does different operations depending on rsa_mult_mode_reg value: */ + bool is_mod_mult = (s->rsa_mult_mode_reg < 8); + if (is_mod_mult) { + esp32_rsa_mod_mul_op(s); + } else { + esp32_rsa_mul_op(s); + } +} + +/** Calculates Z_MEM = X_MEM * (Z_MEM >> n) */ +static void esp32_rsa_mul_op(Esp32RsaState *s) +{ + assert(s->rsa_mult_mode_reg >= 8 && s->rsa_mult_mode_reg < 16); + /* In this mode, the output length is set by rsa_mult_mode_reg, + * and the length of inputs is half of that. + * Z input is shifted (multiplied by 2^(input length in bits)), + * and needs to be shifted back before passing to gcry_mpi_mul. + */ + size_t n_bytes = (s->rsa_mult_mode_reg - 8 + 1) * 64; + size_t n_bytes_input = n_bytes / 2; + memcpy(s->rsa_z_mem, s->rsa_z_mem + n_bytes_input / sizeof(s->rsa_z_mem[0]), n_bytes_input); + memset(s->rsa_z_mem + n_bytes_input / sizeof(s->rsa_z_mem[0]), 0, n_bytes_input); + /* convert inputs to gcry_mpi_t */ + gcry_mpi_t x, z, result; + if (!mpi_block_to_gcrypt(s->rsa_x_mem, n_bytes, &x) || + !mpi_block_to_gcrypt(s->rsa_z_mem, n_bytes, &z)) { + return; + } + /* multiply */ + result = gcry_mpi_new(n_bytes * 8); + gcry_mpi_mul(result, x, z); + mpi_gcrypt_to_block(result, s->rsa_z_mem); + + /* clean up */ + gcry_mpi_release(x); + gcry_mpi_release(z); + gcry_mpi_release(result); + + /* indicate that the operation is complete */ + s->rsa_q_int_reg = 1; +} + +/** Calculates Z_MEM = Z_MEM * X_MEM * R^-1 mod M_MEM. + * + * Real hardware does this using Montgomery multiplication + * algorithm. Here we simply call the modular multiplication function + * twice. + * R^-1 is re-calculated if M_MEM is modified. + * M' (mprime) register value is ignored in this simulation. + */ +static void esp32_rsa_mod_mul_op(Esp32RsaState *s) +{ + assert(s->rsa_mult_mode_reg < 8); + /* In this mode, the output and input lengths are the same */ + size_t n_bytes = (s->rsa_mult_mode_reg + 1) * 64; + gcry_mpi_t m; + if (!mpi_block_to_gcrypt(s->rsa_m_mem, n_bytes, &m)) { + return; + } + /* Calculate R^-1 if it hasn't been calculated yet */ + if (!s->cache.valid) { + if (!s->cache.rinv) { + s->cache.rinv = gcry_mpi_new(n_bytes * 8); + } + gcry_mpi_t r = gcry_mpi_new(n_bytes * 8 + 1); + gcry_mpi_set_bit(r, n_bytes * 8); + if (!gcry_mpi_invm(s->cache.rinv, r, m)) { + qemu_log("%s: failed to calculate modulo inverse\n", __func__); + return; + } + s->cache.valid = true; + } + + /* convert inputs to gcry_mpi_t */ + gcry_mpi_t x, z, res1, res2; + if (!mpi_block_to_gcrypt(s->rsa_x_mem, n_bytes, &x) || + !mpi_block_to_gcrypt(s->rsa_z_mem, n_bytes, &z)) { + gcry_mpi_release(m); + return; + } + + /* temporaries */ + res1 = gcry_mpi_new(n_bytes * 8 * 2); + res2 = gcry_mpi_new(n_bytes * 8 * 2); + + /* res1 = X * Z mod M */ + gcry_mpi_mulm(res1, x, z, m); + /* res2 = X * Z * Rinv mod M */ + gcry_mpi_mulm(res2, res1, s->cache.rinv, m); + + /* write back */ + mpi_gcrypt_to_block(res2, s->rsa_z_mem); + + /* clean up */ + gcry_mpi_release(x); + gcry_mpi_release(z); + gcry_mpi_release(res1); + + /* indicate that the operation is complete */ + s->rsa_q_int_reg = 1; +} + + +static void esp32_rsa_clean_mem(Esp32RsaState *s) +{ + memset(s->rsa_m_mem, 0, sizeof(s->rsa_m_mem)); + memset(s->rsa_x_mem, 0, sizeof(s->rsa_x_mem)); + memset(s->rsa_y_mem, 0, sizeof(s->rsa_y_mem)); + memset(s->rsa_z_mem, 0, sizeof(s->rsa_z_mem)); + s->cache.valid = false; +} + +static uint64_t esp32_rsa_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32RsaState *s = ESP32_RSA(opaque); + uint64_t val = 0; + + switch (addr) { + case A_RSA_MEM_Z_BLOCK_BASE ... (A_RSA_MEM_Z_BLOCK_BASE + ESP32_RSA_MEM_BLK_SIZE - 1): + val = s->rsa_z_mem[(addr - A_RSA_MEM_Z_BLOCK_BASE) / sizeof(uint32_t)]; + break; + + case A_RSA_QUERY_CLEAN_REG: + /* After coming out from reset, RSA Accelerator first initialize + * internal memory block to zeros before turning this register to 1. + * Software poll this register to read 1, before using the internal + * memory blocks. Internal memory block initialisation performed + * here before returning this read operation to 1. + */ + esp32_rsa_clean_mem(s); + val = s->rsa_clean_reg; + break; + + case A_RSA_QUERY_INTERRUPT_REG: + val = s->rsa_q_int_reg; + break; + } + + return val; +} + + +static void esp32_rsa_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32RsaState *s = ESP32_RSA(opaque); + + switch (addr) { + + case A_RSA_MEM_M_BLOCK_BASE ... (A_RSA_MEM_M_BLOCK_BASE + ESP32_RSA_MEM_BLK_SIZE - 1): + s->rsa_m_mem[(addr - A_RSA_MEM_M_BLOCK_BASE) / sizeof(uint32_t)] = (uint32_t)value; + s->cache.valid = false; + break; + + case A_RSA_MEM_RB_BLOCK_BASE ... (A_RSA_MEM_RB_BLOCK_BASE + ESP32_RSA_MEM_BLK_SIZE - 1): + s->rsa_z_mem[(addr - A_RSA_MEM_RB_BLOCK_BASE) / sizeof(uint32_t)] = (uint32_t)value; + break; + + case A_RSA_MEM_Y_BLOCK_BASE ... (A_RSA_MEM_Y_BLOCK_BASE + ESP32_RSA_MEM_BLK_SIZE - 1): + s->rsa_y_mem[(addr - A_RSA_MEM_Y_BLOCK_BASE) / sizeof(uint32_t)] = (uint32_t)value; + break; + + case A_RSA_MEM_X_BLOCK_BASE ... (A_RSA_MEM_X_BLOCK_BASE + ESP32_RSA_MEM_BLK_SIZE - 1): + s->rsa_x_mem[(addr - A_RSA_MEM_X_BLOCK_BASE) / sizeof(uint32_t)] = (uint32_t)value; + break; + + case A_RSA_M_DASH_REG: + s->rsa_mprime_reg = value; + break; + + case A_RSA_MODEXP_MODE_REG: + s->rsa_modexp_mode_reg = value; + break; + + case A_RSA_MULT_MODE_REG: + s->rsa_mult_mode_reg = value; + break; + + case A_RSA_MODEXP_START_REG: + esp32_rsa_exp_mod(s); + break; + + case A_RSA_MULT_START_REG: + esp32_rsa_mul_start(s); + break; + + case A_RSA_QUERY_INTERRUPT_REG: + /* Clear on write register */ + s->rsa_q_int_reg &= ~value; + break; + } + +} + +static const MemoryRegionOps esp32_rsa_ops = { + .read = esp32_rsa_read, + .write = esp32_rsa_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_rsa_reset(DeviceState *dev) +{ + Esp32RsaState *s = ESP32_RSA(dev); + + esp32_rsa_clean_mem(s); + + /* Clear any spurious interrupt */ + s->rsa_q_int_reg = 0; + + /* RSA memory block initialization complete */ + s->rsa_clean_reg = 1; +} + +static void esp32_rsa_init(Object *obj) +{ + Esp32RsaState *s = ESP32_RSA(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_rsa_ops, s, + TYPE_ESP32_RSA, ESP32_RSA_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void esp32_rsa_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_rsa_reset; +} + +static const TypeInfo esp32_rsa_info = { + .name = TYPE_ESP32_RSA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32RsaState), + .instance_init = esp32_rsa_init, + .class_init = esp32_rsa_class_init +}; + +static void esp32_rsa_register_types(void) +{ + type_register_static(&esp32_rsa_info); +} + +type_init(esp32_rsa_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 39de9d5dea1f..1ced91d686b1 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -131,6 +131,12 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_rng.c', )) +if gcrypt.found() + softmmu_ss.add(when: [gcrypt, 'CONFIG_XTENSA_ESP32'], if_true: files( + 'esp32_rsa.c', + )) +endif + softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_ahb_apb_pnp.c')) softmmu_ss.add(when: 'CONFIG_I2C', if_true: files('i2c-echo.c')) diff --git a/include/hw/misc/esp32_rsa.h b/include/hw/misc/esp32_rsa.h new file mode 100644 index 000000000000..31c8b0a6a29e --- /dev/null +++ b/include/hw/misc/esp32_rsa.h @@ -0,0 +1,46 @@ + #pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32_reg.h" + +#define TYPE_ESP32_RSA "misc.esp32.rsa" +#define ESP32_RSA(obj) OBJECT_CHECK(Esp32RsaState, (obj), TYPE_ESP32_RSA) + +#define ESP32_RSA_MEM_BLK_SIZE 0x200 + +typedef struct Esp32RsaState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + uint32_t rsa_m_mem[ESP32_RSA_MEM_BLK_SIZE / 4]; + uint32_t rsa_z_mem[ESP32_RSA_MEM_BLK_SIZE / 4]; + uint32_t rsa_y_mem[ESP32_RSA_MEM_BLK_SIZE / 4]; + uint32_t rsa_x_mem[ESP32_RSA_MEM_BLK_SIZE / 4]; + + struct { + void *rinv; + bool valid; + } cache; + + uint32_t rsa_mprime_reg; + uint32_t rsa_modexp_mode_reg; + uint32_t rsa_mult_mode_reg; + uint32_t rsa_clean_reg; + uint32_t rsa_q_int_reg; +} Esp32RsaState; + +REG32(RSA_MEM_M_BLOCK_BASE, 0x000) +REG32(RSA_MEM_RB_BLOCK_BASE, 0x200) +REG32(RSA_MEM_Z_BLOCK_BASE, 0x200) +REG32(RSA_MEM_Y_BLOCK_BASE, 0x400) +REG32(RSA_MEM_X_BLOCK_BASE, 0x600) +REG32(RSA_M_DASH_REG, 0x800) +REG32(RSA_MODEXP_MODE_REG, 0x804) +REG32(RSA_MODEXP_START_REG, 0x808) +REG32(RSA_MULT_MODE_REG, 0x80C) +REG32(RSA_MULT_START_REG, 0x810) +REG32(RSA_CLEAR_INTERRUPT_REG, 0x814) +REG32(RSA_QUERY_INTERRUPT_REG, 0x814) +REG32(RSA_QUERY_CLEAN_REG, 0x818) From 8c2b319cd1b98d16396dc1dbebb890139659707c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:38:01 +0200 Subject: [PATCH 18/56] hw/misc: ESP32 RTC controller --- hw/misc/esp32_rtc_cntl.c | 244 +++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/misc/esp32_rtc_cntl.h | 118 +++++++++++++++ 3 files changed, 363 insertions(+) create mode 100644 hw/misc/esp32_rtc_cntl.c create mode 100644 include/hw/misc/esp32_rtc_cntl.h diff --git a/hw/misc/esp32_rtc_cntl.c b/hw/misc/esp32_rtc_cntl.c new file mode 100644 index 000000000000..f4087a126112 --- /dev/null +++ b/hw/misc/esp32_rtc_cntl.c @@ -0,0 +1,244 @@ +/* + * ESP32 RTC_CNTL (RTC block controller) device + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/misc/esp32_reg.h" +#include "hw/misc/esp32_rtc_cntl.h" + +static void esp32_rtc_update_cpu_stall(Esp32RtcCntlState* s); +static void esp32_rtc_update_clk(Esp32RtcCntlState* s); + +static uint64_t esp32_rtc_cntl_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32RtcCntlState *s = ESP32_RTC_CNTL(opaque); + uint64_t r = 0; + switch (addr) { + case A_RTC_CNTL_OPTIONS0: + r = s->options0_reg; + break; + case A_RTC_CNTL_TIME_UPDATE: + r = R_RTC_CNTL_TIME_UPDATE_VALID_MASK; + break; + case A_RTC_CNTL_TIME0: + r = s->time_reg & UINT32_MAX; + break; + case A_RTC_CNTL_TIME1: + r = s->time_reg >> 32; + break; + + case A_RTC_CNTL_RESET_STATE: + r = FIELD_DP32(r, RTC_CNTL_RESET_STATE, RESET_CAUSE_PROCPU, s->reset_cause[0]); + r = FIELD_DP32(r, RTC_CNTL_RESET_STATE, RESET_CAUSE_APPCPU, s->reset_cause[1]); + r = FIELD_DP32(r, RTC_CNTL_RESET_STATE, PROCPU_STAT_VECTOR_SEL, s->stat_vector_sel[0]); + r = FIELD_DP32(r, RTC_CNTL_RESET_STATE, APPCPU_STAT_VECTOR_SEL, s->stat_vector_sel[1]); + break; + + case A_RTC_CNTL_STORE0: + case A_RTC_CNTL_STORE1: + case A_RTC_CNTL_STORE2: + case A_RTC_CNTL_STORE3: + r = s->scratch_reg[(addr - A_RTC_CNTL_STORE0) / 4]; + break; + + case A_RTC_CNTL_CLK_CONF: + r = FIELD_DP32(r, RTC_CNTL_CLK_CONF, SOC_CLK_SEL, s->soc_clk); + r = FIELD_DP32(r, RTC_CNTL_CLK_CONF, FAST_CLK_RTC_SEL, s->rtc_fastclk); + r = FIELD_DP32(r, RTC_CNTL_CLK_CONF, ANA_CLK_RTC_SEL, s->rtc_slowclk); + break; + + case A_RTC_CNTL_SW_CPU_STALL: + r = s->sw_cpu_stall_reg; + break; + + case A_RTC_CNTL_STORE4: + case A_RTC_CNTL_STORE5: + case A_RTC_CNTL_STORE6: + case A_RTC_CNTL_STORE7: + r = s->scratch_reg[(addr - A_RTC_CNTL_STORE4) / 4 + 4]; + break; + } + return r; +} + +static void esp32_rtc_cntl_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) +{ + Esp32RtcCntlState *s = ESP32_RTC_CNTL(opaque); + switch (addr) { + case A_RTC_CNTL_OPTIONS0: + if (value & R_RTC_CNTL_OPTIONS0_SW_SYS_RESET_MASK) { + s->reset_cause[0] = ESP32_SW_SYS_RESET; + s->reset_cause[1] = ESP32_SW_SYS_RESET; + qemu_irq_pulse(s->dig_reset_req); + value &= ~(R_RTC_CNTL_OPTIONS0_SW_SYS_RESET_MASK); + } + if (value & R_RTC_CNTL_OPTIONS0_SW_APPCPU_RESET_MASK) { + s->reset_cause[1] = ESP32_SW_CPU_RESET; + qemu_irq_pulse(s->cpu_reset_req[1]); + value &= ~(R_RTC_CNTL_OPTIONS0_SW_APPCPU_RESET_MASK); + } + if (value & R_RTC_CNTL_OPTIONS0_SW_PROCPU_RESET_MASK) { + s->reset_cause[0] = ESP32_SW_CPU_RESET; + qemu_irq_pulse(s->cpu_reset_req[0]); + value &= ~(R_RTC_CNTL_OPTIONS0_SW_PROCPU_RESET_MASK); + } + s->options0_reg = value; + esp32_rtc_update_cpu_stall(s); + break; + + case A_RTC_CNTL_TIME_UPDATE: + if (value & R_RTC_CNTL_TIME_UPDATE_UPDATE_MASK) { + s->time_reg = muldiv64( + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->time_base_ns, + s->rtc_slowclk_freq, NANOSECONDS_PER_SECOND); + } + break; + + case A_RTC_CNTL_RESET_STATE: + s->stat_vector_sel[0] = FIELD_EX32(value, RTC_CNTL_RESET_STATE, + PROCPU_STAT_VECTOR_SEL); + s->stat_vector_sel[1] = FIELD_EX32(value, RTC_CNTL_RESET_STATE, + APPCPU_STAT_VECTOR_SEL); + break; + + case A_RTC_CNTL_STORE0: + case A_RTC_CNTL_STORE1: + case A_RTC_CNTL_STORE2: + case A_RTC_CNTL_STORE3: + s->scratch_reg[(addr - A_RTC_CNTL_STORE0) / 4] = value; + break; + + case A_RTC_CNTL_CLK_CONF: + s->soc_clk = FIELD_EX32(value, RTC_CNTL_CLK_CONF, SOC_CLK_SEL); + s->rtc_fastclk = FIELD_EX32(value, RTC_CNTL_CLK_CONF, FAST_CLK_RTC_SEL); + s->rtc_slowclk = FIELD_EX32(value, RTC_CNTL_CLK_CONF, ANA_CLK_RTC_SEL); + esp32_rtc_update_clk(s); + break; + + case A_RTC_CNTL_SW_CPU_STALL: + s->sw_cpu_stall_reg = value; + esp32_rtc_update_cpu_stall(s); + break; + + case A_RTC_CNTL_STORE4: + case A_RTC_CNTL_STORE5: + case A_RTC_CNTL_STORE6: + case A_RTC_CNTL_STORE7: + s->scratch_reg[(addr - A_RTC_CNTL_STORE4) / 4 + 4] = value; + break; + } +} + +static void esp32_rtc_update_cpu_stall(Esp32RtcCntlState* s) +{ + uint32_t procpu_stall = (FIELD_EX32(s->sw_cpu_stall_reg, RTC_CNTL_SW_CPU_STALL, PROCPU_C1) << 2) | + (FIELD_EX32(s->options0_reg, RTC_CNTL_OPTIONS0, SW_STALL_PROCPU_C0)); + + uint32_t appcpu_stall = (FIELD_EX32(s->sw_cpu_stall_reg, RTC_CNTL_SW_CPU_STALL, APPCPU_C1) << 2) | + (FIELD_EX32(s->options0_reg, RTC_CNTL_OPTIONS0, SW_STALL_APPCPU_C0)); + + const uint32_t stall_magic_val = 0x86; + + s->cpu_stall_state[0] = procpu_stall == stall_magic_val; + s->cpu_stall_state[1] = appcpu_stall == stall_magic_val; + + qemu_set_irq(s->cpu_stall_req[0], s->cpu_stall_state[0]); + qemu_set_irq(s->cpu_stall_req[1], s->cpu_stall_state[1]); +} + +static void esp32_rtc_update_clk(Esp32RtcCntlState* s) +{ + const uint32_t slowclk_freq[] = {150000, 32768, 8000000/256}; + const uint32_t fastclk_freq[] = {s->xtal_apb_freq / 4, 8000000}; + s->rtc_slowclk_freq = slowclk_freq[s->rtc_slowclk]; + s->rtc_fastclk_freq = fastclk_freq[s->rtc_fastclk]; + qemu_irq_pulse(s->clk_update); +} + +static const MemoryRegionOps esp32_rtc_cntl_ops = { + .read = esp32_rtc_cntl_read, + .write = esp32_rtc_cntl_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_rtc_cntl_reset(DeviceState *dev) +{ + Esp32RtcCntlState *s = ESP32_RTC_CNTL(dev); + + s->time_base_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void esp32_rtc_cntl_realize(DeviceState *dev, Error **errp) +{ +} + +static void esp32_rtc_cntl_init(Object *obj) +{ + Esp32RtcCntlState *s = ESP32_RTC_CNTL(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_rtc_cntl_ops, s, + TYPE_ESP32_RTC_CNTL, ESP32_RTC_CNTL_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + qdev_init_gpio_out_named(DEVICE(sbd), &s->dig_reset_req, ESP32_RTC_DIG_RESET_GPIO, 1); + qdev_init_gpio_out_named(DEVICE(sbd), &s->cpu_reset_req[0], ESP32_RTC_CPU_RESET_GPIO, ESP32_CPU_COUNT); + qdev_init_gpio_out_named(DEVICE(sbd), &s->cpu_stall_req[0], ESP32_RTC_CPU_STALL_GPIO, ESP32_CPU_COUNT); + qdev_init_gpio_out_named(DEVICE(sbd), &s->clk_update, ESP32_RTC_CLK_UPDATE_GPIO, 1); + + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + s->reset_cause[i] = ESP32_POWERON_RESET; + s->stat_vector_sel[i] = true; + } + + s->rtc_slowclk = ESP32_SLOW_CLK_RC; + s->rtc_fastclk = ESP32_FAST_CLK_8M; + s->soc_clk = ESP32_SOC_CLK_XTAL; + s->xtal_apb_freq = 40000000; + s->pll_apb_freq = 80000000; + esp32_rtc_update_clk(s); +} + +static Property esp32_rtc_cntl_properties[] = { + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_rtc_cntl_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_rtc_cntl_reset; + dc->realize = esp32_rtc_cntl_realize; + device_class_set_props(dc, esp32_rtc_cntl_properties); +} + +static const TypeInfo esp32_rtc_cntl_info = { + .name = TYPE_ESP32_RTC_CNTL, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32RtcCntlState), + .instance_init = esp32_rtc_cntl_init, + .class_init = esp32_rtc_cntl_class_init +}; + +static void esp32_rtc_cntl_register_types(void) +{ + type_register_static(&esp32_rtc_cntl_info); +} + +type_init(esp32_rtc_cntl_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 1ced91d686b1..cbfc10686234 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -129,6 +129,7 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_crosscore_int.c', 'esp32_dport.c', 'esp32_rng.c', + 'esp32_rtc_cntl.c', )) if gcrypt.found() diff --git a/include/hw/misc/esp32_rtc_cntl.h b/include/hw/misc/esp32_rtc_cntl.h new file mode 100644 index 000000000000..cef7baceba4d --- /dev/null +++ b/include/hw/misc/esp32_rtc_cntl.h @@ -0,0 +1,118 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" + +#include "hw/misc/esp32_reg.h" +#define TYPE_ESP32_RTC_CNTL "misc.esp32.rtc_cntl" +#define ESP32_RTC_CNTL(obj) OBJECT_CHECK(Esp32RtcCntlState, (obj), TYPE_ESP32_RTC_CNTL) + +#define ESP32_RTC_DIG_RESET_GPIO "dig-reset" +#define ESP32_RTC_CPU_RESET_GPIO "cpu-reset" +#define ESP32_RTC_CPU_STALL_GPIO "cpu-stall" +#define ESP32_RTC_CLK_UPDATE_GPIO "clk-update" + +typedef enum Esp32ResetCause { + ESP32_POWERON_RESET = 1, + ESP32_SW_SYS_RESET = 3, + ESP32_OWDT_RESET = 4, + ESP32_DEEPSLEEP_RESET = 5, + ESP32_SDIO_RESET = 6, + ESP32_TG0WDT_SYS_RESET = 7, + ESP32_TG1WDT_SYS_RESET = 8, + ESP32_RTCWDT_SYS_RESET = 9, + ESP32_TGWDT_CPU_RESET = 11, + ESP32_SW_CPU_RESET = 12, + ESP32_RTCWDT_CPU_RESET = 13, + ESP32_EXT_CPU_RESET = 14, + ESP32_RTCWDT_BROWN_OUT_RESET = 15, + ESP32_RTCWDT_RTC_RESET = 16 +} Esp32ResetCause; + +typedef enum Esp32SocClkSel { + ESP32_SOC_CLK_XTAL = 0, + ESP32_SOC_CLK_PLL = 1, + ESP32_SOC_CLK_8M = 2, + ESP32_SOC_CLK_APLL = 3 +} Esp32SocClkSel; + +typedef enum Esp32FastClkSel { + ESP32_FAST_CLK_XTALD4 = 0, + ESP32_FAST_CLK_8M = 1 +} Esp32FastClkSel; + +typedef enum Esp32SlowClkSel { + ESP32_SLOW_CLK_RC = 0, + ESP32_SLOW_CLK_32KXTAL = 1, + ESP32_SLOW_CLK_8MD256 = 2 +} Esp32SlowClkSel; + +typedef struct Esp32RtcCntlState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + qemu_irq dig_reset_req; + qemu_irq cpu_reset_req[ESP32_CPU_COUNT]; + qemu_irq cpu_stall_req[ESP32_CPU_COUNT]; + qemu_irq clk_update; + bool cpu_stall_state[ESP32_CPU_COUNT]; + + uint32_t xtal_apb_freq; + uint32_t pll_apb_freq; + Esp32SocClkSel soc_clk; + Esp32FastClkSel rtc_fastclk; + uint32_t rtc_fastclk_freq; + Esp32SlowClkSel rtc_slowclk; + uint32_t rtc_slowclk_freq; + int64_t time_base_ns; + + uint32_t options0_reg; + uint64_t time_reg; + uint32_t sw_cpu_stall_reg; + uint32_t scratch_reg[ESP32_RTC_CNTL_SCRATCH_REG_COUNT]; + Esp32ResetCause reset_cause[ESP32_CPU_COUNT]; + bool stat_vector_sel[ESP32_CPU_COUNT]; +} Esp32RtcCntlState; + +REG32(RTC_CNTL_OPTIONS0, 0x00) + FIELD(RTC_CNTL_OPTIONS0, SW_SYS_RESET, 31, 1) + FIELD(RTC_CNTL_OPTIONS0, SW_PROCPU_RESET, 5, 1) + FIELD(RTC_CNTL_OPTIONS0, SW_APPCPU_RESET, 4, 1) + FIELD(RTC_CNTL_OPTIONS0, SW_STALL_PROCPU_C0, 2, 2) + FIELD(RTC_CNTL_OPTIONS0, SW_STALL_APPCPU_C0, 0, 2) + +REG32(RTC_CNTL_TIME_UPDATE, 0xc) + FIELD(RTC_CNTL_TIME_UPDATE, UPDATE, 31, 1) + FIELD(RTC_CNTL_TIME_UPDATE, VALID, 30, 1) +REG32(RTC_CNTL_TIME0, 0x10) +REG32(RTC_CNTL_TIME1, 0x14) + +REG32(RTC_CNTL_RESET_STATE, 0x34) + FIELD(RTC_CNTL_RESET_STATE, PROCPU_STAT_VECTOR_SEL, 13, 1) + FIELD(RTC_CNTL_RESET_STATE, APPCPU_STAT_VECTOR_SEL, 12, 1) + FIELD(RTC_CNTL_RESET_STATE, RESET_CAUSE_APPCPU, 6, 6) + FIELD(RTC_CNTL_RESET_STATE, RESET_CAUSE_PROCPU, 0, 6) + +REG32(RTC_CNTL_STORE0, 0x4c) +REG32(RTC_CNTL_STORE1, 0x50) +REG32(RTC_CNTL_STORE2, 0x54) +REG32(RTC_CNTL_STORE3, 0x58) + +REG32(RTC_CNTL_CLK_CONF, 0x70) + FIELD(RTC_CNTL_CLK_CONF, ANA_CLK_RTC_SEL, 30, 2) + FIELD(RTC_CNTL_CLK_CONF, FAST_CLK_RTC_SEL, 29, 1) + FIELD(RTC_CNTL_CLK_CONF, SOC_CLK_SEL, 27, 2) + +REG32(RTC_CNTL_SW_CPU_STALL, 0xac) + FIELD(RTC_CNTL_SW_CPU_STALL, PROCPU_C1, 26, 6) + FIELD(RTC_CNTL_SW_CPU_STALL, APPCPU_C1, 20, 6) + +REG32(RTC_CNTL_STORE4, 0xb0) +REG32(RTC_CNTL_STORE5, 0xb4) +REG32(RTC_CNTL_STORE6, 0xb8) +REG32(RTC_CNTL_STORE7, 0xbc) +REG32(RTC_CNTL_DATE, 0x13c) + +#define ESP32_RTC_CNTL_SIZE (A_RTC_CNTL_DATE + 4) From 03638c2c271c70a8707f64d6c4409febb27a6383 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:38:50 +0200 Subject: [PATCH 19/56] hw/misc: add ESP32 SHA Co-authored-by: Maksim Naumenko --- crypto/meson.build | 4 + crypto/sha1-internal.c | 227 ++++++++++++++++++++++++++++++++++++ crypto/sha1_i.h | 21 ++++ crypto/sha256-internal.c | 107 +++++++++++++++++ crypto/sha256_i.h | 20 ++++ crypto/sha384-internal.c | 37 ++++++ crypto/sha384_i.h | 19 +++ crypto/sha512-internal.c | 148 +++++++++++++++++++++++ crypto/sha512_i.h | 20 ++++ hw/misc/esp32_sha.c | 132 +++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/misc/esp32_sha.h | 36 ++++++ 12 files changed, 772 insertions(+) create mode 100644 crypto/sha1-internal.c create mode 100644 crypto/sha1_i.h create mode 100644 crypto/sha256-internal.c create mode 100644 crypto/sha256_i.h create mode 100644 crypto/sha384-internal.c create mode 100644 crypto/sha384_i.h create mode 100644 crypto/sha512-internal.c create mode 100644 crypto/sha512_i.h create mode 100644 hw/misc/esp32_sha.c create mode 100644 include/hw/misc/esp32_sha.h diff --git a/crypto/meson.build b/crypto/meson.build index 5f03a30d342d..e35c633c8576 100644 --- a/crypto/meson.build +++ b/crypto/meson.build @@ -50,6 +50,10 @@ crypto_ss.add(when: gnutls, if_true: files('tls-cipher-suites.c')) util_ss.add(files('sm4.c')) util_ss.add(files('aes.c')) +util_ss.add(files('sha512-internal.c')) +util_ss.add(files('sha384-internal.c')) +util_ss.add(files('sha256-internal.c')) +util_ss.add(files('sha1-internal.c')) util_ss.add(files('init.c')) if gnutls.found() util_ss.add(gnutls) diff --git a/crypto/sha1-internal.c b/crypto/sha1-internal.c new file mode 100644 index 000000000000..a56d55c91b9a --- /dev/null +++ b/crypto/sha1-internal.c @@ -0,0 +1,227 @@ +/* + * SHA1 hash implementation and interface functions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "sha1_i.h" +#include "stddef.h" +#include "string.h" + +typedef struct sha1_state SHA1_CTX; + +/* ===== start - public domain SHA1 implementation ===== */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * ----------------- + * Modified 7/98 + * By James H. Brown + * Still 100% Public Domain + * + * Corrected a problem which generated improper hash values on 16 bit machines + * Routine SHA1Update changed from + * void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int + * len) + * to + * void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned + * long len) + * + * The 'len' parameter was declared an int which works fine on 32 bit machines. + * However, on 16 bit machines an int is too small for the shifts being done + * against + * it. This caused the hash function to generate incorrect values if len was + * greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). + * + * Since the file IO in main() reads 16K at a time, any file 8K or larger would + * be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million + * "a"s). + * + * I also changed the declaration of variables i & j in SHA1Update to + * unsigned long from unsigned int for the same reason. + * + * These changes should make no difference to any 32 bit implementations since + * an + * int and a long are the same size in those environments. + * + * -- + * I also corrected a few compiler warnings generated by Borland C. + * 1. Added #include for exit() prototype + * 2. Removed unused variable 'j' in SHA1Final + * 3. Changed exit(0) to return(0) at end of main. + * + * ALL changes I made can be located by searching for comments containing 'JHB' + * ----------------- + * Modified 8/98 + * By Steve Reid + * Still 100% public domain + * + * 1- Removed #include and used return() instead of exit() + * 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) + * 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net + * + * ----------------- + * Modified 4/01 + * By Saul Kravitz + * Still 100% PD + * Modified to run on Compaq Alpha hardware. + * + * ----------------- + * Modified 4/01 + * By Jouni Malinen + * Minor changes to match the coding style used in Dynamics. + * + * Modified September 24, 2004 + * By Jouni Malinen + * Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. + * + */ + +/* + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + */ + +#define SHA1HANDSOFF + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#ifndef WORDS_BIGENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ + (rol(block->l[i], 8) & 0x00FF00FF)) +#else +#define blk0(i) (block->l[i]) +#endif +#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ + block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v, w, x, y, z, i) \ + do { \ + z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); \ + } while (0) +#define R1(v, w, x, y, z, i) \ + do { \ + z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); \ + } while (0) +#define R2(v, w, x, y, z, i) \ + do { \ + z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ + w = rol(w, 30); \ + } while (0) +#define R3(v, w, x, y, z, i) \ + do { \ + z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ + w = rol(w, 30); \ + } while (0) +#define R4(v, w, x, y, z, i) \ + do { \ + z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ + w = rol(w, 30); \ + } while (0) + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void sha1_compress(uint32_t state[5], const unsigned char buffer[64]) +{ + uint32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + uint32_t l[16]; + } CHAR64LONG16; + CHAR64LONG16 *block; +#ifdef SHA1HANDSOFF + CHAR64LONG16 workspace; + block = &workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); + R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); + R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); + R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); + R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); + R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); + R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); + R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); + R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); + R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); + R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); + R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); + R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); + R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); + R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); + R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); + R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); + R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); + R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); + R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); + R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, 0, 64); +#endif +} + +/* sha1_init - Initialize new context */ + +void sha1_init(SHA1_CTX *context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + +/* ===== end - public domain SHA1 implementation ===== */ diff --git a/crypto/sha1_i.h b/crypto/sha1_i.h new file mode 100644 index 000000000000..b91211fce6e3 --- /dev/null +++ b/crypto/sha1_i.h @@ -0,0 +1,21 @@ +/* + * SHA1 internal definitions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA1_I_H +#define SHA1_I_H +#include "qemu/osdep.h" + +struct sha1_state { + uint32_t state[5]; + uint32_t count[2]; +}; + +void sha1_init(struct sha1_state *context); +void sha1_compress(uint32_t state[5], const unsigned char buffer[64]); + +#endif /* SHA1_I_H */ diff --git a/crypto/sha256-internal.c b/crypto/sha256-internal.c new file mode 100644 index 000000000000..708269eb1187 --- /dev/null +++ b/crypto/sha256-internal.c @@ -0,0 +1,107 @@ +/* + * SHA-256 hash implementation and interface functions + * Copyright (c) 2003-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "sha256_i.h" + +static inline uint32_t WPA_GET_BE32(const uint8_t *a) +{ + return ((uint32_t) a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]; +} + +/* ===== start - public domain SHA256 implementation ===== */ + +/* + * This is based on SHA256 implementation in LibTomCrypt that was released into + * public domain by Tom St Denis. + */ + +/* the K array */ +static const unsigned long K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Compress */ +#define RND(a, b, c, d, e, f, g, h, i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; +/* Various logical functions */ +#define RORc(x, y) \ +(((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ + ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) +#define Ch(x, y, z) (z ^ (x & (y ^ z))) +#define Maj(x, y, z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x), (n)) +#define R(x, n) (((x) & 0xFFFFFFFFUL) >> (n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +/* compress 512-bits */ +int sha256_compress(struct sha256_state *md, unsigned char *buf) +{ + uint32_t S[8], W[64], t0, t1; + uint32_t t; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + W[i] = WPA_GET_BE32(buf + (4 * i)); + } + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + + W[i - 16]; + } + + for (i = 0; i < 64; ++i) { + RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } + + /* feedback */ + for (i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + return 0; +} + +/* Initialize the hash state */ +void sha256_init(struct sha256_state *md) +{ + md->state[0] = 0x6A09E667UL; + md->state[1] = 0xBB67AE85UL; + md->state[2] = 0x3C6EF372UL; + md->state[3] = 0xA54FF53AUL; + md->state[4] = 0x510E527FUL; + md->state[5] = 0x9B05688CUL; + md->state[6] = 0x1F83D9ABUL; + md->state[7] = 0x5BE0CD19UL; +} + +/* ===== end - public domain SHA256 implementation ===== */ diff --git a/crypto/sha256_i.h b/crypto/sha256_i.h new file mode 100644 index 000000000000..50d23ec55513 --- /dev/null +++ b/crypto/sha256_i.h @@ -0,0 +1,20 @@ +/* + * SHA-256 internal definitions + * Copyright (c) 2003-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA256_I_H +#define SHA256_I_H +#include "qemu/osdep.h" + +struct sha256_state { + uint32_t state[8]; +}; + +void sha256_init(struct sha256_state *md); +int sha256_compress(struct sha256_state *md, unsigned char *buf); + +#endif /* SHA256_I_H */ diff --git a/crypto/sha384-internal.c b/crypto/sha384-internal.c new file mode 100644 index 000000000000..1a0e6f807416 --- /dev/null +++ b/crypto/sha384-internal.c @@ -0,0 +1,37 @@ +/* + * SHA-384 hash implementation and interface functions + * Copyright (c) 2015, Pali Rohár + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "sha384_i.h" + +/* ===== start - public domain SHA384 implementation ===== */ + +/* + * This is based on SHA384 implementation in LibTomCrypt that was released into + * public domain by Tom St Denis. + */ + +#define CONST64(n) n ## ULL + +/* + * Initialize the hash state + * @param md The hash state you wish to initialize + * @return CRYPT_OK if successful + */ +void sha384_init(struct sha512_state *md) +{ + md->state[0] = CONST64(0xcbbb9d5dc1059ed8); + md->state[1] = CONST64(0x629a292a367cd507); + md->state[2] = CONST64(0x9159015a3070dd17); + md->state[3] = CONST64(0x152fecd8f70e5939); + md->state[4] = CONST64(0x67332667ffc00b31); + md->state[5] = CONST64(0x8eb44a8768581511); + md->state[6] = CONST64(0xdb0c2e0d64f98fa7); + md->state[7] = CONST64(0x47b5481dbefa4fa4); +} + +/* ===== end - public domain SHA384 implementation ===== */ diff --git a/crypto/sha384_i.h b/crypto/sha384_i.h new file mode 100644 index 000000000000..e8f9793af070 --- /dev/null +++ b/crypto/sha384_i.h @@ -0,0 +1,19 @@ +/* + * SHA-384 internal definitions + * Copyright (c) 2015, Pali Rohár + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA384_I_H +#define SHA384_I_H + +#include "qemu/osdep.h" +#include "sha512_i.h" + +#define sha384_state sha512_state + +void sha384_init(struct sha384_state *md); + +#endif /* SHA384_I_H */ diff --git a/crypto/sha512-internal.c b/crypto/sha512-internal.c new file mode 100644 index 000000000000..9ee72afb745a --- /dev/null +++ b/crypto/sha512-internal.c @@ -0,0 +1,148 @@ +/* + * SHA-512 hash implementation and interface functions + * Copyright (c) 2015, Pali Rohár + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "sha512_i.h" + +static inline uint64_t WPA_GET_BE64(const uint8_t *a) +{ + return (((uint64_t) a[0]) << 56) | (((uint64_t) a[1]) << 48) | + (((uint64_t) a[2]) << 40) | (((uint64_t) a[3]) << 32) | + (((uint64_t) a[4]) << 24) | (((uint64_t) a[5]) << 16) | + (((uint64_t) a[6]) << 8) | ((uint64_t) a[7]); +} + +/* ===== start - public domain SHA512 implementation ===== */ + +/* + * This is based on SHA512 implementation in LibTomCrypt that was released into + * public domain by Tom St Denis. + */ + +#define CONST64(n) n ## ULL + +/* the K array */ +static const uint64_t K[80] = { + CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), + CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), + CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), + CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), + CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), + CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), + CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), + CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), + CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), + CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), + CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), + CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), + CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), + CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), + CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), + CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), + CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), + CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), + CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), + CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), + CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), + CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), + CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), + CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), + CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), + CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), + CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), + CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), + CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), + CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), + CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), + CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), + CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), + CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), + CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), + CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), + CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), + CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), + CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), + CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) +}; + +/* Various logical functions */ +#define Ch(x, y, z) (z ^ (x & (y ^ z))) +#define Maj(x, y, z) (((x | y) & z) | (x & y)) +#define S(x, n) ROR64c(x, n) +#define R(x, n) (((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((uint64_t) n)) +#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) +#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) +#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) +#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) + +#define ROR64c(x, y) \ + (((((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((uint64_t) (y) & CONST64(63))) | \ + ((x) << ((uint64_t) (64 - ((y) & CONST64(63)))))) & \ + CONST64(0xFFFFFFFFFFFFFFFF)) + +/* compress 1024-bits */ +int sha512_compress(struct sha512_state *md, unsigned char *buf) +{ + uint64_t S[8], t0, t1; + uint64_t W[80]; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + + /* copy the state into 1024-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + W[i] = WPA_GET_BE64(buf + (8 * i)); + } + /* fill W[16..79] */ + for (i = 16; i < 80; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + + W[i - 16]; + } + + /* Compress */ + for (i = 0; i < 80; i++) { + t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; + t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3] + t0; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = t0 + t1; + } + + /* feedback */ + for (i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + + return 0; +} + +/* + * Initialize the hash state + * @param md The hash state you wish to initialize + * @return CRYPT_OK if successful + */ +void sha512_init(struct sha512_state *md) +{ + md->state[0] = CONST64(0x6a09e667f3bcc908); + md->state[1] = CONST64(0xbb67ae8584caa73b); + md->state[2] = CONST64(0x3c6ef372fe94f82b); + md->state[3] = CONST64(0xa54ff53a5f1d36f1); + md->state[4] = CONST64(0x510e527fade682d1); + md->state[5] = CONST64(0x9b05688c2b3e6c1f); + md->state[6] = CONST64(0x1f83d9abfb41bd6b); + md->state[7] = CONST64(0x5be0cd19137e2179); +} + +/* ===== end - public domain SHA512 implementation ===== */ diff --git a/crypto/sha512_i.h b/crypto/sha512_i.h new file mode 100644 index 000000000000..a669e6fd1222 --- /dev/null +++ b/crypto/sha512_i.h @@ -0,0 +1,20 @@ +/* + * SHA-512 internal definitions + * Copyright (c) 2015, Pali Rohár + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA512_I_H +#define SHA512_I_H +#include "qemu/osdep.h" + +struct sha512_state { + uint64_t state[8]; +}; + +void sha512_init(struct sha512_state *md); +int sha512_compress(struct sha512_state *md, unsigned char *buf); + +#endif /* SHA512_I_H */ diff --git a/hw/misc/esp32_sha.c b/hw/misc/esp32_sha.c new file mode 100644 index 000000000000..411fb69d861c --- /dev/null +++ b/hw/misc/esp32_sha.c @@ -0,0 +1,132 @@ +/* + * ESP32 SHA accelerator + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "crypto/hash.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/boards.h" +#include "hw/misc/esp32_sha.h" + +#define ESP32_SHA_REGS_SIZE (A_SHA512_BUSY + 4) + +static void esp32_sha_text_reg_byteswap_to(Esp32ShaState* s, uint32_t* dst, size_t len_words) +{ + for (int i = 0; i < len_words; ++i) { + dst[i] = __builtin_bswap32(s->text[i]); + } +} + +static uint64_t esp32_sha_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32ShaState *s = ESP32_SHA(opaque); + uint64_t r = 0; + switch (addr) { + case 0 ... (ESP32_SHA_TEXT_REG_CNT - 1) * sizeof(uint32_t): + r = s->text[addr / sizeof(uint32_t)]; + break; + } + return r; +} + +static void esp32_sha_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32ShaState *s = ESP32_SHA(opaque); + switch (addr) { + case 0 ... (ESP32_SHA_TEXT_REG_CNT - 1) * sizeof(uint32_t): + s->text[addr / sizeof(uint32_t)] = value; + break; + case A_SHA1_START: + sha1_init(&s->sha1); + esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 16); + sha1_compress((uint32_t *)&s->sha1.state, (unsigned char *)s->text); + break; + case A_SHA256_START: + sha256_init(&s->sha256); + esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 16); + sha256_compress(&s->sha256, (unsigned char *)s->text); + break; + case A_SHA384_START: + sha384_init(&s->sha512); + esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 32); + sha512_compress(&s->sha512, (unsigned char *)s->text); + break; + case A_SHA512_START: + sha512_init(&s->sha512); + esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 32); + sha512_compress(&s->sha512, (unsigned char *)s->text); + break; + case A_SHA1_CONTINUE: + esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 16); + sha1_compress((uint32_t *)&s->sha1.state, (unsigned char *)s->text); + break; + case A_SHA256_CONTINUE: + esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 16); + sha256_compress(&s->sha256, (unsigned char *)s->text); + break; + case A_SHA384_CONTINUE: + case A_SHA512_CONTINUE: + esp32_sha_text_reg_byteswap_to(s, (uint32_t *) s->text, 32); + sha512_compress(&s->sha512, (unsigned char *)s->text); + break; + case A_SHA1_LOAD: + for (int i = 0; i < 5; i++) { + s->text[i] = s->sha1.state[i]; + } + break; + case A_SHA256_LOAD: + for (int i = 0; i < 8; i++) { + s->text[i] = s->sha256.state[i]; + } + break; + case A_SHA384_LOAD: + case A_SHA512_LOAD: + for (int i = 0; i < 8; i++) { + s->text[i * 2] = (uint32_t)(s->sha512.state[i] >> 32); + s->text[1 + (i * 2)] = (uint32_t)(s->sha512.state[i] & 0xffffffff); + } + break; + } +} + +static const MemoryRegionOps esp32_sha_ops = { + .read = esp32_sha_read, + .write = esp32_sha_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_sha_init(Object *obj) +{ + Esp32ShaState *s = ESP32_SHA(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_sha_ops, s, + TYPE_ESP32_SHA, ESP32_SHA_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static const TypeInfo esp32_sha_info = { + .name = TYPE_ESP32_SHA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32ShaState), + .instance_init = esp32_sha_init, +}; + +static void esp32_sha_register_types(void) +{ + type_register_static(&esp32_sha_info); +} + +type_init(esp32_sha_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index cbfc10686234..5b3496fe200e 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -130,6 +130,7 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_dport.c', 'esp32_rng.c', 'esp32_rtc_cntl.c', + 'esp32_sha.c', )) if gcrypt.found() diff --git a/include/hw/misc/esp32_sha.h b/include/hw/misc/esp32_sha.h new file mode 100644 index 000000000000..7a7594127dcc --- /dev/null +++ b/include/hw/misc/esp32_sha.h @@ -0,0 +1,36 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32_reg.h" +#include "crypto/sha512_i.h" +#include "crypto/sha384_i.h" +#include "crypto/sha256_i.h" +#include "crypto/sha1_i.h" + +#define TYPE_ESP32_SHA "misc.esp32.sha" +#define ESP32_SHA(obj) OBJECT_CHECK(Esp32ShaState, (obj), TYPE_ESP32_SHA) + +#define ESP32_SHA_TEXT_REG_CNT 32 + +typedef struct Esp32ShaState { + SysBusDevice parent_obj; + MemoryRegion iomem; + uint32_t text[ESP32_SHA_TEXT_REG_CNT]; + struct sha512_state sha512; + struct sha512_state sha384; + struct sha256_state sha256; + struct sha1_state sha1; +} Esp32ShaState; + +#define SHA_REG_GROUP(name, base) \ + REG32(name ## _START, (base)) \ + REG32(name ## _CONTINUE, (base + 0x4)) \ + REG32(name ## _LOAD, (base + 0x8)) \ + REG32(name ## _BUSY, (base + 0xc)) + +SHA_REG_GROUP(SHA1, 0x80) +SHA_REG_GROUP(SHA256, 0x90) +SHA_REG_GROUP(SHA384, 0xa0) +SHA_REG_GROUP(SHA512, 0xb0) From 3f70bd1e41f433758a8804d31eba2593cc7fe330 Mon Sep 17 00:00:00 2001 From: Maksim Naumenko Date: Mon, 30 May 2022 11:19:11 +0200 Subject: [PATCH 20/56] hw/misc: add ESP32 AES --- hw/misc/esp32_aes.c | 129 ++++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/misc/esp32_aes.h | 46 +++++++++++++ 3 files changed, 176 insertions(+) create mode 100644 hw/misc/esp32_aes.c create mode 100644 include/hw/misc/esp32_aes.h diff --git a/hw/misc/esp32_aes.c b/hw/misc/esp32_aes.c new file mode 100644 index 000000000000..a7f53eb7d7c4 --- /dev/null +++ b/hw/misc/esp32_aes.c @@ -0,0 +1,129 @@ +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_aes.h" +#include "crypto/aes.h" + +#define ESP32_AES_REGS_SIZE (A_AES_ENDIAN_REG + 4) + +/* + * process the value of the AES_MODE_REG + */ +static void esp32_aes_mode(Esp32AesState *s, uint32_t mode_value) +{ + if ((mode_value == 0) || (mode_value == 1) || (mode_value == 2)) { + s->mode.type = ESP32_AES_ENCRYPTION_MODE; + } else { + s->mode.type = ESP32_AES_DECRYPTION_MODE; + } + if ((mode_value == 0) || (mode_value == 4)) { + s->mode.bits = 128; + } else if ((mode_value == 1) || (mode_value == 5)) { + s->mode.bits = 192; + } else { + s->mode.bits = 256; + } +} + +/* + * fill the full_key according to the mode bits + * encrypt/decrypt according to mode value + * set idle to 1 + */ +static void esp32_aes_start(Esp32AesState *s) +{ + AES_KEY aes_key; + uint32_t full_key[s->mode.bits / 32]; + memcpy(full_key, s->key, s->mode.bits / 8); + if (s->mode.type == ESP32_AES_ENCRYPTION_MODE) { + AES_set_encrypt_key((unsigned char *)full_key, s->mode.bits, &aes_key); + AES_encrypt((unsigned char *)s->text, (unsigned char *)s->text, &aes_key); + } else if (s->mode.type == ESP32_AES_DECRYPTION_MODE) { + AES_set_decrypt_key((unsigned char *)full_key, s->mode.bits, &aes_key); + AES_decrypt((unsigned char *)s->text, (unsigned char *)s->text, &aes_key); + } + s->aes_idle_reg = 1; +} + +static uint64_t esp32_aes_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32AesState *s = ESP32_AES(opaque); + uint64_t r = 0; + switch (addr) { + case A_AES_TEXT_0_REG ... A_AES_TEXT_3_REG: + r = s->text[(addr - A_AES_TEXT_0_REG) / sizeof(uint32_t)]; + break; + case A_AES_IDLE_REG: + r = s->aes_idle_reg; + break; + } + return r; +} + + +static void esp32_aes_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32AesState *s = ESP32_AES(opaque); + switch (addr) { + case A_AES_TEXT_0_REG ... A_AES_TEXT_3_REG: + s->text[(addr - A_AES_TEXT_0_REG) / sizeof(uint32_t)] = value; + break; + case A_AES_KEY_0_REG ... A_AES_KEY_7_REG: + s->key[(addr - A_AES_KEY_0_REG) / sizeof(uint32_t)] = value; + break; + case A_AES_START_REG: + s->aes_idle_reg = 0; + esp32_aes_start(s); + break; + case A_AES_IDLE_REG: + s->aes_idle_reg = value; + break; + case A_AES_MODE_REG: + esp32_aes_mode(s, (uint32_t)value); + break; + } +} + +static const MemoryRegionOps esp32_aes_ops = { + .read = esp32_aes_read, + .write = esp32_aes_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_aes_reset(DeviceState *dev) +{ + Esp32AesState *s = ESP32_AES(dev); + s->aes_idle_reg = 0; +} + +static void esp32_aes_init(Object *obj) +{ + Esp32AesState *s = ESP32_AES(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_aes_ops, s, + TYPE_ESP32_AES, ESP32_AES_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void esp32_aes_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_aes_reset; +} + +static const TypeInfo esp32_aes_info = { + .name = TYPE_ESP32_AES, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32AesState), + .instance_init = esp32_aes_init, + .class_init = esp32_aes_class_init +}; + +static void esp32_aes_register_types(void) +{ + type_register_static(&esp32_aes_info); +} + +type_init(esp32_aes_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 5b3496fe200e..a13a38f1c09a 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -131,6 +131,7 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_rng.c', 'esp32_rtc_cntl.c', 'esp32_sha.c', + 'esp32_aes.c', )) if gcrypt.found() diff --git a/include/hw/misc/esp32_aes.h b/include/hw/misc/esp32_aes.h new file mode 100644 index 000000000000..76b8683e53b4 --- /dev/null +++ b/include/hw/misc/esp32_aes.h @@ -0,0 +1,46 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32_reg.h" + +#define TYPE_ESP32_AES "misc.esp32.aes" +#define ESP32_AES(obj) OBJECT_CHECK(Esp32AesState, (obj), TYPE_ESP32_AES) + +#define ESP32_AES_TEXT_REG_CNT 4 +#define ESP32_AES_KEY_REG_CNT 8 + +#define ESP32_AES_ENCRYPTION_MODE TRUE +#define ESP32_AES_DECRYPTION_MODE FALSE + +typedef struct Esp32AesState { + SysBusDevice parent_object; + MemoryRegion iomem; + uint32_t text[ESP32_AES_TEXT_REG_CNT]; + uint32_t key[ESP32_AES_KEY_REG_CNT]; + uint32_t aes_idle_reg; + struct { + bool type; + int bits; + } mode; +} Esp32AesState; + +REG32(AES_START_REG, 0x00) +REG32(AES_IDLE_REG, 0x04) +REG32(AES_MODE_REG, 0x08) +REG32(AES_ENDIAN_REG, 0x40) + +REG32(AES_KEY_0_REG, 0x10) +REG32(AES_KEY_1_REG, 0x14) +REG32(AES_KEY_2_REG, 0x18) +REG32(AES_KEY_3_REG, 0x1C) +REG32(AES_KEY_4_REG, 0x20) +REG32(AES_KEY_5_REG, 0x24) +REG32(AES_KEY_6_REG, 0x28) +REG32(AES_KEY_7_REG, 0x2C) + +REG32(AES_TEXT_0_REG, 0x30) +REG32(AES_TEXT_1_REG, 0x34) +REG32(AES_TEXT_2_REG, 0x38) +REG32(AES_TEXT_3_REG, 0x3C) From e5ef5b2352eb0d86442f3adad09519dffe527cdd Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 10 Feb 2021 03:10:05 +0100 Subject: [PATCH 21/56] hw/misc: add ESP32 flash encryption module --- hw/misc/esp32_flash_enc.c | 271 ++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/misc/esp32_flash_enc.h | 62 +++++++ 3 files changed, 334 insertions(+) create mode 100644 hw/misc/esp32_flash_enc.c create mode 100644 include/hw/misc/esp32_flash_enc.h diff --git a/hw/misc/esp32_flash_enc.c b/hw/misc/esp32_flash_enc.c new file mode 100644 index 000000000000..0ef9fef0c5c2 --- /dev/null +++ b/hw/misc/esp32_flash_enc.c @@ -0,0 +1,271 @@ +/* + * ESP32 flash encryption + * + * Copyright (c) 2020 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "crypto/cipher.h" +#include "hw/misc/esp32_flash_enc.h" +#include "hw/nvram/esp32_efuse.h" + +#define FLASH_ENCRYPTION_KEY_WORDS 8 +#define FLASH_ENCRYPTION_DATA_WORDS 4 + +static void esp32_flash_encryption_op(Esp32FlashEncryptionState *s); + +static uint64_t esp32_flash_encryption_read(void *opaque, hwaddr addr, + unsigned int size) +{ + Esp32FlashEncryptionState *s = ESP32_FLASH_ENCRYPTION(opaque); + switch (addr) { + case A_FLASH_ENCRYPTION_DONE: + return s->encryption_done; + } + return 0; +} + +static void esp32_flash_encryption_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32FlashEncryptionState *s = ESP32_FLASH_ENCRYPTION(opaque); + + switch (addr) { + case A_FLASH_ENCRYPTION_BUFFER_0 ... A_FLASH_ENCRYPTION_BUFFER_7: + s->buffer_reg[(addr - A_FLASH_ENCRYPTION_BUFFER_0) / 4] = value; + break; + + case A_FLASH_ENCRYPTION_START: + if (FIELD_EX32(value, FLASH_ENCRYPTION_START, START)) { + esp32_flash_encryption_op(s); + } + s->encryption_done = true; + break; + + case A_FLASH_ENCRYPTION_ADDRESS: + s->address_reg = value; + break; + + case A_FLASH_ENCRYPTION_DONE: + if (FIELD_EX32(value, FLASH_ENCRYPTION_DONE, DONE) == 0) { + s->encryption_done = false; + } + break; + } +} + +static const MemoryRegionOps esp32_flash_encryption_ops = { + .read = esp32_flash_encryption_read, + .write = esp32_flash_encryption_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +bool esp32_flash_encryption_enabled(struct Esp32FlashEncryptionState *s) +{ + /* Logic from ESP32 Technical Reference Manual section 25.3.2 */ + if (s->dl_mode) { + return s->encrypt_enable_reg && !s->dl_mode_enc_disabled; + } else { + return s->encrypt_enable_reg; + } +} + +bool esp32_flash_decryption_enabled(struct Esp32FlashEncryptionState *s) +{ + /* Logic from ESP32 Technical Reference Manual section 25.3.3 */ + if (s->dl_mode) { + return s->decrypt_enable_reg && !s->dl_mode_dec_disabled; + } else { + return s->efuse_encrypt_enabled; + } +} + +static void esp32_flash_encryption_key_tweak(struct Esp32FlashEncryptionState *s, + size_t offset, const uint32_t *in_key, uint32_t *out_key) +{ + uint32_t offset_5 = offset >> 5; + uint32_t offset_5_8 = (offset_5) & 0xf; + uint32_t offset_5_10 = (offset_5) & 0x3f; + uint32_t offset_5_12 = (offset_5) & 0xff; + uint32_t offset_5_14 = (offset_5) & 0x3ff; + uint32_t offset_5_23 = (offset_5) & 0x7ffff; + + uint32_t key_tweak[FLASH_ENCRYPTION_KEY_WORDS] = { + (offset_5_23 >> 6) | (offset_5_23 << 13), + (offset_5_14 >> 3) | (offset_5_23 << 7) | (offset_5_23 << 26), + (offset_5_23 >> 9) | (offset_5_23 << 10) | (offset_5_14 << 29), + (offset_5_12 >> 4) | (offset_5_23 << 4) | (offset_5_23 << 23), + (offset_5_23 >> 10) | (offset_5_23 << 9) | (offset_5_12 << 28), + (offset_5_10 >> 3) | (offset_5_23 << 3) | (offset_5_23 << 22), + (offset_5_23 >> 9) | (offset_5_23 << 10) | (offset_5_10 << 29), + (offset_5_8) | (offset_5_23 << 4) | (offset_5_23 << 23) + }; + + for (size_t i = 0; i < FLASH_ENCRYPTION_KEY_WORDS; ++i) { + out_key[i] = in_key[i] ^ bswap32(key_tweak[i]); + } +} + +static void reverse_key_byte_order(const uint32_t* src, uint32_t* dst) +{ + assert( src != dst ); + for (size_t i = 0; i < FLASH_ENCRYPTION_KEY_WORDS; ++i) { + dst[i] = bswap32(src[FLASH_ENCRYPTION_KEY_WORDS - i - 1]); + } +} + +static void reverse_data_byte_order(const uint32_t* src, uint32_t* dst) +{ + assert( src != dst ); + for (size_t i = 0; i < FLASH_ENCRYPTION_DATA_WORDS; ++i) { + dst[i] = bswap32(src[FLASH_ENCRYPTION_DATA_WORDS - i - 1]); + } +} + +static void esp32_flash_encryption_op(struct Esp32FlashEncryptionState *s) +{ + uint32_t tweaked_key[FLASH_ENCRYPTION_KEY_WORDS]; + uint32_t reversed_key[FLASH_ENCRYPTION_KEY_WORDS]; + uint32_t reversed_data[FLASH_ENCRYPTION_DATA_WORDS]; + uint32_t encrypted_data[FLASH_ENCRYPTION_DATA_WORDS]; + + memset(s->encrypted_buffer, 0, sizeof(s->encrypted_buffer)); + reverse_key_byte_order(s->efuse_key, reversed_key); + esp32_flash_encryption_key_tweak(s, s->address_reg, reversed_key, tweaked_key); + QCryptoCipher *cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256, QCRYPTO_CIPHER_MODE_ECB, (const uint8_t*) tweaked_key, FLASH_ENCRYPTION_KEY_WORDS * 4, &error_abort); + for (size_t total_words = 0; total_words < ARRAY_SIZE(s->buffer_reg); total_words += FLASH_ENCRYPTION_DATA_WORDS) { + reverse_data_byte_order(s->buffer_reg + total_words, reversed_data); + qcrypto_cipher_decrypt(cipher, reversed_data, encrypted_data, sizeof(s->buffer_reg), &error_abort); + reverse_data_byte_order(encrypted_data, s->encrypted_buffer + total_words); + } + qcrypto_cipher_free(cipher); +} + +void esp32_flash_encryption_get_result(struct Esp32FlashEncryptionState* s, uint32_t* dst, size_t dst_words) +{ + assert(dst_words * 4 == sizeof(s->encrypted_buffer)); + memcpy(dst, s->encrypted_buffer, sizeof(s->encrypted_buffer)); +} + +void esp32_flash_decrypt_inplace(struct Esp32FlashEncryptionState* s, size_t flash_addr, uint32_t* data, size_t words) +{ + assert(flash_addr % 32 == 0); + assert(words % FLASH_ENCRYPTION_DATA_WORDS == 0); + uint32_t tweaked_key[FLASH_ENCRYPTION_KEY_WORDS]; + uint32_t reversed_key[FLASH_ENCRYPTION_KEY_WORDS]; + uint32_t reversed_data[FLASH_ENCRYPTION_DATA_WORDS]; + uint32_t decrypted_data[FLASH_ENCRYPTION_DATA_WORDS]; + + reverse_key_byte_order(s->efuse_key, reversed_key); + for (size_t pos = 0; pos < words; pos += FLASH_ENCRYPTION_DATA_WORDS) { + uint32_t offset = flash_addr + pos * 4; + esp32_flash_encryption_key_tweak(s, offset, reversed_key, tweaked_key); + QCryptoCipher *cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256, QCRYPTO_CIPHER_MODE_ECB, (const uint8_t*) tweaked_key, FLASH_ENCRYPTION_KEY_WORDS * 4, &error_abort); + reverse_data_byte_order(data + pos, reversed_data); + qcrypto_cipher_encrypt(cipher, reversed_data, decrypted_data, sizeof(decrypted_data), &error_abort); + reverse_data_byte_order(decrypted_data, data + pos); + qcrypto_cipher_free(cipher); + } +} + +static void esp32_flash_encryption_on_dl_mode_change(void *opaque, int n, + int level) +{ + Esp32FlashEncryptionState *s = ESP32_FLASH_ENCRYPTION(opaque); + s->dl_mode = !!level; +} + +static void esp32_flash_encryption_on_enc_enable_change(void *opaque, int n, + int level) +{ + Esp32FlashEncryptionState *s = ESP32_FLASH_ENCRYPTION(opaque); + s->encrypt_enable_reg = !!level; +} + +static void esp32_flash_encryption_on_dec_enable_change(void *opaque, int n, + int level) +{ + Esp32FlashEncryptionState *s = ESP32_FLASH_ENCRYPTION(opaque); + s->decrypt_enable_reg = !!level; +} + +static void esp32_flash_encryption_on_efuse_update(void *opaque, int n, + int level) +{ + if (!level) { + return; + } + Esp32FlashEncryptionState *s = ESP32_FLASH_ENCRYPTION(opaque); + Esp32EfuseState *efuse = esp32_efuse_find(); + /* Odd number of bits in flash_crypt_cnt indicates that flash encryption is enabled */ + s->efuse_encrypt_enabled = (ctpop32(efuse->efuse_rd.blk0_d0.flash_crypt_cnt) % 2) == 1; + uint32_t flash_crypt_config = efuse->efuse_rd.blk0_d5.flash_crypt_config; + if (s->efuse_encrypt_enabled && flash_crypt_config != 0xf) { + qemu_log("%s: Unsupported value of flash_crypt_config: 0x%x\n", __func__, flash_crypt_config); + } + if (efuse->efuse_rd.blk0_d6.coding_scheme != 0) { + qemu_log("%s: Unsupported value of coding_scheme: 0x%x\n", + __func__, efuse->efuse_rd.blk0_d6.coding_scheme); + } + /* Copy the key */ + memcpy(s->efuse_key, &efuse->efuse_rd.blk1[0], sizeof(s->efuse_key)); +} + +static void esp32_flash_encryption_init(Object *obj) +{ + Esp32FlashEncryptionState *s = ESP32_FLASH_ENCRYPTION(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_flash_encryption_ops, s, + TYPE_ESP32_FLASH_ENCRYPTION, + A_FLASH_ENCRYPTION_DONE + 4); + + qdev_init_gpio_in_named(DEVICE(s), esp32_flash_encryption_on_dl_mode_change, + ESP32_FLASH_ENCRYPTION_DL_MODE_GPIO, 1); + qdev_init_gpio_in_named(DEVICE(s), + esp32_flash_encryption_on_enc_enable_change, + ESP32_FLASH_ENCRYPTION_ENC_EN_GPIO, 1); + qdev_init_gpio_in_named(DEVICE(s), + esp32_flash_encryption_on_dec_enable_change, + ESP32_FLASH_ENCRYPTION_DEC_EN_GPIO, 1); + qdev_init_gpio_in_named(DEVICE(s), esp32_flash_encryption_on_efuse_update, + ESP32_FLASH_ENCRYPTION_EFUSE_UPDATE_GPIO, 1); + + sysbus_init_mmio(sbd, &s->iomem); +} + +static void esp32_flash_encryption_reset(DeviceState *dev) +{ + Esp32FlashEncryptionState *s = ESP32_FLASH_ENCRYPTION(dev); + s->encryption_done = false; +} + +static void esp32_flash_encryption_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_flash_encryption_reset; +} + +static const TypeInfo esp32_flash_encryption_info = { + .name = TYPE_ESP32_FLASH_ENCRYPTION, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32FlashEncryptionState), + .instance_init = esp32_flash_encryption_init, + .class_init = esp32_flash_encryption_class_init +}; + +static void esp32_flash_encryption_register_types(void) +{ + type_register_static(&esp32_flash_encryption_info); +} + +type_init(esp32_flash_encryption_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index a13a38f1c09a..e66c3bb26eaa 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -132,6 +132,7 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_rtc_cntl.c', 'esp32_sha.c', 'esp32_aes.c', + 'esp32_flash_enc.c', )) if gcrypt.found() diff --git a/include/hw/misc/esp32_flash_enc.h b/include/hw/misc/esp32_flash_enc.h new file mode 100644 index 000000000000..70de1115f61c --- /dev/null +++ b/include/hw/misc/esp32_flash_enc.h @@ -0,0 +1,62 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" + +#define TYPE_ESP32_FLASH_ENCRYPTION "misc.esp32.flash_encryption" +#define ESP32_FLASH_ENCRYPTION(obj) OBJECT_CHECK(Esp32FlashEncryptionState, (obj), TYPE_ESP32_FLASH_ENCRYPTION) + +#define ESP32_FLASH_ENCRYPTION_DL_MODE_GPIO "dl-mode" +#define ESP32_FLASH_ENCRYPTION_ENC_EN_GPIO "flash-enc-enable" +#define ESP32_FLASH_ENCRYPTION_DEC_EN_GPIO "flash-dec-enable" +#define ESP32_FLASH_ENCRYPTION_EFUSE_UPDATE_GPIO "efuse-update" + +typedef struct Esp32FlashEncryptionState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + uint32_t buffer_reg[8]; + uint32_t address_reg; + + bool encryption_done; + uint32_t encrypted_buffer[8]; + + bool dl_mode; + bool encrypt_enable_reg; /* mirrors DPORT_SPI_ENCRYPT_ENABLE state */ + bool decrypt_enable_reg; /* mirrors DPORT_SPI_DECRYPT_ENABLE state */ + bool efuse_encrypt_enabled; + bool dl_mode_enc_disabled; + bool dl_mode_dec_disabled; + uint32_t efuse_key[8]; + +} Esp32FlashEncryptionState; + +/* returns NULL unless there is exactly one device */ +static inline Esp32FlashEncryptionState *esp32_flash_encryption_find(void) +{ + Object *o = object_resolve_path_type("", TYPE_ESP32_FLASH_ENCRYPTION, NULL); + return o ? ESP32_FLASH_ENCRYPTION(o) : NULL; +} + +bool esp32_flash_encryption_enabled(struct Esp32FlashEncryptionState* s); +bool esp32_flash_decryption_enabled(struct Esp32FlashEncryptionState* s); +void esp32_flash_encryption_get_result(struct Esp32FlashEncryptionState* s, uint32_t* dst, size_t dst_words); +void esp32_flash_decrypt_inplace(struct Esp32FlashEncryptionState* s, size_t flash_addr, uint32_t* data, size_t words); + + +REG32(FLASH_ENCRYPTION_BUFFER_0, 0x00) +REG32(FLASH_ENCRYPTION_BUFFER_1, 0x04) +REG32(FLASH_ENCRYPTION_BUFFER_2, 0x08) +REG32(FLASH_ENCRYPTION_BUFFER_3, 0x0C) +REG32(FLASH_ENCRYPTION_BUFFER_4, 0x10) +REG32(FLASH_ENCRYPTION_BUFFER_5, 0x14) +REG32(FLASH_ENCRYPTION_BUFFER_6, 0x18) +REG32(FLASH_ENCRYPTION_BUFFER_7, 0x1C) +REG32(FLASH_ENCRYPTION_START, 0x20) + FIELD(FLASH_ENCRYPTION_START, START, 0, 1) + +REG32(FLASH_ENCRYPTION_ADDRESS, 0x24) + +REG32(FLASH_ENCRYPTION_DONE, 0x28) + FIELD(FLASH_ENCRYPTION_DONE, DONE, 0, 1) From 84a85968fcd002957985b2a1658fb3187caa12e8 Mon Sep 17 00:00:00 2001 From: Maksim Naumenko Date: Fri, 30 Sep 2022 13:11:23 +0200 Subject: [PATCH 22/56] hw/misc: Add ESP32 LEDC --- hw/misc/esp32_ledc.c | 154 +++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + include/hw/misc/esp32_ledc.h | 66 +++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 hw/misc/esp32_ledc.c create mode 100644 include/hw/misc/esp32_ledc.h diff --git a/hw/misc/esp32_ledc.c b/hw/misc/esp32_ledc.c new file mode 100644 index 000000000000..9cebea98214e --- /dev/null +++ b/hw/misc/esp32_ledc.c @@ -0,0 +1,154 @@ +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "hw/misc/esp32_ledc.h" + +#define ESP32_LEDC_REGS_SIZE (A_LEDC_CONF_REG + 4) + +static uint64_t esp32_ledc_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32LEDCState *s = ESP32_LEDC(opaque); + uint64_t r = 0; + switch (addr) { + case A_LEDC_HSTIMER0_CONF_REG ... A_LEDC_LSTIMER3_CONF_REG: + r = s->timer_conf_reg[(addr - A_LEDC_HSTIMER0_CONF_REG) / 0x8]; + break; + + case A_LEDC_HSCH0_CONF0_REG: + case A_LEDC_HSCH1_CONF0_REG: + case A_LEDC_HSCH2_CONF0_REG: + case A_LEDC_HSCH3_CONF0_REG: + case A_LEDC_HSCH4_CONF0_REG: + case A_LEDC_HSCH5_CONF0_REG: + case A_LEDC_HSCH6_CONF0_REG: + case A_LEDC_HSCH7_CONF0_REG: + case A_LEDC_LSCH0_CONF0_REG: + case A_LEDC_LSCH1_CONF0_REG: + case A_LEDC_LSCH2_CONF0_REG: + case A_LEDC_LSCH3_CONF0_REG: + case A_LEDC_LSCH4_CONF0_REG: + case A_LEDC_LSCH5_CONF0_REG: + case A_LEDC_LSCH6_CONF0_REG: + case A_LEDC_LSCH7_CONF0_REG: + r = s->channel_conf0_reg[(addr - A_LEDC_HSCH0_CONF0_REG) / 0x14]; + break; + } + return r; +} + +static uint32_t esp32_ledc_get_percent(Esp32LEDCState *s, uint32_t value, hwaddr addr) +{ + uint32_t duty_val = (value >> 4) & ((1 << 20) - 1); + uint32_t duty_res; + if (((addr - A_LEDC_HSCH0_DUTY_REG) / 0x14) < 8) { + /* get duty res for the high speed channel from high speed timer */ + duty_res = s->duty_res[(s->channel_conf0_reg[(addr - A_LEDC_HSCH0_DUTY_REG) / 0x14] & ((1 << 2) - 1))]; + } else { + /* get duty res for the low speed channel from low speed timer */ + duty_res = s->duty_res[((s->channel_conf0_reg[(addr - A_LEDC_HSCH0_DUTY_REG) / 0x14]) & ((1 << 2) - 1)) + 4]; + } + return duty_res ? (100 * duty_val / ((2 << (duty_res - 1)) - 1)) : 0; +} + +static void esp32_ledc_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32LEDCState *s = ESP32_LEDC(opaque); + switch (addr) { + case A_LEDC_HSTIMER0_CONF_REG ... A_LEDC_LSTIMER3_CONF_REG: + /* get duty resolution from timer config */ + if (((uint32_t)value & ((1 << 4) - 1)) != 0) { + s->duty_res[(addr - A_LEDC_HSTIMER0_CONF_REG) / 0x8] = (uint32_t)value & ((1 << 4) - 1); + } + s->timer_conf_reg[(addr - A_LEDC_HSTIMER0_CONF_REG) / 0x8] = value; + break; + + case A_LEDC_HSCH0_CONF0_REG: + case A_LEDC_HSCH1_CONF0_REG: + case A_LEDC_HSCH2_CONF0_REG: + case A_LEDC_HSCH3_CONF0_REG: + case A_LEDC_HSCH4_CONF0_REG: + case A_LEDC_HSCH5_CONF0_REG: + case A_LEDC_HSCH6_CONF0_REG: + case A_LEDC_HSCH7_CONF0_REG: + case A_LEDC_LSCH0_CONF0_REG: + case A_LEDC_LSCH1_CONF0_REG: + case A_LEDC_LSCH2_CONF0_REG: + case A_LEDC_LSCH3_CONF0_REG: + case A_LEDC_LSCH4_CONF0_REG: + case A_LEDC_LSCH5_CONF0_REG: + case A_LEDC_LSCH6_CONF0_REG: + case A_LEDC_LSCH7_CONF0_REG: + s->channel_conf0_reg[(addr - A_LEDC_HSCH0_CONF0_REG) / 0x14] = value; + break; + + case A_LEDC_HSCH0_DUTY_REG: + case A_LEDC_HSCH1_DUTY_REG: + case A_LEDC_HSCH2_DUTY_REG: + case A_LEDC_HSCH3_DUTY_REG: + case A_LEDC_HSCH4_DUTY_REG: + case A_LEDC_HSCH5_DUTY_REG: + case A_LEDC_HSCH6_DUTY_REG: + case A_LEDC_HSCH7_DUTY_REG: + case A_LEDC_LSCH0_DUTY_REG: + case A_LEDC_LSCH1_DUTY_REG: + case A_LEDC_LSCH2_DUTY_REG: + case A_LEDC_LSCH3_DUTY_REG: + case A_LEDC_LSCH4_DUTY_REG: + case A_LEDC_LSCH5_DUTY_REG: + case A_LEDC_LSCH6_DUTY_REG: + case A_LEDC_LSCH7_DUTY_REG: + led_set_intensity(&s->led[(addr - A_LEDC_HSCH0_DUTY_REG) / 0x14], esp32_ledc_get_percent(s, value, addr)); + break; + } + +} + +static const MemoryRegionOps esp32_ledc_ops = { + .read = esp32_ledc_read, + .write = esp32_ledc_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_ledc_realize(DeviceState *dev, Error **errp) +{ + Esp32LEDCState *s = ESP32_LEDC(dev); + for (int i = 0; i < ESP32_LEDC_CHANNEL_CNT; i++) { + qdev_realize(DEVICE(&s->led[i]), NULL, &error_fatal); + } +} + +static void esp32_ledc_init(Object *obj) +{ + Esp32LEDCState *s = ESP32_LEDC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + memory_region_init_io(&s->iomem, obj, &esp32_ledc_ops, s, + TYPE_ESP32_LEDC, ESP32_LEDC_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + for (int i = 0; i < ESP32_LEDC_CHANNEL_CNT; i++) { + object_initialize_child(obj, g_strdup_printf("led%d", i + 1), &s->led[i], TYPE_LED); + s->led[i].color = (char *)"blue"; + } +} + +static void esp32_ledc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + dc->realize = esp32_ledc_realize; +} + +static const TypeInfo esp32_ledc_info = { + .name = TYPE_ESP32_LEDC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32LEDCState), + .instance_init = esp32_ledc_init, + .class_init = esp32_ledc_class_init +}; + +static void esp32_ledc_register_types(void) +{ + type_register_static(&esp32_ledc_info); +} + +type_init(esp32_ledc_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index e66c3bb26eaa..92fda7270c43 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -132,6 +132,7 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_rtc_cntl.c', 'esp32_sha.c', 'esp32_aes.c', + 'esp32_ledc.c', 'esp32_flash_enc.c', )) diff --git a/include/hw/misc/esp32_ledc.h b/include/hw/misc/esp32_ledc.h new file mode 100644 index 000000000000..fe7e4e1dd4fa --- /dev/null +++ b/include/hw/misc/esp32_ledc.h @@ -0,0 +1,66 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32_reg.h" +#include "hw/misc/led.h" + +#define TYPE_ESP32_LEDC "misc.esp32.ledc" +#define ESP32_LEDC(obj) OBJECT_CHECK(Esp32LEDCState, (obj), TYPE_ESP32_LEDC) +#define ESP32_LEDC_TIMER_CNT 8 +#define ESP32_LEDC_CHANNEL_CNT 16 + +typedef struct Esp32LEDCState { + SysBusDevice parent_object; + MemoryRegion iomem; + uint32_t duty_res[ESP32_LEDC_TIMER_CNT]; + uint32_t timer_conf_reg[ESP32_LEDC_TIMER_CNT]; + uint32_t channel_conf0_reg[ESP32_LEDC_CHANNEL_CNT]; + LEDState led[ESP32_LEDC_CHANNEL_CNT]; +} Esp32LEDCState; + +REG32(LEDC_CONF_REG, 0x190) + +#define LEDC_REG_GROUP(name, base) \ + REG32(name ## _CONF0_REG, (base)) \ + REG32(name ## _CONF1_REG, ((base) + 0x00C)) \ + REG32(name ## _DUTY_REG, ((base) + 0x008)) \ + REG32(name ## _DUTY_R_REG, ((base) + 0x010)) + +#define LEDC_TIMER_REG_GROUP(name, base) \ + REG32(name ## _CONF_REG, (base)) \ + REG32(name ## _VALUE_REG, ((base) + 0x004)) + +LEDC_REG_GROUP(LEDC_HSCH0, 0x000) +LEDC_REG_GROUP(LEDC_HSCH1, 0x014) +LEDC_REG_GROUP(LEDC_HSCH2, 0x028) +LEDC_REG_GROUP(LEDC_HSCH3, 0x03C) +LEDC_REG_GROUP(LEDC_HSCH4, 0x050) +LEDC_REG_GROUP(LEDC_HSCH5, 0x064) +LEDC_REG_GROUP(LEDC_HSCH6, 0x078) +LEDC_REG_GROUP(LEDC_HSCH7, 0x08C) + +LEDC_REG_GROUP(LEDC_LSCH0, 0x0A0) +LEDC_REG_GROUP(LEDC_LSCH1, 0x0B4) +LEDC_REG_GROUP(LEDC_LSCH2, 0x0C8) +LEDC_REG_GROUP(LEDC_LSCH3, 0x0DC) +LEDC_REG_GROUP(LEDC_LSCH4, 0x0F0) +LEDC_REG_GROUP(LEDC_LSCH5, 0x104) +LEDC_REG_GROUP(LEDC_LSCH6, 0x118) +LEDC_REG_GROUP(LEDC_LSCH7, 0x12C) + +LEDC_TIMER_REG_GROUP(LEDC_HSTIMER0, 0x140) +LEDC_TIMER_REG_GROUP(LEDC_HSTIMER1, 0x148) +LEDC_TIMER_REG_GROUP(LEDC_HSTIMER2, 0x150) +LEDC_TIMER_REG_GROUP(LEDC_HSTIMER3, 0x158) + +LEDC_TIMER_REG_GROUP(LEDC_LSTIMER0, 0x160) +LEDC_TIMER_REG_GROUP(LEDC_LSTIMER1, 0x168) +LEDC_TIMER_REG_GROUP(LEDC_LSTIMER2, 0x170) +LEDC_TIMER_REG_GROUP(LEDC_LSTIMER3, 0x178) + +REG32(LEDC_INT_RAW_REG, 0x180) +REG32(LEDC_INT_ST_REG, 0x184) +REG32(LEDC_INT_ENA_REG, 0x188) +REG32(LEDC_INT_CLR_REG, 0x18C) From 995725f05435cda48bcb9a7b28f4c8c863879652 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 Jun 2021 22:49:20 +0200 Subject: [PATCH 23/56] hw/misc: add simple PSRAM emulation This is an SSIPeripheral instance that knows how to respond to read_id command. It doesn't store any data. It is sufficient for the IDF driver to decide to turn on the PSRAM cache. Actual data storage in PSRAM is emulated in DPORT. --- hw/misc/meson.build | 1 + hw/misc/ssi_psram.c | 118 ++++++++++++++++++++++++++++++++++++ include/hw/misc/ssi_psram.h | 18 ++++++ 3 files changed, 137 insertions(+) create mode 100644 hw/misc/ssi_psram.c create mode 100644 include/hw/misc/ssi_psram.h diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 92fda7270c43..fd85a80ba48b 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -134,6 +134,7 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_aes.c', 'esp32_ledc.c', 'esp32_flash_enc.c', + 'ssi_psram.c' )) if gcrypt.found() diff --git a/hw/misc/ssi_psram.c b/hw/misc/ssi_psram.c new file mode 100644 index 000000000000..df8b24b9eaa8 --- /dev/null +++ b/hw/misc/ssi_psram.c @@ -0,0 +1,118 @@ +/* + * ESP-PSRAM basic emulation + * + * Copyright (c) 2021 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/irq.h" +#include "qemu/module.h" +#include "hw/qdev-properties.h" +#include "hw/misc/ssi_psram.h" + +#define CMD_READ_ID 0x9f +#define PSRAM_ID_MFG 0x0d +#define PSRAM_ID_KGD 0x5d + +static int get_eid_by_size(uint32_t size_mbytes) { + switch (size_mbytes) + { + case 2: + return 0x00; + case 4: + return 0x21; + case 8: + return 0x40; + default: + qemu_log_mask(LOG_UNIMP, "%s: PSRAM size %" PRIu32 "MB not implemented\n", + __func__, size_mbytes); + return 0; + } +} + +static uint32_t psram_read(SsiPsramState *s) +{ + uint32_t result = 0; + if (s->command == CMD_READ_ID) { + uint8_t read_id_response[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, PSRAM_ID_MFG, PSRAM_ID_KGD, + get_eid_by_size(s->size_mbytes), + 0xaa, 0xbb, 0xcc, 0xdd, 0xee + }; + int index = s->byte_count - s->dummy; + if (index < ARRAY_SIZE(read_id_response)) { + result = read_id_response[index]; + } + } + return result; +} + +static void psram_write(SsiPsramState *s, uint32_t value) +{ + if (s->byte_count == s->dummy) { + s->command = value; + } + s->byte_count++; +} + +static uint32_t psram_transfer(SSIPeripheral *dev, uint32_t value) +{ + SsiPsramState *s = SSI_PSRAM(dev); + psram_write(s, value); + return psram_read(s); +} + +static int psram_cs(SSIPeripheral *ss, bool select) +{ + SsiPsramState *s = SSI_PSRAM(ss); + + if (!select) { + s->byte_count = 0; + s->command = -1; + } + return 0; +} + +static void psram_realize(SSIPeripheral *ss, Error **errp) +{ + SsiPsramState *s = SSI_PSRAM(ss); + s->dummy = 1; +} + +static Property psram_properties[] = { + DEFINE_PROP_UINT32("size_mbytes", SsiPsramState, size_mbytes, 4), + DEFINE_PROP_END_OF_LIST(), +}; + + +static void psram_class_init(ObjectClass *klass, void *data) +{ + SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + k->transfer = psram_transfer; + k->set_cs = psram_cs; + k->cs_polarity = SSI_CS_LOW; + k->realize = psram_realize; + device_class_set_props(dc, psram_properties); +} + +static const TypeInfo psram_info = { + .name = TYPE_SSI_PSRAM, + .parent = TYPE_SSI_PERIPHERAL, + .instance_size = sizeof(SsiPsramState), + .class_init = psram_class_init +}; + +static void psram_register_types(void) +{ + type_register_static(&psram_info); +} + +type_init(psram_register_types) diff --git a/include/hw/misc/ssi_psram.h b/include/hw/misc/ssi_psram.h new file mode 100644 index 000000000000..5585bd2b6a91 --- /dev/null +++ b/include/hw/misc/ssi_psram.h @@ -0,0 +1,18 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/ssi/ssi.h" +#include "qom/object.h" + +typedef struct SsiPsramState { + SSIPeripheral parent_obj; + uint32_t size_mbytes; + int dummy; + int command; + int byte_count; +} SsiPsramState; + +#define TYPE_SSI_PSRAM "ssi_psram" +OBJECT_DECLARE_SIMPLE_TYPE(SsiPsramState, SSI_PSRAM) + From 3371729d73ecace7796f8015ff767126c0cc6051 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:39:32 +0200 Subject: [PATCH 24/56] hw/timer: add ESP32 timers --- hw/timer/esp32_frc_timer.c | 245 +++++++++++ hw/timer/esp32_timg.c | 664 +++++++++++++++++++++++++++++ hw/timer/meson.build | 1 + hw/timer/trace-events | 8 + include/hw/timer/esp32_frc_timer.h | 49 +++ include/hw/timer/esp32_timg.h | 217 ++++++++++ 6 files changed, 1184 insertions(+) create mode 100644 hw/timer/esp32_frc_timer.c create mode 100644 hw/timer/esp32_timg.c create mode 100644 include/hw/timer/esp32_frc_timer.h create mode 100644 include/hw/timer/esp32_timg.h diff --git a/hw/timer/esp32_frc_timer.c b/hw/timer/esp32_frc_timer.c new file mode 100644 index 000000000000..7bfc4a198621 --- /dev/null +++ b/hw/timer/esp32_frc_timer.c @@ -0,0 +1,245 @@ +/* + * ESP32 FRC (legacy) timer + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/boards.h" +#include "hw/timer/esp32_frc_timer.h" +#include "trace.h" + +static uint64_t esp32_frc_timer_get_count(Esp32FrcTimerState *s, uint64_t ns_now) +{ + if (!s->enable) { + return s->count_base; + } + uint64_t ns_from_base = ns_now - s->ns_base; + uint64_t ticks_from_base = muldiv64(ns_from_base, s->apb_freq, NANOSECONDS_PER_SECOND * s->prescaler); + uint64_t count = (ticks_from_base + s->count_base) & s->count_mask; + return count; +} + +static uint64_t esp32_frc_timer_count_to_ns(Esp32FrcTimerState *s, uint64_t count) +{ + return muldiv64(count, NANOSECONDS_PER_SECOND * s->prescaler, s->apb_freq); +} + +static void esp32_frc_timer_update_alarm(Esp32FrcTimerState *s, uint64_t ticks_alarm, uint32_t ticks_now, uint64_t ns_now) +{ + if (ticks_alarm <= ticks_now) { + ticks_alarm += (1ULL << 32); + } + uint64_t ticks_to_alarm = ticks_alarm - ticks_now; + uint64_t ns_to_alarm = esp32_frc_timer_count_to_ns(s, ticks_to_alarm); + trace_esp32_frc_timer_update_alarm(ns_now, ticks_now, ticks_alarm, ns_to_alarm); + timer_mod_anticipate_ns(&s->alarm_timer, ns_now + ns_to_alarm); +} + +static void esp32_frc_timer_cb(void *opaque) +{ + Esp32FrcTimerState *s = ESP32_FRC_TIMER(opaque); + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint32_t count_now = esp32_frc_timer_get_count(s, ns_now); + trace_esp32_frc_timer_cb(ns_now, count_now); + + if (s->level_int) { + s->level_int_status = true; + qemu_irq_raise(s->irq); + } else { + qemu_irq_pulse(s->irq); + } + + if (s->autoload) { + esp32_frc_timer_update_alarm(s, s->alarm_reg, count_now, ns_now); + } +} + +static void esp32_frc_timer_update_config(Esp32FrcTimerState *s, + bool enable, bool level_int, bool autoload, int prescaler) +{ + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint32_t count_now = esp32_frc_timer_get_count(s, ns_now); + trace_esp32_frc_timer_update_config(ns_now, count_now, enable, level_int, autoload, prescaler); + + s->count_base = count_now; + s->ns_base = ns_now; + + if (!enable) { + timer_del(&s->alarm_timer); + } else { + esp32_frc_timer_update_alarm(s, s->alarm_reg, count_now, ns_now); + } + + s->enable = enable; + s->level_int = level_int; + s->autoload = autoload; + s->prescaler = prescaler; +} + + +static uint64_t esp32_frc_timer_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32FrcTimerState *s = ESP32_FRC_TIMER(opaque); + uint64_t r = 0; + switch (addr) { + case A_FRC_TIMER_ALARM: + r = s->alarm_reg; + break; + case A_FRC_TIMER_LOAD: + r = s->load_reg; + break; + case A_FRC_TIMER_CTRL: + r = FIELD_DP32(r, FRC_TIMER_CTRL, LEVEL_INT, s->level_int); + r = FIELD_DP32(r, FRC_TIMER_CTRL, PRESCALER, (s->prescaler == 1) ? 0 : (s->prescaler == 16) ? 2 : 4); + r = FIELD_DP32(r, FRC_TIMER_CTRL, AUTOLOAD, s->autoload); + r = FIELD_DP32(r, FRC_TIMER_CTRL, ENABLE, s->enable); + r = FIELD_DP32(r, FRC_TIMER_CTRL, STATUS, s->level_int_status); + break; + case A_FRC_TIMER_COUNT: { + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + r = (uint32_t) esp32_frc_timer_get_count(s, ns_now); + break; + } + case A_FRC_TIMER_INT_CLR: + default: + break; + } + trace_esp32_frc_timer_read(addr, r); + return r; +} + +static void esp32_frc_timer_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32FrcTimerState *s = ESP32_FRC_TIMER(opaque); + trace_esp32_frc_timer_write(addr, value); + switch (addr) { + case A_FRC_TIMER_INT_CLR: + if (value & 1) { + if (s->level_int_status) { + qemu_irq_lower(s->irq); + } + s->level_int_status = false; + } + break; + case A_FRC_TIMER_LOAD: + s->load_reg = value; + s->ns_base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + s->count_base = value; + break; + case A_FRC_TIMER_CTRL: { + bool level_int = FIELD_EX32(value, FRC_TIMER_CTRL, LEVEL_INT); + int prescaler = FIELD_EX32(value, FRC_TIMER_CTRL, PRESCALER); + bool autoload = FIELD_EX32(value, FRC_TIMER_CTRL, AUTOLOAD); + bool enable = FIELD_EX32(value, FRC_TIMER_CTRL, ENABLE); + if (prescaler == 2) { + prescaler = 16; + } else if (prescaler == 4) { + prescaler = 256; + } else { + prescaler = 1; + } + esp32_frc_timer_update_config(s, enable, level_int, autoload, prescaler); + break; + } + case A_FRC_TIMER_ALARM: { + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint32_t count_now = esp32_frc_timer_get_count(s, ns_now); + s->alarm_reg = value; + esp32_frc_timer_update_alarm(s, s->alarm_reg, count_now, ns_now); + break; + } + } +} + +static void esp32_frc_timer_set_apb_freq(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + Esp32FrcTimerState *s = ESP32_FRC_TIMER(opaque); + visit_type_uint32(v, name, &s->apb_freq, errp); + +} + +static const MemoryRegionOps esp32_frc_timer_ops = { + .read = esp32_frc_timer_read, + .write = esp32_frc_timer_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_frc_timer_reset(DeviceState *dev) +{ + Esp32FrcTimerState *s = ESP32_FRC_TIMER(dev); + + s->prescaler = 1; +} + +static void esp32_frc_timer_realize(DeviceState *dev, Error **errp) +{ +} + +static void esp32_frc_timer_init(Object *obj) +{ + Esp32FrcTimerState *s = ESP32_FRC_TIMER(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_frc_timer_ops, s, + TYPE_ESP32_FRC_TIMER, A_FRC_TIMER_ALARM + 4); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + + object_property_add(obj, "apb_freq", "uint32", + NULL, + esp32_frc_timer_set_apb_freq, + NULL, + obj); + + + timer_init_ns(&s->alarm_timer, QEMU_CLOCK_VIRTUAL, esp32_frc_timer_cb, s); + + s->apb_freq = 80000000; + s->count_mask = UINT32_MAX; + s->has_alarm = true; +} + +static Property esp32_frc_timer_properties[] = { + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_frc_timer_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_frc_timer_reset; + dc->realize = esp32_frc_timer_realize; + device_class_set_props(dc, esp32_frc_timer_properties); +} + +static const TypeInfo esp32_frc_timer_info = { + .name = TYPE_ESP32_FRC_TIMER, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32FrcTimerState), + .instance_init = esp32_frc_timer_init, + .class_init = esp32_frc_timer_class_init +}; + +static void esp32_frc_timer_register_types(void) +{ + type_register_static(&esp32_frc_timer_info); +} + +type_init(esp32_frc_timer_register_types) diff --git a/hw/timer/esp32_timg.c b/hw/timer/esp32_timg.c new file mode 100644 index 000000000000..8f29c62bbe94 --- /dev/null +++ b/hw/timer/esp32_timg.c @@ -0,0 +1,664 @@ +/* + * ESP32 "Timer Group" peripheral + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/registerfields.h" +#include "hw/boards.h" +#include "hw/timer/esp32_timg.h" + + +#define TIMG_REGFILE_SIZE 0x100 + +static uint64_t esp32_timg_timer_get_count(Esp32TimgTimerState *s, uint64_t ns_now); +static uint64_t esp32_timg_timer_count_to_ns(Esp32TimgTimerState *s, uint64_t count); +static void esp32_timg_timer_update_config(Esp32TimgTimerState *ts); +static void esp32_timg_timer_update_alarm(Esp32TimgTimerState *ts, uint64_t ns_now); +static void esp32_timg_timer_reload(Esp32TimgTimerState *ts, uint64_t ns_now); +static void esp32_timg_do_calibration(Esp32TimgState* s); +static void esp32_timg_int_update(Esp32TimgState *s); +static bool esp32_timg_wdt_protected(Esp32TimgWdtState *ws); +static void esp32_timg_wdt_update_config(Esp32TimgWdtState *ws); +static void esp32_timg_wdt_feed(Esp32TimgWdtState *ws); +static void esp32_timg_wdt_arm(Esp32TimgWdtState *ws, uint64_t ns_now); + + +#define TIMG_DEBUG_LOG(...) // qemu_log(__VA_ARGS__) + +static inline void set_low_word(uint64_t *dst, uint32_t word) +{ + *dst = (*dst & ~UINT32_MAX) | word; +} + +static inline void set_high_word(uint64_t *dst, uint32_t word) +{ + *dst = (*dst & UINT32_MAX) | (((uint64_t)word) << 32); +} + +static inline qemu_irq get_level_irq(Esp32TimgState* s, Esp32TimgInterruptType it) +{ + return s->irqs[it]; +} + +static inline qemu_irq get_edge_irq(Esp32TimgState* s, Esp32TimgInterruptType it) +{ + return s->irqs[TIMG_INT_MAX + it]; +} + + +static uint64_t esp32_timg_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32TimgState *s = ESP32_TIMG(opaque); + Esp32TimgTimerState *ts = NULL; + if (addr <= A_TIMG_T0LOAD) { + ts = &s->t0; + } else if (addr <= A_TIMG_T1LOAD) { + ts = &s->t1; + } else if (addr >= A_TIMG_LACTCONFIG && addr < A_TIMG_LACTLOAD) { + ts = &s->lact; + } + uint64_t r = 0; + switch (addr) { + case A_TIMG_T0CONFIG: + case A_TIMG_T1CONFIG: + case A_TIMG_LACTCONFIG: + r = ts->config_reg; + break; + case A_TIMG_T0LO: + case A_TIMG_T1LO: + case A_TIMG_LACTLO: + r = ts->last_val & UINT32_MAX; + break; + case A_TIMG_T0HI: + case A_TIMG_T1HI: + case A_TIMG_LACTHI: + r = ts->last_val >> 32; + break; + case A_TIMG_T0LOADLO: + case A_TIMG_T1LOADLO: + case A_TIMG_LACTLOADLO: + r = ts->load_val & UINT32_MAX; + break; + case A_TIMG_T0LOADHI: + case A_TIMG_T1LOADHI: + case A_TIMG_LACTLOADHI: + r = ts->load_val >> 32; + break; + case A_TIMG_T0ALARMLO: + case A_TIMG_T1ALARMLO: + case A_TIMG_LACTALARMLO: + r = ts->alarm_val & UINT32_MAX; + break; + case A_TIMG_T0ALARMHI: + case A_TIMG_T1ALARMHI: + case A_TIMG_LACTALARMHI: + r = ts->alarm_val >> 32; + break; + + case A_TIMG_WDTCONFIG0: + r = s->wdt.config0_reg; + break; + case A_TIMG_WDTCONFIG1: + r = FIELD_DP32(r, TIMG_WDTCONFIG1, PRESCALE, s->wdt.prescale); + break; + case A_TIMG_WDTCONFIG2: + case A_TIMG_WDTCONFIG3: + case A_TIMG_WDTCONFIG4: + case A_TIMG_WDTCONFIG5: { + int stage = (addr - A_TIMG_WDTCONFIG2) / 4; + r = s->wdt.timeout[stage]; + break; + } + case A_TIMG_WDTPROTECT: + r = s->wdt.protect_reg; + break; + + case A_TIMG_RTCCALICFG: + r = FIELD_DP32(r, TIMG_RTCCALICFG, START, s->rtc_cal_start); + r = FIELD_DP32(r, TIMG_RTCCALICFG, MAX, s->rtc_cal_max); + r = FIELD_DP32(r, TIMG_RTCCALICFG, RDY, s->rtc_cal_ready); + r = FIELD_DP32(r, TIMG_RTCCALICFG, CLK_SEL, s->rtc_cal_clk_sel); + break; + case A_TIMG_RTCCALICFG1: + r = FIELD_DP32(0, TIMG_RTCCALICFG1, VALUE, s->rtc_cal_value); + break; + + case A_TIMG_INT_ENA: + r = s->int_ena; + break; + case A_TIMG_INT_RAW: + r = s->int_raw; + break; + case A_TIMG_INT_ST: + r = s->int_ena & s->int_raw; + break; + } + return r; +} + +static void esp32_timg_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + Esp32TimgState *s = ESP32_TIMG(opaque); + Esp32TimgTimerState *ts = NULL; + if (addr <= A_TIMG_T0LOAD) { + ts = &s->t0; + } else if (addr <= A_TIMG_T1LOAD) { + ts = &s->t1; + } else if (addr >= A_TIMG_LACTCONFIG && addr <= A_TIMG_LACTLOAD) { + ts = &s->lact; + } + + switch (addr) { + case A_TIMG_T0CONFIG: + case A_TIMG_T1CONFIG: + case A_TIMG_LACTCONFIG: + ts->config_reg = value; + esp32_timg_timer_update_config(ts); + break; + case A_TIMG_T0UPDATE: + case A_TIMG_T1UPDATE: + case A_TIMG_LACTUPDATE: { + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ts->last_val = esp32_timg_timer_get_count(ts, ns_now); + break; + } + case A_TIMG_T0LOADLO: + case A_TIMG_T1LOADLO: + case A_TIMG_LACTLOADLO: + set_low_word(&ts->load_val, value); + break; + case A_TIMG_T0LOADHI: + case A_TIMG_T1LOADHI: + case A_TIMG_LACTLOADHI: + set_high_word(&ts->load_val, value); + break; + case A_TIMG_T0LOAD: + case A_TIMG_T1LOAD: + case A_TIMG_LACTLOAD: { + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + esp32_timg_timer_reload(ts, ns_now); + break; + } + case A_TIMG_T0ALARMLO: + case A_TIMG_T1ALARMLO: + case A_TIMG_LACTALARMLO: + set_low_word(&ts->alarm_val, value); + break; + case A_TIMG_T0ALARMHI: + case A_TIMG_T1ALARMHI: + case A_TIMG_LACTALARMHI: + set_high_word(&ts->alarm_val, value); + break; + + case A_TIMG_WDTCONFIG0: + if (!esp32_timg_wdt_protected(&s->wdt)) { + s->wdt.config0_reg = value; + esp32_timg_wdt_update_config(&s->wdt); + } else { + TIMG_DEBUG_LOG("failed to write TIMG_WDTCONFIG0, write protected (0x%08x)\n", s->wdt.protect_reg); + } + break; + case A_TIMG_WDTCONFIG1: + if (!esp32_timg_wdt_protected(&s->wdt)) { + s->wdt.config1_reg = value; + esp32_timg_wdt_update_config(&s->wdt); + } + break; + case A_TIMG_WDTCONFIG2: + case A_TIMG_WDTCONFIG3: + case A_TIMG_WDTCONFIG4: + case A_TIMG_WDTCONFIG5: { + if (!esp32_timg_wdt_protected(&s->wdt)) { + int stage = (addr - A_TIMG_WDTCONFIG2) / 4; + s->wdt.timeout[stage] = value; + } + break; + } + case A_TIMG_WDTFEED: + if (!esp32_timg_wdt_protected(&s->wdt)) { + esp32_timg_wdt_feed(&s->wdt); + } + break; + case A_TIMG_WDTPROTECT: + s->wdt.protect_reg = value; + break; + + + case A_TIMG_RTCCALICFG: + s->rtc_cal_start = FIELD_EX32(value, TIMG_RTCCALICFG, START); + s->rtc_cal_ready = FIELD_EX32(value, TIMG_RTCCALICFG, RDY); + s->rtc_cal_clk_sel = FIELD_EX32(value, TIMG_RTCCALICFG, CLK_SEL); + s->rtc_cal_max = FIELD_EX32(value, TIMG_RTCCALICFG, MAX); + esp32_timg_do_calibration(s); + break; + + case A_TIMG_INT_ENA: + s->int_ena = value; + esp32_timg_int_update(s); + break; + case A_TIMG_INT_CLR: + s->int_raw &= ~value; + esp32_timg_int_update(s); + break; + } +} + +static const MemoryRegionOps esp32_timg_ops = { + .read = esp32_timg_read, + .write = esp32_timg_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_timg_timer_reset(Esp32TimgTimerState* ts) +{ + timer_del(&ts->alarm_timer); + ts->config_reg = R_TIMG_T0CONFIG_INCREASE_MASK + | R_TIMG_T0CONFIG_AUTORELOAD_MASK + | (1 << R_TIMG_T0CONFIG_DIVIDER_SHIFT); + ts->alarm_val = 0; + ts->load_val = 0; + ts->count_base = 0; + ts->ns_base = 0; + esp32_timg_timer_update_config(ts); +} + +static void esp32_timg_wdt_reset(Esp32TimgWdtState* ws) +{ + timer_del(&ws->stage_timer); + + ws->config0_reg = 0x0004c000; + ws->config1_reg = 0x00010000; + ws->timeout[0] = 0x018cba80; + ws->timeout[1] = 0x07ffffff; + ws->timeout[2] = 0x000fffff; + ws->timeout[3] = 0x000fffff; + ws->protect_reg = ESP32_TIMG_WDT_PROTECT_WORD; + + if (ws->parent->wdt_en_at_reset) { + /* On reset, stage0 is configured as system reset, however this is done by + * hardware state, not in config0 register. Emulate this by temporarily setting STG0 field here. + */ + ws->config0_reg |= (WDT_MODE_SYSRESET << R_TIMG_WDTCONFIG0_STG0_SHIFT); + } + esp32_timg_wdt_update_config(ws); + if (ws->parent->wdt_en_at_reset) { + ws->config0_reg &= (~R_TIMG_WDTCONFIG0_STG0_MASK); + } +} + +static void esp32_timg_reset(DeviceState *dev) +{ + Esp32TimgState *s = ESP32_TIMG(dev); + s->rtc_cal_max = 1; + s->rtc_cal_clk_sel = ESP32_TIMG_CAL_8MD256; + s->rtc_cal_ready = 0; + s->rtc_cal_start = 1; + esp32_timg_do_calibration(s); + + esp32_timg_timer_reset(&s->t0); + esp32_timg_timer_reset(&s->t1); + esp32_timg_timer_reset(&s->lact); + esp32_timg_wdt_reset(&s->wdt); +} + +static void esp32_timg_set_apb_freq(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + Esp32TimgState *s = ESP32_TIMG(opaque); + visit_type_uint32(v, name, &s->apb_freq_hz, errp); + TIMG_DEBUG_LOG("%s: TG%d apb_freq_hz=%d\n", __func__, s->id, s->apb_freq_hz); +} + +static void esp32_timg_do_calibration(Esp32TimgState* s) +{ + uint32_t cal_clk_freq; + if (s->rtc_cal_clk_sel == ESP32_TIMG_CAL_RTC_MUX) { + cal_clk_freq = s->rtc_slow_freq_hz; + } else if (s->rtc_cal_clk_sel == ESP32_TIMG_CAL_32K_XTAL) { + cal_clk_freq = 32768; + } else { + cal_clk_freq = 8000000 / 256; + } + + s->rtc_cal_value = muldiv64(s->xtal_freq_hz, s->rtc_cal_max, cal_clk_freq); + s->rtc_cal_ready = true; +} + +static void esp32_timg_timer_cb(void *opaque) +{ + Esp32TimgTimerState *ts = (Esp32TimgTimerState*) opaque; + Esp32TimgState *s = ts->parent; + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + + TIMG_DEBUG_LOG("%s: TG%d ns=0x%llx\n", __func__, s->id, ns_now); + uint32_t int_mask = 1 << (ts->int_type); + + if (ts->level_int_en) { + s->int_raw |= int_mask; + if (s->int_ena & int_mask) { + qemu_irq_raise(get_level_irq(s, ts->int_type)); + } + } + + if (ts->edge_int_en) { + if (s->int_ena & int_mask) { + qemu_irq_pulse(get_edge_irq(s, ts->int_type)); + } + } + + ts->alarm = false; + + if (ts->autoreload) { + esp32_timg_timer_reload(ts, ns_now); + } else { + /* ignore overflow modulo 64 bits */ + timer_del(&ts->alarm_timer); + } +} + +static void esp32_timg_int_update_inttype(Esp32TimgState *s, uint32_t int_st, Esp32TimgInterruptType it) +{ + if (int_st & (1 << it)) { + qemu_irq_raise(get_level_irq(s, it)); + } else { + qemu_irq_lower(get_level_irq(s, it)); + } +} + +static void esp32_timg_int_update(Esp32TimgState *s) +{ + uint32_t int_st = s->int_ena & s->int_raw; + esp32_timg_int_update_inttype(s, int_st, TIMG_T0_INT); + esp32_timg_int_update_inttype(s, int_st, TIMG_T1_INT); + esp32_timg_int_update_inttype(s, int_st, TIMG_WDT_INT); + esp32_timg_int_update_inttype(s, int_st, TIMG_LACT_INT); +} + +static int esp32_timg_timer_direction(Esp32TimgTimerState *s) +{ + if (!s->en) { + return 0; + } + if (s->inc) { + return 1; + } else { + return -1; + } +} + +static uint64_t esp32_timg_timer_get_count(Esp32TimgTimerState *s, uint64_t ns_now) +{ + if (!s->en) { + return s->count_base; + } + uint64_t ns_from_base = ns_now - s->ns_base; + uint64_t ticks_from_base = muldiv64(ns_from_base, s->parent->apb_freq_hz / 1000000, 1000 * s->divider); + uint64_t count = esp32_timg_timer_direction(s) * ticks_from_base + s->count_base; + return count; +} + +static uint64_t esp32_timg_timer_count_to_ns(Esp32TimgTimerState *s, uint64_t count) +{ + return muldiv64(count, 1000 * s->divider, s->parent->apb_freq_hz / 1000000); +} + +static uint32_t esp32_timg_timer_div_from_reg(uint32_t reg_val) +{ + if (reg_val == 0) { + return 65536; + } + if (reg_val == 1 || reg_val == 2) { + return 2; + } + return reg_val; +} + +static void esp32_timg_timer_update_config(Esp32TimgTimerState *ts) +{ + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ts->count_base = esp32_timg_timer_get_count(ts, ns_now); + ts->ns_base = ns_now; + + ts->en = FIELD_EX32(ts->config_reg, TIMG_T0CONFIG, EN); + ts->inc = FIELD_EX32(ts->config_reg, TIMG_T0CONFIG, INCREASE); + ts->autoreload = FIELD_EX32(ts->config_reg, TIMG_T0CONFIG, AUTORELOAD); + ts->divider = esp32_timg_timer_div_from_reg(FIELD_EX32(ts->config_reg, TIMG_T0CONFIG, DIVIDER)); + ts->edge_int_en = FIELD_EX32(ts->config_reg, TIMG_T0CONFIG, EDGE_INT); + ts->level_int_en = FIELD_EX32(ts->config_reg, TIMG_T0CONFIG, LEVEL_INT); + ts->alarm = FIELD_EX32(ts->config_reg, TIMG_T0CONFIG, ALARM); + + TIMG_DEBUG_LOG("%s: TG%d base=0x%llx ns=0x%llx en=%d inc=%d autoreload=%d div=%d li=%d ei=%d alarm=%d\n", __func__, ts->parent->id, + ts->count_base, ts->ns_base, ts->en, ts->inc, ts->autoreload, ts->divider, + ts->level_int_en, ts->edge_int_en, ts->alarm); + + esp32_timg_timer_update_alarm(ts, ns_now); +} + +static void esp32_timg_timer_reload(Esp32TimgTimerState *ts, uint64_t ns_now) +{ + timer_del(&ts->alarm_timer); + + ts->ns_base = ns_now; + ts->count_base = ts->load_val; + + TIMG_DEBUG_LOG("%s: TG%d base=0x%llx ns=0x%llx\n", __func__, ts->parent->id, + ts->count_base, ts->ns_base); + + esp32_timg_timer_update_alarm(ts, ns_now); +} + +static void esp32_timg_timer_update_alarm(Esp32TimgTimerState *ts, uint64_t ns_now) +{ + if (!ts->en || !ts->alarm) { + timer_del(&ts->alarm_timer); + return; + } + + int64_t count_to_alarm = ((int64_t) ts->alarm_val - (int64_t) ts->count_base) + * esp32_timg_timer_direction(ts); + if (count_to_alarm <= 0) { + /* ignore overflow modulo 64 bits */ + timer_del(&ts->alarm_timer); + return; + } + + uint64_t ns_to_alarm = esp32_timg_timer_count_to_ns(ts, count_to_alarm); + + TIMG_DEBUG_LOG("%s: TG%d count_to_alarm=0x%llx ns_to_alarm=0x%llx\n", __func__, ts->parent->id, + count_to_alarm, ns_to_alarm); + + timer_mod_anticipate_ns(&ts->alarm_timer, ns_now + ns_to_alarm); +} + +static bool esp32_timg_wdt_protected(Esp32TimgWdtState *ws) +{ + return ws->protect_reg != ESP32_TIMG_WDT_PROTECT_WORD; +} + +static uint64_t esp32_timg_wdt_get_count(Esp32TimgWdtState *ws, uint64_t ns_now) +{ + if (!ws->en) { + return ws->count_base; + } + uint64_t ns_from_base = ns_now - ws->ns_base; + uint64_t ticks_from_base = muldiv64(ns_from_base, ws->parent->apb_freq_hz / 1000000, 1000 * MAX(ws->prescale, 1)); + uint64_t count = ticks_from_base + ws->count_base; + return count; +} + +static void esp32_timg_wdt_update_config(Esp32TimgWdtState *ws) +{ + Esp32TimgState *s = ws->parent; + + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ws->count_base = esp32_timg_wdt_get_count(ws, ns_now); + ws->ns_base = ns_now; + + bool old_en = ws->en; + ws->en = FIELD_EX32(ws->config0_reg, TIMG_WDTCONFIG0, EN); + ws->mode[0] = FIELD_EX32(ws->config0_reg, TIMG_WDTCONFIG0, STG0); + ws->mode[1] = FIELD_EX32(ws->config0_reg, TIMG_WDTCONFIG0, STG1); + ws->mode[2] = FIELD_EX32(ws->config0_reg, TIMG_WDTCONFIG0, STG2); + ws->mode[3] = FIELD_EX32(ws->config0_reg, TIMG_WDTCONFIG0, STG3); + ws->edge_int_en = FIELD_EX32(ws->config0_reg, TIMG_WDTCONFIG0, EDGE_INT); + ws->level_int_en = FIELD_EX32(ws->config0_reg, TIMG_WDTCONFIG0, LEVEL_INT); + ws->flashboot_en = FIELD_EX32(ws->config0_reg, TIMG_WDTCONFIG0, FLASHBOOT_MODE_EN); + + ws->prescale = FIELD_EX32(ws->config1_reg, TIMG_WDTCONFIG1, PRESCALE); + + if (ws->en && !old_en) { + ws->cur_stage = 0; + ws->count_base = 0; + } else if (!ws->en && old_en) { + qemu_irq_lower(get_level_irq(s, TIMG_WDT_INT)); + } + + TIMG_DEBUG_LOG("%s: TG%d config 0x%08x prescale=0x%08x en=%d fb_en=%d level_int_en=%d\n", __func__, ws->parent->id, + ws->config0_reg, ws->prescale, ws->en, ws->flashboot_en, ws->level_int_en); + esp32_timg_wdt_arm(ws, ns_now); +} + +static void esp32_timg_wdt_feed(Esp32TimgWdtState *ws) +{ + TIMG_DEBUG_LOG("%s TG%d\n", __func__, ws->parent->id); + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ws->cur_stage = 0; + ws->ns_base = ns_now; + ws->count_base = 0; + esp32_timg_wdt_arm(ws, ns_now); +} + +static void esp32_timg_wdt_arm(Esp32TimgWdtState *ws, uint64_t ns_now) +{ + timer_del(&ws->stage_timer); + + if (ws->parent->wdt_disable || !(ws->en || (ws->flashboot_en && ws->parent->flash_boot_mode))) { + return; + } + + uint32_t stage_timeout = ws->timeout[ws->cur_stage]; + uint32_t cur_count = esp32_timg_wdt_get_count(ws, ns_now); + uint32_t count_to_timeout = stage_timeout - cur_count; + uint64_t ns_to_timeout = muldiv64(count_to_timeout, 1000 * ws->prescale, ws->parent->apb_freq_hz / 1000000); + TIMG_DEBUG_LOG("%s: TG%d ns=0x%08llx stage %d count=0x%08x count_to_timeout=0x%08x ns_to_timeout=0x%08llx\n", + __func__, ws->parent->id, ns_now, ws->cur_stage, cur_count, count_to_timeout, ns_to_timeout); + timer_mod_anticipate_ns(&ws->stage_timer, ns_now + ns_to_timeout); +} + +static void esp32_timg_wdt_cb(void *opaque) +{ + Esp32TimgWdtState *ws = (Esp32TimgWdtState*) opaque; + Esp32TimgState *s = ws->parent; + Esp32TimgWdtStageMode mode = ws->mode[ws->cur_stage]; + TIMG_DEBUG_LOG("%s: TG%d stage %d timeout mode %d\n", __func__, s->id, ws->cur_stage, mode); + if (mode == WDT_MODE_INT) { + uint32_t mask = 1 << TIMG_WDT_INT; + if (ws->level_int_en) { + s->int_raw |= mask; + if (true) { /* should be checking s->int_ena & mask, but ESP32 seems to raise interrupt regardless? */ + qemu_irq_raise(get_level_irq(s, TIMG_WDT_INT)); + } + } + if (ws->edge_int_en) { + if (s->int_ena & mask) { + qemu_irq_pulse(get_edge_irq(s, TIMG_WDT_INT)); + } + } + } else if (mode == WDT_MODE_CPURESET) { + qemu_irq_pulse(s->wdt_cpu_reset_req); + } else if (mode == WDT_MODE_SYSRESET) { + qemu_irq_pulse(s->wdt_sys_reset_req); + } + + int next_stage = (ws->cur_stage + 1) % ESP32_TIMG_WDT_STAGE_COUNT; + uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ws->count_base = 0; + ws->cur_stage = next_stage; + ws->ns_base = ns_now; + esp32_timg_wdt_arm(ws, ns_now); +} + +static void esp32_timg_realize(DeviceState *dev, Error **errp) +{ +} + +static void esp32_timg_timer_init(Esp32TimgState *s, Esp32TimgTimerState *ts, Esp32TimgInterruptType int_type) { + ts->parent = s; + timer_init_ns(&ts->alarm_timer, QEMU_CLOCK_VIRTUAL, esp32_timg_timer_cb, ts); + ts->int_type = int_type; +} + +static void esp32_timg_init(Object *obj) +{ + Esp32TimgState *s = ESP32_TIMG(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_timg_ops, s, + TYPE_ESP32_TIMG, TIMG_REGFILE_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + qdev_init_gpio_out_named(DEVICE(sbd), s->irqs, SYSBUS_DEVICE_GPIO_IRQ, 2*TIMG_INT_MAX); + + object_property_add(obj, "apb_freq", "uint32", + NULL, + esp32_timg_set_apb_freq, + NULL, + obj); + + s->rtc_slow_freq_hz = 150000; + s->xtal_freq_hz = 40000000; + s->apb_freq_hz = 40000000; + + esp32_timg_timer_init(s, &s->t0, TIMG_T0_INT); + esp32_timg_timer_init(s, &s->t1, TIMG_T1_INT); + esp32_timg_timer_init(s, &s->lact, TIMG_LACT_INT); + + s->wdt.parent = s; + timer_init_ns(&s->wdt.stage_timer, QEMU_CLOCK_VIRTUAL, esp32_timg_wdt_cb, &s->wdt); + qdev_init_gpio_out_named(DEVICE(sbd), &s->wdt_cpu_reset_req, ESP32_TIMG_WDT_CPU_RESET_GPIO, 1); + qdev_init_gpio_out_named(DEVICE(sbd), &s->wdt_sys_reset_req, ESP32_TIMG_WDT_SYS_RESET_GPIO, 1); +} + +static Property esp32_timg_properties[] = { + DEFINE_PROP_BOOL("wdt_disable", Esp32TimgState, wdt_disable, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_timg_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_timg_reset; + dc->realize = esp32_timg_realize; + device_class_set_props(dc, esp32_timg_properties); +} + +static const TypeInfo esp32_timg_info = { + .name = TYPE_ESP32_TIMG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32TimgState), + .instance_init = esp32_timg_init, + .class_init = esp32_timg_class_init +}; + +static void esp32_timg_register_types(void) +{ + type_register_static(&esp32_timg_info); +} + +type_init(esp32_timg_register_types) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 03092e2cebf4..e6da9aa6af7a 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -34,6 +34,7 @@ softmmu_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('sse-timer.c')) softmmu_ss.add(when: 'CONFIG_STELLARIS_GPTM', if_true: files('stellaris-gptm.c')) softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c')) softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) +softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_frc_timer.c', 'esp32_timg.c')) specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c')) diff --git a/hw/timer/trace-events b/hw/timer/trace-events index 3eccef83858f..4f5bb70fba39 100644 --- a/hw/timer/trace-events +++ b/hw/timer/trace-events @@ -77,6 +77,14 @@ avr_timer16_interrupt_overflow(const char *reason) "overflow: %s" avr_timer16_next_alarm(uint64_t delay_ns) "next alarm: %" PRIu64 " ns from now" avr_timer16_clksrc_update(uint64_t freq_hz, uint64_t period_ns, uint64_t delay_s) "timer frequency: %" PRIu64 " Hz, period: %" PRIu64 " ns (%" PRId64 " us)" + +# esp32_frc_timer.c +esp32_frc_timer_read(uint64_t addr, uint32_t value) "read addr 0x%" PRIx64 " data 0x%" PRIx32 +esp32_frc_timer_write(uint64_t addr, uint32_t value) "write addr 0x%" PRIx64 " data 0x%" PRIx32 +esp32_frc_timer_update_config(uint64_t ns_now, uint32_t count_now, int enable, int level_int, int autoload, uint32_t prescaler) "update now: %" PRIu64 " count: 0x%" PRIx32 " enable: %d level_int: %d autoload: %d prescaler: %" PRIu32 +esp32_frc_timer_cb(uint64_t ns_now, uint32_t count_now) "alarm now: %" PRIu64 " count: 0x%" PRIx32 +esp32_frc_timer_update_alarm(uint64_t ns_now, uint32_t count_now, uint64_t ticks, uint64_t ns_to_alarm) "set alarm now: %" PRIu64 " count: 0x%" PRIx32 " ticks: %" PRIu64 " ns_to_alarm: %" PRIu64 + # sse_counter.c sse_counter_control_read(uint64_t offset, uint64_t data, unsigned size) "SSE system counter control frame read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" sse_counter_control_write(uint64_t offset, uint64_t data, unsigned size) "SSE system counter control framen write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" diff --git a/include/hw/timer/esp32_frc_timer.h b/include/hw/timer/esp32_frc_timer.h new file mode 100644 index 000000000000..cdb09b4cf0d7 --- /dev/null +++ b/include/hw/timer/esp32_frc_timer.h @@ -0,0 +1,49 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_reg.h" + +#define TYPE_ESP32_FRC_TIMER "timer.esp32.frc" +#define ESP32_FRC_TIMER(obj) OBJECT_CHECK(Esp32FrcTimerState, (obj), TYPE_ESP32_FRC_TIMER) + +typedef struct Esp32FrcTimerState { + /* private */ + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq irq; + QEMUTimer alarm_timer; + + /* properties */ + uint32_t apb_freq; + bool has_alarm; + uint32_t count_mask; + + /* state */ + uint32_t count_base; + uint64_t ns_base; + bool level_int_status; + + /* registers */ + uint32_t load_reg; + bool enable; + bool autoload; + uint32_t prescaler; + bool level_int; + uint32_t alarm_reg; +} Esp32FrcTimerState; + +REG32(FRC_TIMER_LOAD, 0x00) +REG32(FRC_TIMER_COUNT, 0x04) +REG32(FRC_TIMER_CTRL, 0x08) + FIELD(FRC_TIMER_CTRL, LEVEL_INT, 0, 1) + FIELD(FRC_TIMER_CTRL, PRESCALER, 1, 3) + FIELD(FRC_TIMER_CTRL, AUTOLOAD, 6, 1) + FIELD(FRC_TIMER_CTRL, ENABLE, 7, 1) + FIELD(FRC_TIMER_CTRL, STATUS, 8, 1) +REG32(FRC_TIMER_INT_CLR, 0x0c) +REG32(FRC_TIMER_ALARM, 0x10) + +#define ESP32_FRC_TIMER_STRIDE 0x20 diff --git a/include/hw/timer/esp32_timg.h b/include/hw/timer/esp32_timg.h new file mode 100644 index 000000000000..dbf554ae120b --- /dev/null +++ b/include/hw/timer/esp32_timg.h @@ -0,0 +1,217 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" + +#define TYPE_ESP32_TIMG "timer.esp32.timg" +#define ESP32_TIMG(obj) OBJECT_CHECK(Esp32TimgState, (obj), TYPE_ESP32_TIMG) + +#define ESP32_TIMG_WDT_STAGE_COUNT 4 + +typedef enum Esp32TimgCalClkSel { + ESP32_TIMG_CAL_RTC_MUX = 0, + ESP32_TIMG_CAL_8MD256 = 1, + ESP32_TIMG_CAL_32K_XTAL = 2 +} Esp32TimgCalClkSel; + +typedef enum Esp32TimgInterruptType { + TIMG_T0_INT, + TIMG_T1_INT, + TIMG_WDT_INT, + TIMG_LACT_INT, + TIMG_INT_MAX +} Esp32TimgInterruptType; + +typedef struct Esp32TimgState Esp32TimgState; + +typedef struct Esp32TimgTimerState { + Esp32TimgState *parent; + uint32_t config_reg; + int divider; + bool en; + bool autoreload; + bool inc; + bool edge_int_en; + bool level_int_en; + bool alarm; + uint64_t alarm_val; + uint64_t load_val; + uint64_t count_base; + uint64_t last_val; + uint64_t ns_base; + Esp32TimgInterruptType int_type; + QEMUTimer alarm_timer; +} Esp32TimgTimerState; + +typedef enum Esp32TimgWdtStageMode { + WDT_MODE_OFF = 0, + WDT_MODE_INT = 1, + WDT_MODE_CPURESET = 2, + WDT_MODE_SYSRESET = 3 +} Esp32TimgWdtStageMode; + +typedef struct Esp32TimgWdtState { + Esp32TimgState *parent; + uint32_t config0_reg; + uint32_t config1_reg; + bool en; + bool flashboot_en; + bool level_int_en; + bool edge_int_en; + int prescale; + Esp32TimgWdtStageMode mode[ESP32_TIMG_WDT_STAGE_COUNT]; + int timeout[ESP32_TIMG_WDT_STAGE_COUNT]; + uint32_t count_base; + uint64_t ns_base; + int cur_stage; + uint32_t protect_reg; + QEMUTimer stage_timer; +} Esp32TimgWdtState; + +typedef struct Esp32TimgState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + int id; + qemu_irq irqs[2*TIMG_INT_MAX]; + qemu_irq wdt_cpu_reset_req; + qemu_irq wdt_sys_reset_req; + + Esp32TimgTimerState t0; + Esp32TimgTimerState t1; + Esp32TimgTimerState lact; + Esp32TimgWdtState wdt; + + uint32_t int_ena; + uint32_t int_raw; + + uint32_t rtc_slow_freq_hz; + uint32_t xtal_freq_hz; + uint32_t apb_freq_hz; + bool flash_boot_mode; + bool wdt_en_at_reset; + bool wdt_disable; + + bool rtc_cal_start; + bool rtc_cal_ready; + Esp32TimgCalClkSel rtc_cal_clk_sel; + uint32_t rtc_cal_max; + uint32_t rtc_cal_value; +} Esp32TimgState; + +#define ESP32_TIMG_WDT_CPU_RESET_GPIO "mwdt-cpu-reset" +#define ESP32_TIMG_WDT_SYS_RESET_GPIO "mwdt-sys-reset" + +#define RTC_CLK_CAL_FRACT 19 +#define RTC_CLK_CAL_FACTOR (1 << RTC_CLK_CAL_FRACT) + +REG32(TIMG_T0CONFIG, 0x00) + FIELD(TIMG_T0CONFIG, EN, 31, 1) + FIELD(TIMG_T0CONFIG, INCREASE, 30, 1) + FIELD(TIMG_T0CONFIG, AUTORELOAD, 29, 1) + FIELD(TIMG_T0CONFIG, DIVIDER, 13, 16) + FIELD(TIMG_T0CONFIG, EDGE_INT, 12, 1) + FIELD(TIMG_T0CONFIG, LEVEL_INT, 11, 1) + FIELD(TIMG_T0CONFIG, ALARM, 10, 1) + +REG32(TIMG_T0LO, 0x04) +REG32(TIMG_T0HI, 0x08) +REG32(TIMG_T0UPDATE, 0x0c) +REG32(TIMG_T0ALARMLO, 0x10) +REG32(TIMG_T0ALARMHI, 0x14) +REG32(TIMG_T0LOADLO, 0x18) +REG32(TIMG_T0LOADHI, 0x1c) +REG32(TIMG_T0LOAD, 0x20) + +REG32(TIMG_T1CONFIG, 0x24) + FIELD(TIMG_T1CONFIG, EN, 31, 1) + FIELD(TIMG_T1CONFIG, INCREASE, 30, 1) + FIELD(TIMG_T1CONFIG, AUTORELOAD, 29, 1) + FIELD(TIMG_T1CONFIG, DIVIDER, 13, 16) + FIELD(TIMG_T1CONFIG, EDGE_INT, 12, 1) + FIELD(TIMG_T1CONFIG, LEVEL_INT, 11, 1) + FIELD(TIMG_T1CONFIG, ALARM, 10, 1) + +REG32(TIMG_T1LO, 0x28) +REG32(TIMG_T1HI, 0x2c) +REG32(TIMG_T1UPDATE, 0x30) +REG32(TIMG_T1ALARMLO, 0x34) +REG32(TIMG_T1ALARMHI, 0x38) +REG32(TIMG_T1LOADLO, 0x3c) +REG32(TIMG_T1LOADHI, 0x40) +REG32(TIMG_T1LOAD, 0x44) + +REG32(TIMG_WDTCONFIG0, 0x48) + FIELD(TIMG_WDTCONFIG0, EN, 31, 1) + FIELD(TIMG_WDTCONFIG0, STG0, 29, 2) + FIELD(TIMG_WDTCONFIG0, STG1, 27, 2) + FIELD(TIMG_WDTCONFIG0, STG2, 25, 2) + FIELD(TIMG_WDTCONFIG0, STG3, 23, 2) + FIELD(TIMG_WDTCONFIG0, EDGE_INT, 22, 1) + FIELD(TIMG_WDTCONFIG0, LEVEL_INT, 21, 1) + FIELD(TIMG_WDTCONFIG0, FLASHBOOT_MODE_EN, 14, 1) +REG32(TIMG_WDTCONFIG1, 0x4c) + FIELD(TIMG_WDTCONFIG1, PRESCALE, 16, 16) +REG32(TIMG_WDTCONFIG2, 0x50) +REG32(TIMG_WDTCONFIG3, 0x54) +REG32(TIMG_WDTCONFIG4, 0x58) +REG32(TIMG_WDTCONFIG5, 0x5c) +REG32(TIMG_WDTFEED, 0x60) + FIELD(TIMG_WDTFEED, FEED, 31, 1) +REG32(TIMG_WDTPROTECT, 0x64) + + +REG32(TIMG_RTCCALICFG, 0x68) + FIELD(TIMG_RTCCALICFG, START, 31, 1) + FIELD(TIMG_RTCCALICFG, MAX, 16, 15) + FIELD(TIMG_RTCCALICFG, RDY, 15, 1) + FIELD(TIMG_RTCCALICFG, CLK_SEL, 13, 2) + FIELD(TIMG_RTCCALICFG, START_CYCLING, 12, 1) + +REG32(TIMG_RTCCALICFG1, 0x6c) + FIELD(TIMG_RTCCALICFG1, VALUE, 7, 25) + +REG32(TIMG_LACTCONFIG, 0x70) + FIELD(TIMG_LACTCONFIG, EN, 31, 1) + FIELD(TIMG_LACTCONFIG, INCREASE, 30, 1) + FIELD(TIMG_LACTCONFIG, AUTORELOAD, 29, 1) + FIELD(TIMG_LACTCONFIG, DIVIDER, 13, 16) + FIELD(TIMG_LACTCONFIG, EDGE_INT, 12, 1) + FIELD(TIMG_LACTCONFIG, LEVEL_INT, 11, 1) + FIELD(TIMG_LACTCONFIG, ALARM, 10, 1) +REG32(TIMG_LACTRTC, 0x74) + FIELD(TIMG_LACTRTC, STEP_LEN, 6, 26) +REG32(TIMG_LACTLO, 0x78) +REG32(TIMG_LACTHI, 0x7c) +REG32(TIMG_LACTUPDATE, 0x80) +REG32(TIMG_LACTALARMLO, 0x84) +REG32(TIMG_LACTALARMHI, 0x88) +REG32(TIMG_LACTLOADLO, 0x8c) +REG32(TIMG_LACTLOADHI, 0x90) +REG32(TIMG_LACTLOAD, 0x94) + +REG32(TIMG_INT_ENA, 0x98) + FIELD(TIMG_INT_ENA, LACT, 3, 1) + FIELD(TIMG_INT_ENA, WDT, 2, 1) + FIELD(TIMG_INT_ENA, T1, 1, 1) + FIELD(TIMG_INT_ENA, T0, 0, 1) + +REG32(TIMG_INT_RAW, 0x9c) + FIELD(TIMG_INT_RAW, LACT, 3, 1) + FIELD(TIMG_INT_RAW, WDT, 2, 1) + FIELD(TIMG_INT_RAW, T1, 1, 1) + FIELD(TIMG_INT_RAW, T0, 0, 1) + +REG32(TIMG_INT_ST, 0xa0) + FIELD(TIMG_INT_ST, LACT, 3, 1) + FIELD(TIMG_INT_ST, WDT, 2, 1) + FIELD(TIMG_INT_ST, T1, 1, 1) + FIELD(TIMG_INT_ST, T0, 0, 1) + +REG32(TIMG_INT_CLR, 0xa4) + FIELD(TIMG_INT_CLR, LACT, 3, 1) + FIELD(TIMG_INT_CLR, WDT, 2, 1) + FIELD(TIMG_INT_CLR, T1, 1, 1) + FIELD(TIMG_INT_CLR, T0, 0, 1) + +#define ESP32_TIMG_WDT_PROTECT_WORD 0x50D83AA1 From 3fb8cbfec299a737877925c2bbf4ceeb105dd231 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sun, 25 Jul 2021 17:39:35 +0200 Subject: [PATCH 25/56] hw/sd: add emulation of designware sdmmc controller --- hw/sd/Kconfig | 4 + hw/sd/dwc_sdmmc.c | 586 ++++++++++++++++++++++++++++++++++++++ hw/sd/meson.build | 1 + include/hw/sd/dwc_sdmmc.h | 60 ++++ 4 files changed, 651 insertions(+) create mode 100644 hw/sd/dwc_sdmmc.c create mode 100644 include/hw/sd/dwc_sdmmc.h diff --git a/hw/sd/Kconfig b/hw/sd/Kconfig index 633b9afec915..684e6bd6e797 100644 --- a/hw/sd/Kconfig +++ b/hw/sd/Kconfig @@ -23,3 +23,7 @@ config SDHCI_PCI config CADENCE_SDHCI bool select SDHCI + +config DWC_SDMMC + bool + select SD diff --git a/hw/sd/dwc_sdmmc.c b/hw/sd/dwc_sdmmc.c new file mode 100644 index 000000000000..9b9cf1a7726a --- /dev/null +++ b/hw/sd/dwc_sdmmc.c @@ -0,0 +1,586 @@ +/* + * Designware SD/MMC controller emulation + * + * Copyright (c) 2021 Espressif Systems (Shanghai) Co. Ltd. + * + * Based on Allwinner SD Host controller emulation (allwinner-sdhost.c), + * Copyright (C) 2019 Niek Linnenbank + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/sd/dwc_sdmmc.h" +#include "qapi/error.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "sysemu/blockdev.h" +#include "sysemu/dma.h" +#include "hw/qdev-properties.h" +#include "hw/irq.h" +#include "migration/vmstate.h" +#include "trace.h" +#include "qom/object.h" +#include "hw/registerfields.h" + +/* This implementation is simplified: + * - Only DMA mode is implemented, with 32-bit DMA descriptor pointers. + * - FIFO is not implemented. + * - No error interrupts or conditions are generated. + * - Boot mode is not implemented. + * - Clock settings are ignored. + * + * The hardware seems to work in a manner very similar to Allwinner SD Host controller (allwinner-sdhost.c), + * notable exceptions being: + * - slightly different IDMAC descriptor structure + * - slightly different interrupt handling logic + * It is possible that Allwinner SD Host is based on an earlier version of Designware SD/MMC IP, + * or is heavily inspired by it. + */ + +#ifdef DWC_SDMMC_DEBUG +#define DEBUG(...) qemu_log(__VA_ARGS__) +#else +#define DEBUG(...) +#endif + +typedef struct { + uint32_t reserved1: 1; + uint32_t disable_int_on_completion: 1; + uint32_t last_descriptor: 1; + uint32_t first_descriptor: 1; + uint32_t second_address_chained: 1; + uint32_t end_of_ring: 1; + uint32_t reserved2: 24; + uint32_t card_error_summary: 1; + uint32_t owned_by_idmac: 1; + uint32_t buffer1_size: 13; + uint32_t buffer2_size: 13; + uint32_t reserved3: 6; + uint32_t buffer1_ptr; + union { + uint32_t buffer2_ptr; + uint32_t next_desc_ptr; + }; +} sdmmc_desc_t; + +typedef struct { + uint32_t cmd_index: 6; ///< Command index + uint32_t response_expect: 1; ///< set if response is expected + uint32_t response_long: 1; ///< 0: short response expected, 1: long response expected + uint32_t check_response_crc: 1; ///< set if controller should check response CRC + uint32_t data_expected: 1; ///< 0: no data expected, 1: data expected + uint32_t rw: 1; ///< 0: read from card, 1: write to card (don't care if no data expected) + uint32_t stream_mode: 1; ///< 0: block transfer, 1: stream transfer (don't care if no data expected) + uint32_t send_auto_stop: 1; ///< set to send stop at the end of the transfer + uint32_t wait_complete: 1; ///< 0: send command at once, 1: wait for previous command to complete + uint32_t stop_abort_cmd: 1; ///< set if this is a stop or abort command intended to stop current transfer + uint32_t send_init: 1; ///< set to send init sequence (80 clocks of 1) + uint32_t card_num: 5; ///< card number + uint32_t update_clk_reg: 1; ///< 0: normal command, 1: don't send command, just update clock registers + uint32_t read_ceata: 1; ///< set if performing read from CE-ATA device + uint32_t ccs_expected: 1; ///< set if CCS is expected from CE-ATA device + uint32_t enable_boot: 1; ///< set for mandatory boot mode + uint32_t expect_boot_ack: 1; ///< when set along with enable_boot, controller expects boot ack pattern + uint32_t disable_boot: 1; ///< set to terminate boot operation (don't set along with enable_boot) + uint32_t boot_mode: 1; ///< 0: mandatory boot operation, 1: alternate boot operation + uint32_t volt_switch: 1; ///< set to enable voltage switching (for CMD11 only) + uint32_t use_hold_reg: 1; ///< clear to bypass HOLD register + uint32_t reserved: 1; + uint32_t start_command: 1; ///< Start command; once command is sent to the card, bit is cleared. +} sdmmc_hw_cmd_t; ///< command format used in cmd register; this structure is defined to make it easier to build command values + +_Static_assert(sizeof(sdmmc_hw_cmd_t) == 4, "invalid size of sdmmc_cmd_t structure"); + + +REG32(SDMMC_CTRL, 0x00) + FIELD(SDMMC_CTRL, RST, 0, 1); + FIELD(SDMMC_CTRL, FIFO_RST, 1, 1); + FIELD(SDMMC_CTRL, DMA_RST, 2, 1); + FIELD(SDMMC_CTRL, INTEN, 4, 1); + FIELD(SDMMC_CTRL, DMAEN, 5, 1); + +REG32(SDMMC_PWREN, 0x04) +REG32(SDMMC_CLKDIV, 0x08) +REG32(SDMMC_CLKSRC, 0x0c) +REG32(SDMMC_CLKENA, 0x10) +REG32(SDMMC_TMOUT, 0x14) +REG32(SDMMC_CTYPE, 0x18) +REG32(SDMMC_BLKSIZ, 0x1c) +REG32(SDMMC_BYTCNT, 0x20) +REG32(SDMMC_INTMASK, 0x24) +REG32(SDMMC_CMDARG, 0x28) +REG32(SDMMC_CMD, 0x2c) + FIELD(SDMMC_CMD, START, 31, 1); + +REG32(SDMMC_RESP0, 0x30) +REG32(SDMMC_RESP1, 0x34) +REG32(SDMMC_RESP2, 0x38) +REG32(SDMMC_RESP3, 0x3c) + +REG32(SDMMC_MINTSTS, 0x40) +REG32(SDMMC_RINTSTS, 0x44) +REG32(SDMMC_STATUS, 0x48) +REG32(SDMMC_FIFOTH, 0x4c) +REG32(SDMMC_CDETECT, 0x50) +REG32(SDMMC_WRTPRT, 0x54) +REG32(SDMMC_GPIO, 0x58) +REG32(SDMMC_TCBCNT, 0x5c) +REG32(SDMMC_TBBCNT, 0x60) +REG32(SDMMC_DEBNCE, 0x64) +REG32(SDMMC_USRID, 0x68) +REG32(SDMMC_VERID, 0x6c) +REG32(SDMMC_HCON, 0x70) +REG32(SDMMC_UHS_REG, 0x74) +REG32(SDMMC_RST_N, 0x78) +REG32(SDMMC_BMOD, 0x80) +REG32(SDMMC_PLDMND, 0x84) +REG32(SDMMC_DBADDR, 0x88) +REG32(SDMMC_DBADDRU, 0x8c) +REG32(SDMMC_IDSTS, 0x8c) +REG32(SDMMC_IDINTEN, 0x90) +REG32(SDMMC_DSCADDR, 0x94) +REG32(SDMMC_DSCADDRL, 0x98) +REG32(SDMMC_DSCADDRU, 0x9c) +REG32(SDMMC_BUFADDRL, 0xa0) +REG32(SDMMC_BUFADDRU, 0xa4) +REG32(SDMMC_CARDTHRCTL, 0x100) +REG32(SDMMC_BACK_END_POWER, 0x104) +REG32(SDMMC_UHS_REG_EXT, 0x108) +REG32(SDMMC_EMMC_DDR_REG, 0x10c) +REG32(SDMMC_ENABLE_SHIFT, 0x110) + +#define SDMMC_INTMASK_IO_SLOT1 BIT(17) +#define SDMMC_INTMASK_IO_SLOT0 BIT(16) +#define SDMMC_INTMASK_EBE BIT(15) +#define SDMMC_INTMASK_ACD BIT(14) +#define SDMMC_INTMASK_SBE BIT(13) +#define SDMMC_INTMASK_HLE BIT(12) +#define SDMMC_INTMASK_FRUN BIT(11) +#define SDMMC_INTMASK_HTO BIT(10) +#define SDMMC_INTMASK_DTO BIT(9) +#define SDMMC_INTMASK_RTO BIT(8) +#define SDMMC_INTMASK_DCRC BIT(7) +#define SDMMC_INTMASK_RCRC BIT(6) +#define SDMMC_INTMASK_RXDR BIT(5) +#define SDMMC_INTMASK_TXDR BIT(4) +#define SDMMC_INTMASK_DATA_OVER BIT(3) +#define SDMMC_INTMASK_CMD_DONE BIT(2) +#define SDMMC_INTMASK_RESP_ERR BIT(1) +#define SDMMC_INTMASK_CD BIT(0) + +#define SDMMC_IDMAC_INTMASK_AI BIT(9) +#define SDMMC_IDMAC_INTMASK_NI BIT(8) +#define SDMMC_IDMAC_INTMASK_CES BIT(5) +#define SDMMC_IDMAC_INTMASK_DU BIT(4) +#define SDMMC_IDMAC_INTMASK_FBE BIT(2) +#define SDMMC_IDMAC_INTMASK_RI BIT(1) +#define SDMMC_IDMAC_INTMASK_TI BIT(0) + + +#define SDMMC_DMA_MAX_BUF_LEN 4096 + +static bool dwc_sdmmc_ctrl_interrupts_enabled(uint32_t ctrl_reg) +{ + return FIELD_EX32(ctrl_reg, SDMMC_CTRL, INTEN) == 1; +} + +static sdmmc_hw_cmd_t dwc_sdmmc_get_hw_cmd(DWCSDMMCState *s) +{ + sdmmc_hw_cmd_t hw_cmd; + memcpy(&hw_cmd, &s->cmd, sizeof(hw_cmd)); + return hw_cmd; +} + +static void dwc_sdmmc_handle_reset(DWCSDMMCState *s) +{ + const uint32_t reset_mask = R_SDMMC_CTRL_FIFO_RST_MASK | R_SDMMC_CTRL_RST_MASK | R_SDMMC_CTRL_DMA_RST_MASK; + if (s->ctrl & reset_mask) { + /* just clear it */ + s->ctrl &= ~reset_mask; + } +} + +static void dwc_sdmmc_update_irq(DWCSDMMCState *s) +{ + uint32_t irq = 0; + if (dwc_sdmmc_ctrl_interrupts_enabled(s->ctrl)) { + irq = s->rintsts & s->intmask; + irq |= (s->idsts & s->idinten) << 16; + } + DEBUG("%s: mask=0x%04x, sts=0x%04x irq=%d\n", __func__, s->intmask, s->rintsts, irq); + qemu_set_irq(s->irq, irq); +} + +static void dwc_sdmmc_handle_cmd(DWCSDMMCState *s) +{ + SDRequest request; + uint8_t resp[16]; + int rlen; + DEBUG("%s: hw_cmd=0x%08x\n", __func__, s->cmd); + sdmmc_hw_cmd_t hw_cmd = dwc_sdmmc_get_hw_cmd(s); + if (hw_cmd.update_clk_reg) { + goto done; + } + + request.cmd = hw_cmd.cmd_index; + request.arg = s->cmdarg; + + rlen = sdbus_do_command(&s->sdbus, &request, resp); + s->rintsts |= SDMMC_INTMASK_CMD_DONE; + if (rlen < 0) { + DEBUG("%s: error: rlen=%d\n", __func__, rlen); + } else { + if (hw_cmd.response_expect) { + if (rlen == 4 && !hw_cmd.response_long) { + s->resp[0] = ldl_be_p(&resp[0]); + s->resp[1] = s->resp[2] = s->resp[3] = 0; + + } else if (rlen == 16 && hw_cmd.response_long) { + s->resp[0] = ldl_be_p(&resp[12]); + s->resp[1] = ldl_be_p(&resp[8]); + s->resp[2] = ldl_be_p(&resp[4]); + s->resp[3] = ldl_be_p(&resp[0]); + } else { + s->rintsts |= SDMMC_INTMASK_RTO; + goto done; + } + } + } + +done: + DEBUG("%s: ending with rinsts=0x%04x\n", __func__, s->rintsts); + s->cmd = FIELD_DP32(s->cmd, SDMMC_CMD, START, 0); + dwc_sdmmc_update_irq(s); +} + +static void dwc_sdmmc_update_bytes_left(DWCSDMMCState *s, size_t bytes_done) +{ + if (s->bytes_left > bytes_done) { + s->bytes_left -= bytes_done; + } else { + s->bytes_left = 0; + } + DEBUG("%s: bytes_left = %d\n", __func__, (unsigned) s->bytes_left); + if (s->bytes_left == 0) { + DEBUG("%s: bytes_left = 0, setting SDMMC_INTMASK_DATA_OVER\n", __func__); + s->rintsts |= SDMMC_INTMASK_DATA_OVER; + } +} + +static size_t dwc_sdmmc_handle_one_desc(DWCSDMMCState *s, hwaddr desc_addr, sdmmc_desc_t *desc, bool is_write, size_t max_bytes) +{ + uint32_t num_done = 0; + uint32_t num_bytes = max_bytes; + uint8_t buf[4096]; + + /* Read descriptor */ + dma_memory_read(&address_space_memory, desc_addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); + if (desc->buffer1_size < num_bytes) { + num_bytes = desc->buffer1_size; + } + + if (desc->owned_by_idmac == 0) { + /* ran into a descriptor owned by software */ + return 0; + } + + while (num_done < num_bytes) { + /* Try to completely fill the local buffer */ + uint32_t buf_bytes = num_bytes - num_done; + if (buf_bytes > sizeof(buf)) { + buf_bytes = sizeof(buf); + } + DEBUG("%s: %sing %d bytes from descr 0x%08x\n", __func__, is_write?"write":"read", buf_bytes, (uint32_t) desc_addr); + /* Write to SD bus */ + if (is_write) { + dma_memory_read(&address_space_memory, + desc->buffer1_ptr + num_done, + buf, buf_bytes, MEMTXATTRS_UNSPECIFIED); + sdbus_write_data(&s->sdbus, buf, buf_bytes); + + /* Read from SD bus */ + } else { + sdbus_read_data(&s->sdbus, buf, buf_bytes); + dma_memory_write(&address_space_memory, + desc->buffer1_ptr + num_done, + buf, buf_bytes, MEMTXATTRS_UNSPECIFIED); + } + num_done += buf_bytes; + } + + /* Clear hold flag and flush descriptor */ + sdmmc_desc_t new_desc = *desc; + new_desc.owned_by_idmac = 0; + dma_memory_write(&address_space_memory, desc_addr, &new_desc, sizeof(new_desc), MEMTXATTRS_UNSPECIFIED); + + /* Update DMAC bits */ + s->idsts |= is_write ? SDMMC_IDMAC_INTMASK_TI : SDMMC_IDMAC_INTMASK_RI; + + return num_done; + +} + +static void dwc_sdmmc_handle_dma(DWCSDMMCState *s) +{ + sdmmc_desc_t desc; + hwaddr desc_addr = s->dscaddr; + sdmmc_hw_cmd_t hw_cmd = dwc_sdmmc_get_hw_cmd(s); + bool is_write = hw_cmd.rw == 1; + uint32_t bytes_done = 0; + + if (s->bytcnt == 0 || s->blksiz == 0 || + !FIELD_EX32(s->ctrl, SDMMC_CTRL, DMAEN)) { + DEBUG("%s: nothing to do (bytcnt=%d, blksiz=%d)\n", __func__, s->bytcnt, s->blksiz); + return; + } + + if (!is_write && !sdbus_data_ready(&s->sdbus)) { + return; + } + + while (s->bytcnt > 0) { + DEBUG("%s: handling descriptor @0x%0x, bytcnt=%d\n", __func__, (uint32_t) desc_addr, s->bytcnt); + bytes_done = dwc_sdmmc_handle_one_desc(s, desc_addr, &desc, is_write, s->bytcnt); + dwc_sdmmc_update_bytes_left(s, bytes_done); + + if (bytes_done <= s->bytcnt) { + s->bytcnt -= bytes_done; + } else { + s->bytcnt = 0; + } + + if (desc.last_descriptor || desc.owned_by_idmac == 0) { + break; + } else { + desc_addr = desc.next_desc_ptr; + s->dscaddr = desc_addr; + } + } + DEBUG("%s: finished with bytcnt=%d at dscaddr=0x%08x\n", __func__, s->bytcnt, s->dscaddr); +} + +static void dwc_sdmmc_maybe_autostop(DWCSDMMCState *s) +{ + sdmmc_hw_cmd_t hw_cmd = dwc_sdmmc_get_hw_cmd(s); + if (hw_cmd.send_auto_stop && s->bytes_left == 0) { + /* First save current command registers */ + uint32_t saved_cmd = s->cmd; + uint32_t saved_arg = s->cmdarg; + + /* Prepare stop command (CMD12) */ + sdmmc_hw_cmd_t auto_stop_cmd = hw_cmd; + auto_stop_cmd.cmd_index = 12; + memcpy(&s->cmd, &auto_stop_cmd, sizeof(s->cmd)); + s->cmdarg = 0; + + /* Put the command on SD bus */ + dwc_sdmmc_handle_cmd(s); + + /* Restore command values */ + s->cmd = saved_cmd; + s->cmdarg = saved_arg; + + /* Set IRQ status bit for automatic stop done */ + s->rintsts |= SDMMC_INTMASK_ACD; + } +} + + +static void dwc_sdmmc_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + DWCSDMMCState *s = DWC_SDMMC(opaque); + + switch (offset) { + case A_SDMMC_CTRL: + s->ctrl = value; + dwc_sdmmc_handle_reset(s); + dwc_sdmmc_update_irq(s); + break; + + case A_SDMMC_CMD: { + s->cmd = value; + if (FIELD_EX32(value, SDMMC_CMD, START)) { + dwc_sdmmc_handle_cmd(s); + dwc_sdmmc_handle_dma(s); + dwc_sdmmc_maybe_autostop(s); + dwc_sdmmc_update_irq(s); + } + break; + } + case A_SDMMC_PLDMND: + dwc_sdmmc_handle_dma(s); + dwc_sdmmc_maybe_autostop(s); + dwc_sdmmc_update_irq(s); + break; + + case A_SDMMC_CMDARG: + s->cmdarg = value; + break; + + case A_SDMMC_INTMASK: + s->intmask = value; + dwc_sdmmc_update_irq(s); + break; + + case A_SDMMC_RINTSTS: + s->rintsts &= ~value; + dwc_sdmmc_update_irq(s); + break; + + case A_SDMMC_IDSTS: + s->idsts &= ~value; + dwc_sdmmc_update_irq(s); + break; + + case A_SDMMC_IDINTEN: + s->idinten = value; + dwc_sdmmc_update_irq(s); + break; + + case A_SDMMC_DBADDR: + s->dbaddr = value; + s->dscaddr = value; + break; + + case A_SDMMC_BYTCNT: + s->bytcnt = value; + s->bytes_left = value; + break; + + case A_SDMMC_BLKSIZ: + s->blksiz = value; + break; + + default: + qemu_log_mask(LOG_UNIMP, "%s: write@0x%02x value=0x%08x\n", __func__, (uint32_t) offset, (uint32_t) value); + } + +} + +static uint64_t dwc_sdmmc_read(void *opaque, hwaddr offset, + unsigned size) +{ + DWCSDMMCState *s = DWC_SDMMC(opaque); + switch (offset) { + case A_SDMMC_CTRL: + return s->ctrl; + case A_SDMMC_INTMASK: + return s->intmask; + case A_SDMMC_CMD: + return s->cmd; + case A_SDMMC_CMDARG: + return s->cmdarg; + case A_SDMMC_RESP0 ... A_SDMMC_RESP3: + return s->resp[(offset - A_SDMMC_RESP0) / 4]; + case A_SDMMC_RINTSTS: + return s->rintsts; + case A_SDMMC_MINTSTS: + return s->intmask & s->rintsts; + case A_SDMMC_IDSTS: + return s->idsts; + case A_SDMMC_IDINTEN: + return s->idinten; + case A_SDMMC_BLKSIZ: + return s->blksiz; + case A_SDMMC_BYTCNT: + return s->bytcnt; + case A_SDMMC_DBADDR: + return s->dbaddr; + case A_SDMMC_DSCADDR: + return s->dscaddr; + default: + qemu_log_mask(LOG_UNIMP, "%s: read@0x%02x\n", __func__, (uint32_t) offset); + } + return 0; +} + + +static const MemoryRegionOps dwc_sdmmc_ops = { + .read = dwc_sdmmc_read, + .write = dwc_sdmmc_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4, + } +}; + + + +static Property dwc_sdmmc_properties[] = { + DEFINE_PROP_END_OF_LIST(), +}; + +static void dwc_sdmmc_init(Object *obj) +{ + DWCSDMMCState *s = DWC_SDMMC(obj); + + qbus_init(&s->sdbus, sizeof(s->sdbus), + TYPE_SD_BUS, DEVICE(s), "sd-bus"); + + memory_region_init_io(&s->iomem, obj, &dwc_sdmmc_ops, s, + TYPE_DWC_SDMMC, 4 * KiB); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); +} + +static void dwc_sdmmc_reset(DeviceState *dev) +{ + DWCSDMMCState *s = DWC_SDMMC(dev); + s->cmd = 0; + s->cmdarg = 0; + s->intmask = 0; + s->rintsts = 0; + s->ctrl = 0; + s->bytes_left = 0; + s->idinten = 0; + s->idsts = 0; + s->blksiz = 512; + s->bytcnt = 0; + s->dbaddr = 0; + s->pldmnd = 0; + memset(s->resp, 0, sizeof(s->resp)); +} + +static void dwc_sdmmc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = dwc_sdmmc_reset; + device_class_set_props(dc, dwc_sdmmc_properties); +} + +static TypeInfo dwc_sdmmc_info = { + .name = TYPE_DWC_SDMMC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = dwc_sdmmc_init, + .instance_size = sizeof(DWCSDMMCState), + .class_init = dwc_sdmmc_class_init, +}; + +static void dwc_sdmmc_register_types(void) +{ + type_register_static(&dwc_sdmmc_info); +} + +type_init(dwc_sdmmc_register_types) diff --git a/hw/sd/meson.build b/hw/sd/meson.build index 807ca07b7cc9..3671b16a347b 100644 --- a/hw/sd/meson.build +++ b/hw/sd/meson.build @@ -11,3 +11,4 @@ softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c')) softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c')) softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c')) softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c')) +softmmu_ss.add(when: 'CONFIG_DWC_SDMMC', if_true: files('dwc_sdmmc.c')) diff --git a/include/hw/sd/dwc_sdmmc.h b/include/hw/sd/dwc_sdmmc.h new file mode 100644 index 000000000000..6520e6db4c10 --- /dev/null +++ b/include/hw/sd/dwc_sdmmc.h @@ -0,0 +1,60 @@ +/* + * Designware SD/MMC controller emulation + * + * Copyright (c) 2021 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef DWC_SDMMC_H +#define DWC_SDMMC_H + +#include "qom/object.h" +#include "hw/sysbus.h" +#include "hw/sd/sd.h" + + +typedef struct DWCSDMMCState { + /*< private >*/ + SysBusDevice busdev; + + /*< public >*/ + SDBus sdbus; + MemoryRegion iomem; + qemu_irq irq; + + uint32_t ctrl; + uint32_t cmd; + uint32_t cmdarg; + uint32_t resp[4]; + uint32_t intmask; + uint32_t rintsts; + uint32_t dbaddr; + uint32_t dscaddr; + uint32_t blksiz; + uint32_t bytcnt; + uint32_t pldmnd; + uint32_t idinten; + uint32_t idsts; + + size_t bytes_left; + + +} DWCSDMMCState; + +#define TYPE_DWC_SDMMC "dwc_sdmmc" +#define DWC_SDMMC(obj) OBJECT_CHECK(DWCSDMMCState, (obj), \ + TYPE_DWC_SDMMC) + +#endif /* DWC_SDMMC_H */ From 04439d5ee3c00e19aa8b89f2289bc009aab58d33 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:39:56 +0200 Subject: [PATCH 26/56] hw/misc: add ESP32 register base addresses --- include/hw/misc/esp32_reg.h | 146 ++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 include/hw/misc/esp32_reg.h diff --git a/include/hw/misc/esp32_reg.h b/include/hw/misc/esp32_reg.h new file mode 100644 index 000000000000..657f4679e74b --- /dev/null +++ b/include/hw/misc/esp32_reg.h @@ -0,0 +1,146 @@ +#pragma once + + +#define DR_REG_DPORT_BASE 0x3ff00000 +#define DR_REG_AES_BASE 0x3ff01000 +#define DR_REG_RSA_BASE 0x3ff02000 +#define DR_REG_SHA_BASE 0x3ff03000 +#define DR_REG_FLASH_MMU_TABLE_PRO 0x3ff10000 +#define DR_REG_FLASH_MMU_TABLE_APP 0x3ff12000 +#define DR_REG_DPORT_END 0x3ff13FFC +#define DR_REG_DPORT_APB_BASE 0x3ff40000 +#define DR_REG_UART_BASE 0x3ff40000 +#define DR_REG_SPI1_BASE 0x3ff42000 +#define DR_REG_SPI0_BASE 0x3ff43000 +#define DR_REG_GPIO_BASE 0x3ff44000 +#define DR_REG_GPIO_SD_BASE 0x3ff44f00 +#define DR_REG_FE2_BASE 0x3ff45000 +#define DR_REG_FE_BASE 0x3ff46000 +#define DR_REG_FRC_TIMER_BASE 0x3ff47000 +#define DR_REG_RTCCNTL_BASE 0x3ff48000 +#define DR_REG_RTCIO_BASE 0x3ff48400 +#define DR_REG_SENS_BASE 0x3ff48800 +#define DR_REG_RTC_I2C_BASE 0x3ff48C00 +#define DR_REG_IO_MUX_BASE 0x3ff49000 +#define DR_REG_HINF_BASE 0x3ff4B000 +#define DR_REG_UHCI1_BASE 0x3ff4C000 +#define DR_REG_ANA_BASE 0x3ff4E000 +#define DR_REG_I2S_BASE 0x3ff4F000 +#define DR_REG_UART1_BASE 0x3ff50000 +#define DR_REG_BT_BASE 0x3ff51000 +#define DR_REG_I2C_EXT_BASE 0x3ff53000 +#define DR_REG_UHCI0_BASE 0x3ff54000 +#define DR_REG_SLCHOST_BASE 0x3ff55000 +#define DR_REG_RMT_BASE 0x3ff56000 +#define DR_REG_PCNT_BASE 0x3ff57000 +#define DR_REG_SLC_BASE 0x3ff58000 +#define DR_REG_LEDC_BASE 0x3ff59000 +#define DR_REG_EFUSE_BASE 0x3ff5A000 +#define DR_REG_SPI_ENCRYPT_BASE 0x3ff5B000 +#define DR_REG_NRX_BASE 0x3ff5CC00 +#define DR_REG_BB_BASE 0x3ff5D000 +#define DR_REG_PWM_BASE 0x3ff5E000 +#define DR_REG_TIMERGROUP0_BASE 0x3ff5F000 +#define DR_REG_TIMERGROUP1_BASE 0x3ff60000 +#define DR_REG_RTCMEM0_BASE 0x3ff61000 +#define DR_REG_RTCMEM1_BASE 0x3ff62000 +#define DR_REG_RTCMEM2_BASE 0x3ff63000 +#define DR_REG_SPI2_BASE 0x3ff64000 +#define DR_REG_SPI3_BASE 0x3ff65000 +#define DR_REG_SYSCON_BASE 0x3ff66000 +#define DR_REG_APB_CTRL_BASE 0x3ff66000 /* Old name for SYSCON, to be removed */ +#define DR_REG_I2C1_EXT_BASE 0x3ff67000 +#define DR_REG_SDMMC_BASE 0x3ff68000 +#define DR_REG_EMAC_BASE 0x3ff69000 +#define DR_REG_CAN_BASE 0x3ff6B000 +#define DR_REG_PWM1_BASE 0x3ff6C000 +#define DR_REG_I2S1_BASE 0x3ff6D000 +#define DR_REG_UART2_BASE 0x3ff6E000 +#define DR_REG_PWM2_BASE 0x3ff6F000 +#define DR_REG_PWM3_BASE 0x3ff70000 +#define DR_REG_WDEV_BASE 0x3ff75000 + +#define APB_REG_BASE 0x60000000 + +#define ETS_WIFI_MAC_INTR_SOURCE 0/**< interrupt of WiFi MAC, level*/ +#define ETS_WIFI_MAC_NMI_SOURCE 1/**< interrupt of WiFi MAC, NMI, use if MAC have bug to fix in NMI*/ +#define ETS_WIFI_BB_INTR_SOURCE 2/**< interrupt of WiFi BB, level, we can do some calibartion*/ +#define ETS_BT_MAC_INTR_SOURCE 3/**< will be cancelled*/ +#define ETS_BT_BB_INTR_SOURCE 4/**< interrupt of BT BB, level*/ +#define ETS_BT_BB_NMI_SOURCE 5/**< interrupt of BT BB, NMI, use if BB have bug to fix in NMI*/ +#define ETS_RWBT_INTR_SOURCE 6/**< interrupt of RWBT, level*/ +#define ETS_RWBLE_INTR_SOURCE 7/**< interrupt of RWBLE, level*/ +#define ETS_RWBT_NMI_SOURCE 8/**< interrupt of RWBT, NMI, use if RWBT have bug to fix in NMI*/ +#define ETS_RWBLE_NMI_SOURCE 9/**< interrupt of RWBLE, NMI, use if RWBT have bug to fix in NMI*/ +#define ETS_SLC0_INTR_SOURCE 10/**< interrupt of SLC0, level*/ +#define ETS_SLC1_INTR_SOURCE 11/**< interrupt of SLC1, level*/ +#define ETS_UHCI0_INTR_SOURCE 12/**< interrupt of UHCI0, level*/ +#define ETS_UHCI1_INTR_SOURCE 13/**< interrupt of UHCI1, level*/ +#define ETS_TG0_T0_LEVEL_INTR_SOURCE 14/**< interrupt of TIMER_GROUP0, TIMER0, level, we would like use EDGE for timer if permission*/ +#define ETS_TG0_T1_LEVEL_INTR_SOURCE 15/**< interrupt of TIMER_GROUP0, TIMER1, level, we would like use EDGE for timer if permission*/ +#define ETS_TG0_WDT_LEVEL_INTR_SOURCE 16/**< interrupt of TIMER_GROUP0, WATCHDOG, level*/ +#define ETS_TG0_LACT_LEVEL_INTR_SOURCE 17/**< interrupt of TIMER_GROUP0, LACT, level*/ +#define ETS_TG1_T0_LEVEL_INTR_SOURCE 18/**< interrupt of TIMER_GROUP1, TIMER0, level, we would like use EDGE for timer if permission*/ +#define ETS_TG1_T1_LEVEL_INTR_SOURCE 19/**< interrupt of TIMER_GROUP1, TIMER1, level, we would like use EDGE for timer if permission*/ +#define ETS_TG1_WDT_LEVEL_INTR_SOURCE 20/**< interrupt of TIMER_GROUP1, WATCHDOG, level*/ +#define ETS_TG1_LACT_LEVEL_INTR_SOURCE 21/**< interrupt of TIMER_GROUP1, LACT, level*/ +#define ETS_GPIO_INTR_SOURCE 22/**< interrupt of GPIO, level*/ +#define ETS_GPIO_NMI_SOURCE 23/**< interrupt of GPIO, NMI*/ +#define ETS_FROM_CPU_INTR0_SOURCE 24/**< interrupt0 generated from a CPU, level*/ /* Used for FreeRTOS */ +#define ETS_FROM_CPU_INTR1_SOURCE 25/**< interrupt1 generated from a CPU, level*/ /* Used for FreeRTOS */ +#define ETS_FROM_CPU_INTR2_SOURCE 26/**< interrupt2 generated from a CPU, level*/ /* Used for DPORT Access */ +#define ETS_FROM_CPU_INTR3_SOURCE 27/**< interrupt3 generated from a CPU, level*/ /* Used for DPORT Access */ +#define ETS_SPI0_INTR_SOURCE 28/**< interrupt of SPI0, level, SPI0 is for Cache Access, do not use this*/ +#define ETS_SPI1_INTR_SOURCE 29/**< interrupt of SPI1, level, SPI1 is for flash read/write, do not use this*/ +#define ETS_SPI2_INTR_SOURCE 30/**< interrupt of SPI2, level*/ +#define ETS_SPI3_INTR_SOURCE 31/**< interrupt of SPI3, level*/ +#define ETS_I2S0_INTR_SOURCE 32/**< interrupt of I2S0, level*/ +#define ETS_I2S1_INTR_SOURCE 33/**< interrupt of I2S1, level*/ +#define ETS_UART0_INTR_SOURCE 34/**< interrupt of UART0, level*/ +#define ETS_UART1_INTR_SOURCE 35/**< interrupt of UART1, level*/ +#define ETS_UART2_INTR_SOURCE 36/**< interrupt of UART2, level*/ +#define ETS_SDIO_HOST_INTR_SOURCE 37/**< interrupt of SD/SDIO/MMC HOST, level*/ +#define ETS_ETH_MAC_INTR_SOURCE 38/**< interrupt of ethernet mac, level*/ +#define ETS_PWM0_INTR_SOURCE 39/**< interrupt of PWM0, level, Reserved*/ +#define ETS_PWM1_INTR_SOURCE 40/**< interrupt of PWM1, level, Reserved*/ +#define ETS_PWM2_INTR_SOURCE 41/**< interrupt of PWM2, level*/ +#define ETS_PWM3_INTR_SOURCE 42/**< interruot of PWM3, level*/ +#define ETS_LEDC_INTR_SOURCE 43/**< interrupt of LED PWM, level*/ +#define ETS_EFUSE_INTR_SOURCE 44/**< interrupt of efuse, level, not likely to use*/ +#define ETS_CAN_INTR_SOURCE 45/**< interrupt of can, level*/ +#define ETS_RTC_CORE_INTR_SOURCE 46/**< interrupt of rtc core, level, include rtc watchdog*/ +#define ETS_RMT_INTR_SOURCE 47/**< interrupt of remote controller, level*/ +#define ETS_PCNT_INTR_SOURCE 48/**< interrupt of pluse count, level*/ +#define ETS_I2C_EXT0_INTR_SOURCE 49/**< interrupt of I2C controller1, level*/ +#define ETS_I2C_EXT1_INTR_SOURCE 50/**< interrupt of I2C controller0, level*/ +#define ETS_RSA_INTR_SOURCE 51/**< interrupt of RSA accelerator, level*/ +#define ETS_SPI1_DMA_INTR_SOURCE 52/**< interrupt of SPI1 DMA, SPI1 is for flash read/write, do not use this*/ +#define ETS_SPI2_DMA_INTR_SOURCE 53/**< interrupt of SPI2 DMA, level*/ +#define ETS_SPI3_DMA_INTR_SOURCE 54/**< interrupt of SPI3 DMA, level*/ +#define ETS_WDT_INTR_SOURCE 55/**< will be cancelled*/ +#define ETS_TIMER1_INTR_SOURCE 56/**< will be cancelled*/ +#define ETS_TIMER2_INTR_SOURCE 57/**< will be cancelled*/ +#define ETS_TG0_T0_EDGE_INTR_SOURCE 58/**< interrupt of TIMER_GROUP0, TIMER0, EDGE*/ +#define ETS_TG0_T1_EDGE_INTR_SOURCE 59/**< interrupt of TIMER_GROUP0, TIMER1, EDGE*/ +#define ETS_TG0_WDT_EDGE_INTR_SOURCE 60/**< interrupt of TIMER_GROUP0, WATCH DOG, EDGE*/ +#define ETS_TG0_LACT_EDGE_INTR_SOURCE 61/**< interrupt of TIMER_GROUP0, LACT, EDGE*/ +#define ETS_TG1_T0_EDGE_INTR_SOURCE 62/**< interrupt of TIMER_GROUP1, TIMER0, EDGE*/ +#define ETS_TG1_T1_EDGE_INTR_SOURCE 63/**< interrupt of TIMER_GROUP1, TIMER1, EDGE*/ +#define ETS_TG1_WDT_EDGE_INTR_SOURCE 64/**< interrupt of TIMER_GROUP1, WATCHDOG, EDGE*/ +#define ETS_TG1_LACT_EDGE_INTR_SOURCE 65/**< interrupt of TIMER_GROUP0, LACT, EDGE*/ +#define ETS_MMU_IA_INTR_SOURCE 66/**< interrupt of MMU Invalid Access, LEVEL*/ +#define ETS_MPU_IA_INTR_SOURCE 67/**< interrupt of MPU Invalid Access, LEVEL*/ +#define ETS_CACHE_IA_INTR_SOURCE 68/**< interrupt of Cache Invalied Access, LEVEL*/ + + +#define ESP32_DPORT_CROSSCORE_INT_COUNT 4 +#define ESP32_INT_MATRIX_OUTPUTS 32 +#define ESP32_INT_MATRIX_INPUTS 69 +#define ESP32_CPU_COUNT 2 +#define ESP32_UART_COUNT 3 +#define ESP32_FRC_COUNT 2 +#define ESP32_TIMG_COUNT 2 +#define ESP32_SPI_COUNT 4 +#define ESP32_I2C_COUNT 2 +#define ESP32_RTC_CNTL_SCRATCH_REG_COUNT 8 + From 66fa088264b93c67f7f3b2eb7c897513721a1b0c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 21 Jan 2021 00:49:59 +0100 Subject: [PATCH 27/56] hw/xtensa: add ESP32 interrupt matrix --- hw/xtensa/esp32_intc.c | 143 +++++++++++++++++++++++++++++++++ include/hw/xtensa/esp32_intc.h | 41 ++++++++++ 2 files changed, 184 insertions(+) create mode 100644 hw/xtensa/esp32_intc.c create mode 100644 include/hw/xtensa/esp32_intc.h diff --git a/hw/xtensa/esp32_intc.c b/hw/xtensa/esp32_intc.c new file mode 100644 index 000000000000..68e985a19605 --- /dev/null +++ b/hw/xtensa/esp32_intc.c @@ -0,0 +1,143 @@ +/* + * ESP32 Interrupt Matrix + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/xtensa/esp32_intc.h" + +#define INTMATRIX_UNINT_VALUE 6 + +#define IRQ_MAP(cpu, input) s->irq_map[cpu][input] + +static void esp32_intmatrix_irq_handler(void *opaque, int n, int level) +{ + Esp32IntMatrixState *s = ESP32_INTMATRIX(opaque); + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + if (s->outputs[i] == NULL) { + continue; + } + int out_index = IRQ_MAP(i, n); + for (int int_index = 0; int_index < s->cpu[i]->env.config->nextint; ++int_index) { + if (s->cpu[i]->env.config->extint[int_index] == out_index) { + qemu_set_irq(s->outputs[i][int_index], level); + break; + } + } + } +} + +static inline uint8_t* get_map_entry(Esp32IntMatrixState* s, hwaddr addr) +{ + int source_index = addr / sizeof(uint32_t); + if (source_index > ESP32_INT_MATRIX_INPUTS * ESP32_CPU_COUNT) { + error_report("%s: source_index %d out of range", __func__, source_index); + return NULL; + } + int cpu_index = source_index / ESP32_INT_MATRIX_INPUTS; + source_index = source_index % ESP32_INT_MATRIX_INPUTS; + return &IRQ_MAP(cpu_index, source_index); +} + +static uint64_t esp32_intmatrix_read(void* opaque, hwaddr addr, unsigned int size) +{ + Esp32IntMatrixState *s = ESP32_INTMATRIX(opaque); + uint8_t* map_entry = get_map_entry(s, addr); + return (map_entry != NULL) ? *map_entry : 0; +} + +static void esp32_intmatrix_write(void* opaque, hwaddr addr, uint64_t value, unsigned int size) +{ + Esp32IntMatrixState *s = ESP32_INTMATRIX(opaque); + uint8_t* map_entry = get_map_entry(s, addr); + if (map_entry != NULL) { + *map_entry = value & 0x1f; + } +} + +static const MemoryRegionOps esp_intmatrix_ops = { + .read = esp32_intmatrix_read, + .write = esp32_intmatrix_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_intmatrix_reset(DeviceState *dev) +{ + Esp32IntMatrixState *s = ESP32_INTMATRIX(dev); + memset(s->irq_map, INTMATRIX_UNINT_VALUE, sizeof(s->irq_map)); + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + if (s->outputs[i] == NULL) { + continue; + } + for (int int_index = 0; int_index < s->cpu[i]->env.config->nextint; ++int_index) { + qemu_irq_lower(s->outputs[i][int_index]); + } + } + +} + +static void esp32_intmatrix_realize(DeviceState *dev, Error **errp) +{ + Esp32IntMatrixState *s = ESP32_INTMATRIX(dev); + + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + if (s->cpu[i]) { + s->outputs[i] = xtensa_get_extints(&s->cpu[i]->env); + } + } + esp32_intmatrix_reset(dev); +} + +static void esp32_intmatrix_init(Object *obj) +{ + Esp32IntMatrixState *s = ESP32_INTMATRIX(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp_intmatrix_ops, s, + TYPE_ESP32_INTMATRIX, ESP32_INT_MATRIX_INPUTS * ESP32_CPU_COUNT * sizeof(uint32_t)); + sysbus_init_mmio(sbd, &s->iomem); + + qdev_init_gpio_in(DEVICE(s), esp32_intmatrix_irq_handler, ESP32_INT_MATRIX_INPUTS); +} + +static Property esp32_intmatrix_properties[] = { + DEFINE_PROP_LINK("cpu0", Esp32IntMatrixState, cpu[0], TYPE_XTENSA_CPU, XtensaCPU *), + DEFINE_PROP_LINK("cpu1", Esp32IntMatrixState, cpu[1], TYPE_XTENSA_CPU, XtensaCPU *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_intmatrix_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32_intmatrix_reset; + dc->realize = esp32_intmatrix_realize; + device_class_set_props(dc, esp32_intmatrix_properties); +} + +static const TypeInfo esp32_intmatrix_info = { + .name = TYPE_ESP32_INTMATRIX, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32IntMatrixState), + .instance_init = esp32_intmatrix_init, + .class_init = esp32_intmatrix_class_init +}; + +static void esp32_intmatrix_register_types(void) +{ + type_register_static(&esp32_intmatrix_info); +} + +type_init(esp32_intmatrix_register_types) diff --git a/include/hw/xtensa/esp32_intc.h b/include/hw/xtensa/esp32_intc.h new file mode 100644 index 000000000000..262dbd13844f --- /dev/null +++ b/include/hw/xtensa/esp32_intc.h @@ -0,0 +1,41 @@ +/* + * ESP32 Interrupt Matrix + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#pragma once + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "target/xtensa/cpu.h" +#include "target/xtensa/cpu-qom.h" + +#define ESP32_CPU_COUNT 2 +#define ESP32_INT_MATRIX_INPUTS 69 + +#define TYPE_ESP32_INTMATRIX "misc.esp32.intmatrix" +#define ESP32_INTMATRIX(obj) OBJECT_CHECK(Esp32IntMatrixState, (obj), TYPE_ESP32_INTMATRIX) + + +typedef struct Esp32IntMatrixState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + qemu_irq *outputs[ESP32_CPU_COUNT]; + uint8_t irq_map[ESP32_CPU_COUNT][ESP32_INT_MATRIX_INPUTS]; + + /* properties */ + XtensaCPU *cpu[ESP32_CPU_COUNT]; +} Esp32IntMatrixState; + From 3fddc2e5d4d0b5ac2c78be5b1837b0e556c9c759 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 27 Sep 2019 11:40:25 +0200 Subject: [PATCH 28/56] hw/xtensa: add ESP32 machine --- configs/devices/xtensa-softmmu/default.mak | 1 + hw/xtensa/Kconfig | 12 + hw/xtensa/esp32.c | 911 +++++++++++++++++++++ hw/xtensa/meson.build | 1 + include/hw/xtensa/esp32.h | 58 ++ pc-bios/esp32-v3-rom-app.bin | Bin 0 -> 455722 bytes pc-bios/esp32-v3-rom.bin | Bin 0 -> 455722 bytes pc-bios/meson.build | 2 + target/xtensa/core-esp32.c | 1 - 9 files changed, 985 insertions(+), 1 deletion(-) create mode 100644 hw/xtensa/esp32.c create mode 100644 include/hw/xtensa/esp32.h create mode 100755 pc-bios/esp32-v3-rom-app.bin create mode 100755 pc-bios/esp32-v3-rom.bin diff --git a/configs/devices/xtensa-softmmu/default.mak b/configs/devices/xtensa-softmmu/default.mak index 4fe1bf00c94b..f819d9b781e2 100644 --- a/configs/devices/xtensa-softmmu/default.mak +++ b/configs/devices/xtensa-softmmu/default.mak @@ -7,3 +7,4 @@ CONFIG_SEMIHOSTING=y CONFIG_XTENSA_SIM=y CONFIG_XTENSA_VIRT=y CONFIG_XTENSA_XTFPGA=y +CONFIG_XTENSA_ESP32=y diff --git a/hw/xtensa/Kconfig b/hw/xtensa/Kconfig index 0740657ea58f..6a09c5b7fc16 100644 --- a/hw/xtensa/Kconfig +++ b/hw/xtensa/Kconfig @@ -12,3 +12,15 @@ config XTENSA_XTFPGA select OPENCORES_ETH select PFLASH_CFI01 select SERIAL + +config XTENSA_ESP32 + bool + select SSI + select SSI_M25P80 + select UNIMP + select OPENCORES_ETH + select DWC_SDMMC + select TMP105 + select LED + + diff --git a/hw/xtensa/esp32.c b/hw/xtensa/esp32.c new file mode 100644 index 000000000000..2df6c2e93840 --- /dev/null +++ b/hw/xtensa/esp32.c @@ -0,0 +1,911 @@ +/* + * ESP32 SoC and machine + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "hw/i2c/esp32_i2c.h" +#include "hw/xtensa/xtensa_memory.h" +#include "hw/misc/unimp.h" +#include "hw/irq.h" +#include "hw/i2c/i2c.h" +#include "hw/qdev-properties.h" +#include "hw/xtensa/esp32.h" +#include "hw/misc/ssi_psram.h" +#include "hw/sd/dwc_sdmmc.h" +#include "core-esp32/core-isa.h" +#include "qemu/datadir.h" +#include "sysemu/sysemu.h" +#include "sysemu/reset.h" +#include "sysemu/cpus.h" +#include "sysemu/runstate.h" +#include "sysemu/blockdev.h" +#include "sysemu/block-backend.h" +#include "exec/exec-all.h" +#include "net/net.h" +#include "elf.h" + +#define TYPE_ESP32_SOC "xtensa.esp32" +#define ESP32_SOC(obj) OBJECT_CHECK(Esp32SocState, (obj), TYPE_ESP32_SOC) + +#define TYPE_ESP32_CPU XTENSA_CPU_TYPE_NAME("esp32") + + + +enum { + ESP32_MEMREGION_IROM, + ESP32_MEMREGION_DROM, + ESP32_MEMREGION_DRAM, + ESP32_MEMREGION_IRAM, + ESP32_MEMREGION_ICACHE0, + ESP32_MEMREGION_ICACHE1, + ESP32_MEMREGION_RTCSLOW, + ESP32_MEMREGION_RTCFAST_D, + ESP32_MEMREGION_RTCFAST_I, +}; + +static const struct MemmapEntry { + hwaddr base; + hwaddr size; +} esp32_memmap[] = { + [ESP32_MEMREGION_DROM] = { 0x3ff90000, 0x10000 }, + [ESP32_MEMREGION_IROM] = { 0x40000000, 0x70000 }, + [ESP32_MEMREGION_DRAM] = { 0x3ffae000, 0x52000 }, + [ESP32_MEMREGION_IRAM] = { 0x40080000, 0x40000 }, + [ESP32_MEMREGION_ICACHE0] = { 0x40070000, 0x8000 }, + [ESP32_MEMREGION_ICACHE1] = { 0x40078000, 0x8000 }, + [ESP32_MEMREGION_RTCSLOW] = { 0x50000000, 0x2000 }, + [ESP32_MEMREGION_RTCFAST_I] = { 0x400C0000, 0x2000 }, + [ESP32_MEMREGION_RTCFAST_D] = { 0x3ff80000, 0x2000 }, +}; + + +#define ESP32_SOC_RESET_PROCPU 0x1 +#define ESP32_SOC_RESET_APPCPU 0x2 +#define ESP32_SOC_RESET_PERIPH 0x4 +#define ESP32_SOC_RESET_DIG (ESP32_SOC_RESET_PROCPU | ESP32_SOC_RESET_APPCPU | ESP32_SOC_RESET_PERIPH) +#define ESP32_SOC_RESET_RTC 0x8 +#define ESP32_SOC_RESET_ALL (ESP32_SOC_RESET_RTC | ESP32_SOC_RESET_DIG) + + + + +static void remove_cpu_watchpoints(XtensaCPU* xcs) +{ + for (int i = 0; i < MAX_NDBREAK; ++i) { + if (xcs->env.cpu_watchpoint[i]) { + cpu_watchpoint_remove_by_ref(CPU(xcs), xcs->env.cpu_watchpoint[i]); + xcs->env.cpu_watchpoint[i] = NULL; + } + } +} + +static void esp32_dig_reset(void *opaque, int n, int level) +{ + Esp32SocState *s = ESP32_SOC(opaque); + if (level) { + esp32_dport_clear_ill_trap_state(&s->dport); + s->requested_reset = ESP32_SOC_RESET_DIG; + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } +} + +static void esp32_cpu_reset(void* opaque, int n, int level) +{ + Esp32SocState *s = ESP32_SOC(opaque); + if (level) { + s->requested_reset = (n == 0) ? ESP32_SOC_RESET_PROCPU : ESP32_SOC_RESET_APPCPU; + /* Use different cause for APP CPU so that its reset doesn't cause QEMU to exit, + * when -no-reboot option is given. + */ + ShutdownCause cause = (n == 0) ? SHUTDOWN_CAUSE_GUEST_RESET : SHUTDOWN_CAUSE_SUBSYSTEM_RESET; + s->rtc_cntl.reset_cause[n] = ESP32_SW_CPU_RESET; + qemu_system_reset_request(cause); + } +} + +static void esp32_timg_cpu_reset(void* opaque, int n, int level) +{ + Esp32SocState *s = ESP32_SOC(opaque); + if (level) { + s->requested_reset = (n == 0) ? ESP32_SOC_RESET_PROCPU : ESP32_SOC_RESET_APPCPU; + /* Use different cause for APP CPU so that its reset doesn't cause QEMU to exit, + * when -no-reboot option is given. + */ + ShutdownCause cause = (n == 0) ? SHUTDOWN_CAUSE_GUEST_RESET : SHUTDOWN_CAUSE_SUBSYSTEM_RESET; + s->rtc_cntl.reset_cause[n] = ESP32_TGWDT_CPU_RESET; + qemu_system_reset_request(cause); + } +} + +static void esp32_timg_sys_reset(void* opaque, int n, int level) +{ + Esp32SocState *s = ESP32_SOC(opaque); + if (level) { + esp32_dport_clear_ill_trap_state(&s->dport); + s->requested_reset = ESP32_SOC_RESET_DIG; + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + s->rtc_cntl.reset_cause[i] = ESP32_TG0WDT_SYS_RESET + n; + } + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } +} + +static void esp32_soc_reset(DeviceState *dev) +{ + Esp32SocState *s = ESP32_SOC(dev); + + uint32_t strap_mode = s->gpio.strap_mode; + + bool flash_boot_mode = ((strap_mode & 0x10) || (strap_mode & 0x1f) == 0x0c); + qemu_set_irq(qdev_get_gpio_in_named(DEVICE(&s->flash_enc), ESP32_FLASH_ENCRYPTION_DL_MODE_GPIO, 0), !flash_boot_mode); + + if (s->requested_reset == 0) { + s->requested_reset = ESP32_SOC_RESET_ALL; + } + if (s->requested_reset & ESP32_SOC_RESET_RTC) { + device_cold_reset(DEVICE(&s->rtc_cntl)); + } + if (s->requested_reset & ESP32_SOC_RESET_PERIPH) { + device_cold_reset(DEVICE(&s->dport)); + device_cold_reset(DEVICE(&s->intmatrix)); + device_cold_reset(DEVICE(&s->aes)); + device_cold_reset(DEVICE(&s->rsa)); + device_cold_reset(DEVICE(&s->gpio)); + for (int i = 0; i < ESP32_UART_COUNT; ++i) { + device_cold_reset(DEVICE(&s->uart[i])); + } + for (int i = 0; i < ESP32_FRC_COUNT; ++i) { + device_cold_reset(DEVICE(&s->frc_timer[i])); + } + for (int i = 0; i < ESP32_TIMG_COUNT; ++i) { + device_cold_reset(DEVICE(&s->timg[i])); + } + s->timg[0].flash_boot_mode = flash_boot_mode; + for (int i = 0; i < ESP32_SPI_COUNT; ++i) { + device_cold_reset(DEVICE(&s->spi[i])); + } + for (int i = 0; i < ESP32_I2C_COUNT; i++) { + device_cold_reset(DEVICE(&s->i2c[i])); + } + device_cold_reset(DEVICE(&s->efuse)); + if (s->eth) { + device_cold_reset(s->eth); + } + } + if (s->requested_reset & ESP32_SOC_RESET_PROCPU) { + xtensa_select_static_vectors(&s->cpu[0].env, s->rtc_cntl.stat_vector_sel[0]); + remove_cpu_watchpoints(&s->cpu[0]); + cpu_reset(CPU(&s->cpu[0])); + } + if (s->requested_reset & ESP32_SOC_RESET_APPCPU) { + xtensa_select_static_vectors(&s->cpu[1].env, s->rtc_cntl.stat_vector_sel[1]); + remove_cpu_watchpoints(&s->cpu[1]); + cpu_reset(CPU(&s->cpu[1])); + } + s->requested_reset = 0; +} + +static void esp32_cpu_stall(void* opaque, int n, int level) +{ + Esp32SocState *s = ESP32_SOC(opaque); + + bool stall; + if (n == 0) { + stall = s->rtc_cntl.cpu_stall_state[0]; + } else { + stall = s->rtc_cntl.cpu_stall_state[1] || s->dport.appcpu_stall_state || (!s->dport.appcpu_clkgate_state); + } + + if (stall != s->cpu[n].env.runstall) { + xtensa_runstall(&s->cpu[n].env, stall); + } +} + +static void esp32_clk_update(void* opaque, int n, int level) +{ + Esp32SocState *s = ESP32_SOC(opaque); + if (!level) { + return; + } + + /* APB clock */ + uint32_t apb_clk_freq, cpu_clk_freq; + if (s->rtc_cntl.soc_clk == ESP32_SOC_CLK_PLL) { + const uint32_t cpu_clk_mul[] = {1, 2, 3}; + apb_clk_freq = s->rtc_cntl.pll_apb_freq; + cpu_clk_freq = cpu_clk_mul[s->dport.cpuperiod_sel] * apb_clk_freq; + } else { + apb_clk_freq = s->rtc_cntl.xtal_apb_freq; + cpu_clk_freq = apb_clk_freq; + } + qdev_prop_set_int32(DEVICE(&s->frc_timer), "apb_freq", apb_clk_freq); + qdev_prop_set_int32(DEVICE(&s->timg[0]), "apb_freq", apb_clk_freq); + qdev_prop_set_int32(DEVICE(&s->timg[1]), "apb_freq", apb_clk_freq); + clock_update_hz(s->cpu[0].clock, cpu_clk_freq ); + clock_update_hz(s->cpu[1].clock, cpu_clk_freq ); +} + +static void esp32_soc_add_periph_device(MemoryRegion *dest, void* dev, hwaddr dport_base_addr) +{ + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_add_subregion_overlap(dest, dport_base_addr, mr, 0); + MemoryRegion *mr_apb = g_new(MemoryRegion, 1); + char *name = g_strdup_printf("mr-apb-0x%08x", (uint32_t) dport_base_addr); + memory_region_init_alias(mr_apb, OBJECT(dev), name, mr, 0, memory_region_size(mr)); + memory_region_add_subregion_overlap(dest, dport_base_addr - DR_REG_DPORT_APB_BASE + APB_REG_BASE, mr_apb, 0); + g_free(name); +} + +static void esp32_soc_add_unimp_device(MemoryRegion *dest, const char* name, hwaddr dport_base_addr, size_t size) +{ + create_unimplemented_device(name, dport_base_addr, size); + char * name_apb = g_strdup_printf("%s-apb", name); + create_unimplemented_device(name_apb, dport_base_addr - DR_REG_DPORT_APB_BASE + APB_REG_BASE, size); + g_free(name_apb); +} + +static void esp32_soc_realize(DeviceState *dev, Error **errp) +{ + Esp32SocState *s = ESP32_SOC(dev); + MachineState *ms = MACHINE(qdev_get_machine()); + + const struct MemmapEntry *memmap = esp32_memmap; + MemoryRegion *sys_mem = get_system_memory(); + + MemoryRegion *dram = g_new(MemoryRegion, 1); + MemoryRegion *iram = g_new(MemoryRegion, 1); + MemoryRegion *icache0 = g_new(MemoryRegion, 1); + MemoryRegion *icache1 = g_new(MemoryRegion, 1); + MemoryRegion *rtcslow = g_new(MemoryRegion, 1); + MemoryRegion *rtcfast_i = g_new(MemoryRegion, 1); + MemoryRegion *rtcfast_d = g_new(MemoryRegion, 1); + + for (int i = 0; i < ms->smp.cpus; ++i) { + MemoryRegion *drom = g_new(MemoryRegion, 1); + MemoryRegion *irom = g_new(MemoryRegion, 1); + + char name[16]; + snprintf(name, sizeof(name), "esp32.irom.cpu%d", i); + memory_region_init_rom(irom, NULL, name, + memmap[ESP32_MEMREGION_IROM].size, &error_fatal); + memory_region_add_subregion(&s->cpu_specific_mem[i], memmap[ESP32_MEMREGION_IROM].base, irom); + + + snprintf(name, sizeof(name), "esp32.drom.cpu%d", i); + memory_region_init_alias(drom, NULL, name, irom, 0x60000, memmap[ESP32_MEMREGION_DROM].size); + memory_region_add_subregion(&s->cpu_specific_mem[i], memmap[ESP32_MEMREGION_DROM].base, drom); + } + + memory_region_init_ram(dram, NULL, "esp32.dram", + memmap[ESP32_MEMREGION_DRAM].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[ESP32_MEMREGION_DRAM].base, dram); + + memory_region_init_ram(iram, NULL, "esp32.iram", + memmap[ESP32_MEMREGION_IRAM].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[ESP32_MEMREGION_IRAM].base, iram); + + memory_region_init_ram(icache0, NULL, "esp32.icache0", + memmap[ESP32_MEMREGION_ICACHE0].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[ESP32_MEMREGION_ICACHE0].base, icache0); + + memory_region_init_ram(icache1, NULL, "esp32.icache1", + memmap[ESP32_MEMREGION_ICACHE1].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[ESP32_MEMREGION_ICACHE1].base, icache1); + + memory_region_init_ram(rtcslow, NULL, "esp32.rtcslow", + memmap[ESP32_MEMREGION_RTCSLOW].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[ESP32_MEMREGION_RTCSLOW].base, rtcslow); + + /* RTC Fast memory is only accessible by the PRO CPU */ + + memory_region_init_ram(rtcfast_i, NULL, "esp32.rtcfast_i", + memmap[ESP32_MEMREGION_RTCSLOW].size, &error_fatal); + memory_region_add_subregion(&s->cpu_specific_mem[0], memmap[ESP32_MEMREGION_RTCFAST_I].base, rtcfast_i); + + memory_region_init_alias(rtcfast_d, NULL, "esp32.rtcfast_d", rtcfast_i, 0, memmap[ESP32_MEMREGION_RTCFAST_D].size); + memory_region_add_subregion(&s->cpu_specific_mem[0], memmap[ESP32_MEMREGION_RTCFAST_D].base, rtcfast_d); + + for (int i = 0; i < ms->smp.cpus; ++i) { + qdev_realize(DEVICE(&s->cpu[i]), NULL, &error_fatal); + } + + qdev_realize(DEVICE(&s->dport), &s->periph_bus, &error_fatal); + MemoryRegion* dport_mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dport), 0); + + memory_region_add_subregion(sys_mem, DR_REG_DPORT_BASE, dport_mem); + qdev_connect_gpio_out_named(DEVICE(&s->dport), ESP32_DPORT_APPCPU_RESET_GPIO, 0, + qdev_get_gpio_in_named(dev, ESP32_RTC_CPU_RESET_GPIO, 1)); + qdev_connect_gpio_out_named(DEVICE(&s->dport), ESP32_DPORT_APPCPU_STALL_GPIO, 0, + qdev_get_gpio_in_named(dev, ESP32_RTC_CPU_STALL_GPIO, 1)); + qdev_connect_gpio_out_named(DEVICE(&s->rtc_cntl), ESP32_DPORT_CLK_UPDATE_GPIO, 0, + qdev_get_gpio_in_named(dev, ESP32_RTC_CLK_UPDATE_GPIO, 0)); + + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + char name[16]; + snprintf(name, sizeof(name), "cpu%d", i); + object_property_set_link(OBJECT(&s->intmatrix), name, OBJECT(qemu_get_cpu(i)), &error_abort); + } + qdev_realize(DEVICE(&s->intmatrix), &s->periph_bus, &error_fatal); + DeviceState* intmatrix_dev = DEVICE(&s->intmatrix); + memory_region_add_subregion_overlap(dport_mem, ESP32_DPORT_PRO_INTMATRIX_BASE, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->intmatrix), 0), -1); + + bool init_cache_err = false; + if (s->dport.flash_blk) { + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + Esp32CacheRegionState *drom0 = &s->dport.cache_state[i].drom0; + memory_region_add_subregion_overlap(&s->cpu_specific_mem[i], drom0->base, &drom0->illegal_access_trap_mem, -2); + memory_region_add_subregion_overlap(&s->cpu_specific_mem[i], drom0->base, &drom0->mem, -1); + Esp32CacheRegionState *iram0 = &s->dport.cache_state[i].iram0; + memory_region_add_subregion_overlap(&s->cpu_specific_mem[i], iram0->base, &iram0->illegal_access_trap_mem, -2); + memory_region_add_subregion_overlap(&s->cpu_specific_mem[i], iram0->base, &iram0->mem, -1); + } + init_cache_err = true; + } + if (s->dport.has_psram) { + for (int i = 0; i < ESP32_CPU_COUNT; ++i) { + Esp32CacheRegionState *dram1 = &s->dport.cache_state[i].dram1; + memory_region_add_subregion_overlap(&s->cpu_specific_mem[i], dram1->base, &dram1->illegal_access_trap_mem, -2); + memory_region_add_subregion_overlap(&s->cpu_specific_mem[i], dram1->base, &dram1->mem, -1); + } + init_cache_err = true; + } + if (init_cache_err) { + qdev_connect_gpio_out_named(DEVICE(&s->dport), ESP32_DPORT_CACHE_ILL_IRQ_GPIO, 0, + qdev_get_gpio_in(DEVICE(&s->intmatrix), ETS_CACHE_IA_INTR_SOURCE)); + } + + int n_crosscore_irqs = ESP32_DPORT_CROSSCORE_INT_COUNT; + object_property_set_int(OBJECT(&s->crosscore_int), "n_irqs", n_crosscore_irqs, &error_abort); + qdev_realize(DEVICE(&s->crosscore_int), &s->periph_bus, &error_fatal); + memory_region_add_subregion_overlap(dport_mem, ESP32_DPORT_CROSSCORE_INT_BASE, &s->crosscore_int.iomem, -1); + + for (int index = 0; index < ESP32_DPORT_CROSSCORE_INT_COUNT; ++index) { + qemu_irq target = qdev_get_gpio_in(DEVICE(&s->intmatrix), ETS_FROM_CPU_INTR0_SOURCE + index); + assert(target); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->crosscore_int), index, target); + } + + qdev_realize(DEVICE(&s->rsa), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->rsa, DR_REG_RSA_BASE); + + qdev_realize(DEVICE(&s->sha), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->sha, DR_REG_SHA_BASE); + + qdev_realize(DEVICE(&s->aes), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->aes, DR_REG_AES_BASE); + + qdev_realize(DEVICE(&s->ledc), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->ledc, DR_REG_LEDC_BASE); + + qdev_realize(DEVICE(&s->rtc_cntl), &s->rtc_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->rtc_cntl, DR_REG_RTCCNTL_BASE); + + qdev_connect_gpio_out_named(DEVICE(&s->rtc_cntl), ESP32_RTC_DIG_RESET_GPIO, 0, + qdev_get_gpio_in_named(dev, ESP32_RTC_DIG_RESET_GPIO, 0)); + qdev_connect_gpio_out_named(DEVICE(&s->rtc_cntl), ESP32_RTC_CLK_UPDATE_GPIO, 0, + qdev_get_gpio_in_named(dev, ESP32_RTC_CLK_UPDATE_GPIO, 0)); + for (int i = 0; i < ms->smp.cpus; ++i) { + qdev_connect_gpio_out_named(DEVICE(&s->rtc_cntl), ESP32_RTC_CPU_RESET_GPIO, i, + qdev_get_gpio_in_named(dev, ESP32_RTC_CPU_RESET_GPIO, i)); + qdev_connect_gpio_out_named(DEVICE(&s->rtc_cntl), ESP32_RTC_CPU_STALL_GPIO, i, + qdev_get_gpio_in_named(dev, ESP32_RTC_CPU_STALL_GPIO, i)); + } + + qdev_realize(DEVICE(&s->gpio), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->gpio, DR_REG_GPIO_BASE); + + for (int i = 0; i < ESP32_UART_COUNT; ++i) { + const hwaddr uart_base[] = {DR_REG_UART_BASE, DR_REG_UART1_BASE, DR_REG_UART2_BASE}; + qdev_realize(DEVICE(&s->uart[i]), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->uart[i], uart_base[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_UART0_INTR_SOURCE + i)); + } + + for (int i = 0; i < ESP32_FRC_COUNT; ++i) { + qdev_realize(DEVICE(&s->frc_timer[i]), &s->periph_bus, &error_fatal); + + esp32_soc_add_periph_device(sys_mem, &s->frc_timer[i], DR_REG_FRC_TIMER_BASE + i * ESP32_FRC_TIMER_STRIDE); + + sysbus_connect_irq(SYS_BUS_DEVICE(&s->frc_timer[i]), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_TIMER1_INTR_SOURCE + i)); + } + + for (int i = 0; i < ESP32_TIMG_COUNT; ++i) { + s->timg[i].id = i; + + const hwaddr timg_base[] = {DR_REG_TIMERGROUP0_BASE, DR_REG_TIMERGROUP1_BASE}; + qdev_realize(DEVICE(&s->timg[i]), &s->periph_bus, &error_fatal); + + esp32_soc_add_periph_device(sys_mem, &s->timg[i], timg_base[i]); + + int timg_level_int[] = { ETS_TG0_T0_LEVEL_INTR_SOURCE, ETS_TG1_T0_LEVEL_INTR_SOURCE }; + int timg_edge_int[] = { ETS_TG0_T0_EDGE_INTR_SOURCE, ETS_TG1_T0_EDGE_INTR_SOURCE }; + for (Esp32TimgInterruptType it = TIMG_T0_INT; it < TIMG_INT_MAX; ++it) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->timg[i]), it, qdev_get_gpio_in(intmatrix_dev, timg_level_int[i] + it)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->timg[i]), TIMG_INT_MAX + it, qdev_get_gpio_in(intmatrix_dev, timg_edge_int[i] + it)); + } + + qdev_connect_gpio_out_named(DEVICE(&s->timg[i]), ESP32_TIMG_WDT_CPU_RESET_GPIO, 0, + qdev_get_gpio_in_named(dev, ESP32_TIMG_WDT_CPU_RESET_GPIO, i)); + qdev_connect_gpio_out_named(DEVICE(&s->timg[i]), ESP32_TIMG_WDT_SYS_RESET_GPIO, 0, + qdev_get_gpio_in_named(dev, ESP32_TIMG_WDT_SYS_RESET_GPIO, i)); + } + s->timg[0].wdt_en_at_reset = true; + + for (int i = 0; i < ESP32_SPI_COUNT; ++i) { + const hwaddr spi_base[] = { + DR_REG_SPI0_BASE, DR_REG_SPI1_BASE, DR_REG_SPI2_BASE, DR_REG_SPI3_BASE + }; + qdev_realize(DEVICE(&s->spi[i]), &s->periph_bus, &error_fatal); + + esp32_soc_add_periph_device(sys_mem, &s->spi[i], spi_base[i]); + + sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_SPI0_INTR_SOURCE + i)); + } + + for (int i = 0; i < ESP32_I2C_COUNT; i++) { + const hwaddr i2c_base[] = { + DR_REG_I2C_EXT_BASE, DR_REG_I2C1_EXT_BASE + }; + qdev_realize(DEVICE(&s->i2c[i]), &s->periph_bus, &error_fatal); + + esp32_soc_add_periph_device(sys_mem, &s->i2c[i], i2c_base[i]); + + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_I2C_EXT0_INTR_SOURCE + i)); + } + + qdev_realize(DEVICE(&s->rng), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->rng, ESP32_RNG_BASE); + + qdev_realize(DEVICE(&s->efuse), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->efuse, DR_REG_EFUSE_BASE); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->efuse), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_EFUSE_INTR_SOURCE)); + + qdev_realize(DEVICE(&s->flash_enc), &s->periph_bus, &error_abort); + esp32_soc_add_periph_device(sys_mem, &s->flash_enc, DR_REG_SPI_ENCRYPT_BASE); + + qdev_connect_gpio_out_named(DEVICE(&s->efuse), ESP32_EFUSE_UPDATE_GPIO, 0, + qdev_get_gpio_in_named(DEVICE(&s->flash_enc), ESP32_FLASH_ENCRYPTION_EFUSE_UPDATE_GPIO, 0)); + qdev_connect_gpio_out_named(DEVICE(&s->dport), ESP32_DPORT_FLASH_ENC_EN_GPIO, 0, + qdev_get_gpio_in_named(DEVICE(&s->flash_enc), ESP32_FLASH_ENCRYPTION_ENC_EN_GPIO, 0)); + qdev_connect_gpio_out_named(DEVICE(&s->dport), ESP32_DPORT_FLASH_DEC_EN_GPIO, 0, + qdev_get_gpio_in_named(DEVICE(&s->flash_enc), ESP32_FLASH_ENCRYPTION_DEC_EN_GPIO, 0)); + + qdev_realize(DEVICE(&s->sdmmc), &s->periph_bus, &error_abort); + esp32_soc_add_periph_device(sys_mem, &s->sdmmc, DR_REG_SDMMC_BASE); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdmmc), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_SDIO_HOST_INTR_SOURCE)); + + esp32_soc_add_unimp_device(sys_mem, "esp32.analog", DR_REG_ANA_BASE, 0x1000); + esp32_soc_add_unimp_device(sys_mem, "esp32.rtcio", DR_REG_RTCIO_BASE, 0x400); + esp32_soc_add_unimp_device(sys_mem, "esp32.rtcio", DR_REG_SENS_BASE, 0x400); + esp32_soc_add_unimp_device(sys_mem, "esp32.iomux", DR_REG_IO_MUX_BASE, 0x2000); + esp32_soc_add_unimp_device(sys_mem, "esp32.hinf", DR_REG_HINF_BASE, 0x1000); + esp32_soc_add_unimp_device(sys_mem, "esp32.slc", DR_REG_SLC_BASE, 0x1000); + esp32_soc_add_unimp_device(sys_mem, "esp32.slchost", DR_REG_SLCHOST_BASE, 0x1000); + esp32_soc_add_unimp_device(sys_mem, "esp32.apbctrl", DR_REG_APB_CTRL_BASE, 0x1000); + esp32_soc_add_unimp_device(sys_mem, "esp32.i2s0", DR_REG_I2S_BASE, 0x1000); + esp32_soc_add_unimp_device(sys_mem, "esp32.i2s1", DR_REG_I2S1_BASE, 0x1000); + esp32_soc_add_unimp_device(sys_mem, "esp32.rmt", DR_REG_RMT_BASE, 0x1000); + esp32_soc_add_unimp_device(sys_mem, "esp32.pcnt", DR_REG_PCNT_BASE, 0x1000); + + /* Emulation of APB_CTRL_DATE_REG, needed for ECO3 revision detection. + * This is a small hack to avoid creating a whole new device just to emulate one + * register. + */ + const hwaddr apb_ctrl_date_reg = DR_REG_APB_CTRL_BASE + 0x7c; + MemoryRegion *apbctrl_mem = g_new(MemoryRegion, 1); + memory_region_init_ram(apbctrl_mem, NULL, "esp32.apbctrl_date_reg", 4 /* bytes */, &error_fatal); + memory_region_add_subregion(sys_mem, apb_ctrl_date_reg, apbctrl_mem); + uint32_t apb_ctrl_date_reg_val = 0x16042000 | 0x80000000; /* MSB indicates ECO3 silicon revision */ + cpu_physical_memory_write(apb_ctrl_date_reg, &apb_ctrl_date_reg_val, 4); + + qemu_register_reset((QEMUResetHandler*) esp32_soc_reset, dev); +} + +static void esp32_soc_init(Object *obj) +{ + Esp32SocState *s = ESP32_SOC(obj); + MachineState *ms = MACHINE(qdev_get_machine()); + char name[16]; + + MemoryRegion *system_memory = get_system_memory(); + + qbus_init(&s->periph_bus, sizeof(s->periph_bus), + TYPE_SYSTEM_BUS, DEVICE(s), "esp32-periph-bus"); + qbus_init(&s->rtc_bus, sizeof(s->rtc_bus), + TYPE_SYSTEM_BUS, DEVICE(s), "esp32-rtc-bus"); + + for (int i = 0; i < ms->smp.cpus; ++i) { + snprintf(name, sizeof(name), "cpu%d", i); + object_initialize_child(obj, name, &s->cpu[i], TYPE_ESP32_CPU); + + const uint32_t cpuid[ESP32_CPU_COUNT] = { 0xcdcd, 0xabab }; + s->cpu[i].env.sregs[PRID] = cpuid[i]; + + snprintf(name, sizeof(name), "cpu%d-mem", i); + memory_region_init(&s->cpu_specific_mem[i], NULL, name, UINT32_MAX); + + CPUState* cs = CPU(&s->cpu[i]); + cs->num_ases = 1; + cpu_address_space_init(cs, 0, "cpu-memory", &s->cpu_specific_mem[i]); + + MemoryRegion *cpu_view_sysmem = g_new(MemoryRegion, 1); + snprintf(name, sizeof(name), "cpu%d-sysmem", i); + memory_region_init_alias(cpu_view_sysmem, NULL, name, system_memory, 0, UINT32_MAX); + memory_region_add_subregion_overlap(&s->cpu_specific_mem[i], 0, cpu_view_sysmem, 0); + cs->memory = &s->cpu_specific_mem[i]; + } + + for (int i = 0; i < ESP32_UART_COUNT; ++i) { + snprintf(name, sizeof(name), "uart%d", i); + object_initialize_child(obj, name, &s->uart[i], TYPE_ESP32_UART); + } + + object_property_add_alias(obj, "serial0", OBJECT(&s->uart[0]), "chardev"); + object_property_add_alias(obj, "serial1", OBJECT(&s->uart[1]), "chardev"); + object_property_add_alias(obj, "serial2", OBJECT(&s->uart[2]), "chardev"); + + object_initialize_child(obj, "gpio", &s->gpio, TYPE_ESP32_GPIO); + + object_initialize_child(obj, "dport", &s->dport, TYPE_ESP32_DPORT); + + object_initialize_child(obj, "intmatrix", &s->intmatrix, TYPE_ESP32_INTMATRIX); + + object_initialize_child(obj, "crosscore_int", &s->crosscore_int, TYPE_ESP32_CROSSCORE_INT); + + object_initialize_child(obj, "rtc_cntl", &s->rtc_cntl, TYPE_ESP32_RTC_CNTL); + + for (int i = 0; i < ESP32_FRC_COUNT; ++i) { + snprintf(name, sizeof(name), "frc%d", i); + object_initialize_child(obj, name, &s->frc_timer[i], TYPE_ESP32_FRC_TIMER); + } + + for (int i = 0; i < ESP32_TIMG_COUNT; ++i) { + snprintf(name, sizeof(name), "timg%d", i); + object_initialize_child(obj, name, &s->timg[i], TYPE_ESP32_TIMG); + } + + for (int i = 0; i < ESP32_SPI_COUNT; ++i) { + snprintf(name, sizeof(name), "spi%d", i); + object_initialize_child(obj, name, &s->spi[i], TYPE_ESP32_SPI); + } + + for (int i = 0; i < ESP32_I2C_COUNT; ++i) { + snprintf(name, sizeof(name), "i2c%d", i); + object_initialize_child(obj, name, &s->i2c[i], TYPE_ESP32_I2C); + } + + object_initialize_child(obj, "rng", &s->rng, TYPE_ESP32_RNG); + + object_initialize_child(obj, "sha", &s->sha, TYPE_ESP32_SHA); + + object_initialize_child(obj, "aes", &s->aes, TYPE_ESP32_AES); + + object_initialize_child(obj, "ledc", &s->ledc, TYPE_ESP32_LEDC); + + object_initialize_child(obj, "rsa", &s->rsa, TYPE_ESP32_RSA); + + object_initialize_child(obj, "efuse", &s->efuse, TYPE_ESP32_EFUSE); + + object_initialize_child(obj, "flash_enc", &s->flash_enc, TYPE_ESP32_FLASH_ENCRYPTION); + + object_initialize_child(obj, "sdmmc", &s->sdmmc, TYPE_DWC_SDMMC); + + qdev_init_gpio_in_named(DEVICE(s), esp32_dig_reset, ESP32_RTC_DIG_RESET_GPIO, 1); + qdev_init_gpio_in_named(DEVICE(s), esp32_cpu_reset, ESP32_RTC_CPU_RESET_GPIO, ESP32_CPU_COUNT); + qdev_init_gpio_in_named(DEVICE(s), esp32_cpu_stall, ESP32_RTC_CPU_STALL_GPIO, ESP32_CPU_COUNT); + qdev_init_gpio_in_named(DEVICE(s), esp32_clk_update, ESP32_RTC_CLK_UPDATE_GPIO, 1); + qdev_init_gpio_in_named(DEVICE(s), esp32_timg_cpu_reset, ESP32_TIMG_WDT_CPU_RESET_GPIO, 2); + qdev_init_gpio_in_named(DEVICE(s), esp32_timg_sys_reset, ESP32_TIMG_WDT_SYS_RESET_GPIO, 2); +} + +static Property esp32_soc_properties[] = { + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32_soc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = esp32_soc_realize; + device_class_set_props(dc, esp32_soc_properties); +} + +static const TypeInfo esp32_soc_info = { + .name = TYPE_ESP32_SOC, + .parent = TYPE_DEVICE, + .instance_size = sizeof(Esp32SocState), + .instance_init = esp32_soc_init, + .class_init = esp32_soc_class_init +}; + +static void esp32_soc_register_types(void) +{ + type_register_static(&esp32_soc_info); +} + +type_init(esp32_soc_register_types) + + +static uint64_t translate_phys_addr(void *opaque, uint64_t addr) +{ + XtensaCPU *cpu = opaque; + + return cpu_get_phys_page_debug(CPU(cpu), addr); +} + + +struct Esp32MachineState { + MachineState parent; + + Esp32SocState esp32; + DeviceState *flash_dev; +}; +#define TYPE_ESP32_MACHINE MACHINE_TYPE_NAME("esp32") + +OBJECT_DECLARE_SIMPLE_TYPE(Esp32MachineState, ESP32_MACHINE) + + +static void esp32_machine_init_spi_flash(Esp32SocState *ss, BlockBackend* blk) +{ + /* "main" flash chip is attached to SPI1, CS0 */ + DeviceState *spi_master = DEVICE(&ss->spi[1]); + BusState* spi_bus = qdev_get_child_bus(spi_master, "spi"); + + /* select the flash chip based on the image size */ + int64_t image_size = blk_getlength(blk); + const char* flash_chip_model = NULL; + switch (image_size) { + case 2 * 1024 * 1024: flash_chip_model = "w25x16"; break; + case 4 * 1024 * 1024: flash_chip_model = "gd25q32"; break; + case 8 * 1024 * 1024: flash_chip_model = "gd25q64"; break; + case 16 * 1024 * 1024: flash_chip_model = "is25lp128"; break; + default: error_report("Error: only 2, 4, 8, 16 MB flash images are supported"); return; + } + + DeviceState *flash_dev = qdev_new(flash_chip_model); + qdev_prop_set_drive(flash_dev, "drive", blk); + qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal); + qdev_connect_gpio_out_named(spi_master, SSI_GPIO_CS, 0, + qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0)); +} + +static void esp32_machine_init_psram(Esp32SocState *ss, uint32_t size_mbytes) +{ + /* PSRAM attached to SPI1, CS1 */ + DeviceState *spi_master = DEVICE(&ss->spi[1]); + BusState* spi_bus = qdev_get_child_bus(spi_master, "spi"); + DeviceState *psram = qdev_new(TYPE_SSI_PSRAM); + qdev_prop_set_uint32(psram, "size_mbytes", size_mbytes); + qdev_realize_and_unref(psram, spi_bus, &error_fatal); + qdev_connect_gpio_out_named(spi_master, SSI_GPIO_CS, 1, + qdev_get_gpio_in_named(psram, SSI_GPIO_CS, 0)); +} + +static void esp32_machine_init_i2c(Esp32SocState *s) +{ + /* It should be possible to create an I2C device from the command line, + * however for this to work the I2C bus must be reachable from sysbus-default. + * At the moment the peripherals are added to an unrelated bus, to avoid being + * reset on CPU reset. + * If we find a way to decouple peripheral reset from sysbus reset, + * we can move them to the sysbus and thus enable creation of i2c devices. + */ + DeviceState *i2c_master = DEVICE(&s->i2c[0]); + I2CBus* i2c_bus = I2C_BUS(qdev_get_child_bus(i2c_master, "i2c")); + I2CSlave* tmp105 = i2c_slave_create_simple(i2c_bus, "tmp105", 0x48); + object_property_set_int(OBJECT(tmp105), "temperature", 25 * 1000, &error_fatal); +} + +static void esp32_machine_init_openeth(Esp32SocState *ss) +{ + SysBusDevice *sbd; + NICInfo *nd = &nd_table[0]; + MemoryRegion* sys_mem = get_system_memory(); + hwaddr reg_base = DR_REG_EMAC_BASE; + hwaddr desc_base = reg_base + 0x400; + qemu_irq irq = qdev_get_gpio_in(DEVICE(&ss->intmatrix), ETS_ETH_MAC_INTR_SOURCE); + + const char* type_openeth = "open_eth"; + if (nd->used && nd->model && strcmp(nd->model, type_openeth) == 0) { + DeviceState* open_eth_dev = qdev_new(type_openeth); + ss->eth = open_eth_dev; + qdev_set_nic_properties(open_eth_dev, nd); + sbd = SYS_BUS_DEVICE(open_eth_dev); + sysbus_realize_and_unref(sbd, &error_fatal); + sysbus_connect_irq(sbd, 0, irq); + memory_region_add_subregion(sys_mem, reg_base, sysbus_mmio_get_region(sbd, 0)); + memory_region_add_subregion(sys_mem, desc_base, sysbus_mmio_get_region(sbd, 1)); + } +} + +static void esp32_machine_init_sd(Esp32SocState *ss) +{ + DriveInfo *dinfo = drive_get(IF_SD, 0, 0); + if (dinfo) { + DeviceState *card; + + card = qdev_new(TYPE_SD_CARD); + qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), + &error_fatal); + /* See the comment on not using sysbus-default in esp32_machine_init_i2c */ + DeviceState *sdmmc = DEVICE(&ss->sdmmc); + SDBus* sd_bus = SD_BUS(qdev_get_child_bus(sdmmc, "sd-bus")); + qdev_realize_and_unref(card, BUS(sd_bus), &error_fatal); + } +} + +static void esp32_machine_init(MachineState *machine) +{ + BlockBackend* blk = NULL; + DriveInfo *dinfo = drive_get(IF_MTD, 0, 0); + if (dinfo) { + qemu_log("Adding SPI flash device\n"); + blk = blk_by_legacy_dinfo(dinfo); + } else { + qemu_log("Not initializing SPI Flash\n"); + } + + Esp32MachineState *ms = ESP32_MACHINE(machine); + object_initialize_child(OBJECT(ms), "soc", &ms->esp32, TYPE_ESP32_SOC); + Esp32SocState *ss = ESP32_SOC(&ms->esp32); + + if (blk) { + ss->dport.flash_blk = blk; + } + qdev_prop_set_chr(DEVICE(ss), "serial0", serial_hd(0)); + qdev_prop_set_chr(DEVICE(ss), "serial1", serial_hd(1)); + qdev_prop_set_chr(DEVICE(ss), "serial2", serial_hd(2)); + if (machine->ram_size > 0) { + qdev_prop_set_bit(DEVICE(&ss->dport), "has_psram", true); + } + + qdev_realize(DEVICE(ss), NULL, &error_fatal); + + if (blk) { + esp32_machine_init_spi_flash(ss, blk); + } + + if (machine->ram_size > 0) { + esp32_machine_init_psram(ss, (uint32_t) (machine->ram_size / MiB)); + } + + esp32_machine_init_i2c(ss); + + esp32_machine_init_openeth(ss); + + esp32_machine_init_sd(ss); + + /* Need MMU initialized prior to ELF loading, + * so that ELF gets loaded into virtual addresses + */ + cpu_reset(CPU(&ss->cpu[0])); + + const char *load_elf_filename = NULL; + if (machine->firmware) { + load_elf_filename = machine->firmware; + } + if (machine->kernel_filename) { + qemu_log("Warning: both -bios and -kernel arguments specified. Only loading the the -kernel file.\n"); + load_elf_filename = machine->kernel_filename; + } + + if (load_elf_filename) { + uint64_t elf_entry; + uint64_t elf_lowaddr; + int size = load_elf(load_elf_filename, NULL, + translate_phys_addr, &ss->cpu[0], + &elf_entry, &elf_lowaddr, + NULL, NULL, 0, EM_XTENSA, 0, 0); + if (size < 0) { + error_report("Error: could not load ELF file '%s'", load_elf_filename); + exit(1); + } + + if (elf_entry != XCHAL_RESET_VECTOR_PADDR) { + // Since ROM is empty when loading elf file AND + // PC value is 0x40000400 after reset + // need to jump to elf entry point to run a programm + uint8_t p[4]; + memcpy(p, &elf_entry, 4); + uint8_t boot[] = { + 0x06, 0x01, 0x00, /* j 1 */ + 0x00, /* .literal_position */ + p[0], p[1], p[2], p[3], /* .literal elf_entry */ + /* 1: */ + 0x01, 0xff, 0xff, /* l32r a0, elf_entry */ + 0xa0, 0x00, 0x00, /* jx a0 */ + }; + // Write boot function to reset-vector address (0x40000400) of the CPU 0 + rom_add_blob_fixed_as("boot", boot, sizeof(boot), XCHAL_RESET_VECTOR_PADDR, CPU(&ss->cpu[0])->as); + ss->cpu[0].env.pc = XCHAL_RESET_VECTOR_PADDR; + } + } else { + char *rom_binary = qemu_find_file(QEMU_FILE_TYPE_BIOS, "esp32-v3-rom.bin"); + if (rom_binary == NULL) { + error_report("Error: -bios argument not set, and ROM code binary not found (1)"); + exit(1); + } + + int size = load_image_targphys_as(rom_binary, esp32_memmap[ESP32_MEMREGION_IROM].base, esp32_memmap[ESP32_MEMREGION_IROM].size, CPU(&ss->cpu[0])->as); + if (size < 0) { + error_report("Error: could not load ROM binary '%s'", rom_binary); + exit(1); + } + g_free(rom_binary); + + rom_binary = qemu_find_file(QEMU_FILE_TYPE_BIOS, "esp32-v3-rom-app.bin"); + if (rom_binary == NULL) { + error_report("Error: -bios argument not set, and ROM code binary not found (2)"); + exit(1); + } + + size = load_image_targphys_as(rom_binary, esp32_memmap[ESP32_MEMREGION_IROM].base, esp32_memmap[ESP32_MEMREGION_IROM].size, CPU(&ss->cpu[1])->as); + if (size < 0) { + error_report("Error: could not load ROM binary '%s'", rom_binary); + exit(1); + } + g_free(rom_binary); + } +} + +static ram_addr_t esp32_fixup_ram_size(ram_addr_t requested_size) +{ + ram_addr_t size; + if (requested_size == 0) { + size = 0; + } else if (requested_size <= 2 * MiB) { + size = 2 * MiB; + } else if (requested_size <= 4 * MiB ) { + size = 4 * MiB; + } else { + qemu_log("RAM size larger than 4 MB not supported\n"); + size = 4 * MiB; + } + return size; +} + +/* Initialize machine type */ +static void esp32_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + mc->desc = "Espressif ESP32 machine"; + mc->init = esp32_machine_init; + mc->max_cpus = 2; + mc->default_cpus = 2; + mc->default_ram_size = 0; + mc->fixup_ram_size = esp32_fixup_ram_size; +} + +static const TypeInfo esp32_info = { + .name = TYPE_ESP32_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(Esp32MachineState), + .class_init = esp32_machine_class_init, +}; + +static void esp32_machine_type_init(void) +{ + type_register_static(&esp32_info); +} + +type_init(esp32_machine_type_init); diff --git a/hw/xtensa/meson.build b/hw/xtensa/meson.build index 1d5835df4bf4..695f15bd4271 100644 --- a/hw/xtensa/meson.build +++ b/hw/xtensa/meson.build @@ -7,5 +7,6 @@ xtensa_ss.add(files( xtensa_ss.add(when: 'CONFIG_XTENSA_SIM', if_true: files('sim.c')) xtensa_ss.add(when: 'CONFIG_XTENSA_VIRT', if_true: files('virt.c')) xtensa_ss.add(when: 'CONFIG_XTENSA_XTFPGA', if_true: files('xtfpga.c')) +xtensa_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32.c', 'esp32_intc.c')) hw_arch += {'xtensa': xtensa_ss} diff --git a/include/hw/xtensa/esp32.h b/include/hw/xtensa/esp32.h new file mode 100644 index 000000000000..6097a362538f --- /dev/null +++ b/include/hw/xtensa/esp32.h @@ -0,0 +1,58 @@ +#pragma once + +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "target/xtensa/cpu.h" +#include "hw/misc/esp32_reg.h" +#include "hw/char/esp32_uart.h" +#include "hw/gpio/esp32_gpio.h" +#include "hw/misc/esp32_dport.h" +#include "hw/misc/esp32_rtc_cntl.h" +#include "hw/misc/esp32_rng.h" +#include "hw/misc/esp32_sha.h" +#include "hw/misc/esp32_aes.h" +#include "hw/misc/esp32_ledc.h" +#include "hw/misc/esp32_rsa.h" +#include "hw/timer/esp32_frc_timer.h" +#include "hw/timer/esp32_timg.h" +#include "hw/misc/esp32_crosscore_int.h" +#include "hw/ssi/esp32_spi.h" +#include "hw/i2c/esp32_i2c.h" +#include "hw/nvram/esp32_efuse.h" +#include "hw/xtensa/esp32_intc.h" +#include "hw/misc/esp32_flash_enc.h" +#include "hw/sd/dwc_sdmmc.h" + +typedef struct Esp32SocState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + XtensaCPU cpu[ESP32_CPU_COUNT]; + Esp32DportState dport; + Esp32IntMatrixState intmatrix; + Esp32CrosscoreInt crosscore_int; + ESP32UARTState uart[ESP32_UART_COUNT]; + Esp32GpioState gpio; + Esp32RngState rng; + Esp32RtcCntlState rtc_cntl; + Esp32FrcTimerState frc_timer[ESP32_FRC_COUNT]; + Esp32TimgState timg[ESP32_TIMG_COUNT]; + Esp32SpiState spi[ESP32_SPI_COUNT]; + Esp32I2CState i2c[ESP32_I2C_COUNT]; + Esp32ShaState sha; + Esp32AesState aes; + Esp32RsaState rsa; + Esp32LEDCState ledc; + Esp32EfuseState efuse; + Esp32FlashEncryptionState flash_enc; + DWCSDMMCState sdmmc; + DeviceState *eth; + + BusState rtc_bus; + BusState periph_bus; + + MemoryRegion cpu_specific_mem[ESP32_CPU_COUNT]; + + uint32_t requested_reset; +} Esp32SocState; diff --git a/pc-bios/esp32-v3-rom-app.bin b/pc-bios/esp32-v3-rom-app.bin new file mode 100755 index 0000000000000000000000000000000000000000..ea8b05d465b0cfab0cd0619c12692a895ab6cb0e GIT binary patch literal 455722 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�&CnZ4?Yj()#W;nNadds=Sj@N?=rImTmNEw;cXS>qTIur) zOq`=D=vW-*W?08-M6;QsY_VkLjFWrmD(bA;<;WPUqH9njK0N0v*O|SaMDG(KHL|YC;HEfXjkwcE} zo7kANxShvw21sgSjiXmhHPrUz;~<3T$CS^+D#@}Bd>!gabq3CBYo6J2O-wzHs5>C+ z_G9Fn0k1@<&emmAMce1iYzLh&1eH-~sWomKM**$wZ>9G%;rLA*GVn&-7d$@X=lR@Q zb@R`8^t@__X7Wn3431M8A9OS_IBVSC&ZT@Z8kN(~;LfFeGSmq}jEqkvL-iEQk^IOC zatrvK`??T8!!Iyi0Q0JGen4wbBb?IphjEvJ5qGT-(fg)&_C;f( z9m>ZAefnL=NQcx+)X0R?vZx1HfwSURw-hIyi~b?HgBoK{_Y8yL;-P8TGIKuVi=oYG zT3BW<=hMCz#;j%}GrY)fKyN`k@q}pR*Pmu{4*ylmBWs36HGrcO0Di zq2V(qpgH(EV5ez$SLX}rpu^f1G(bt`pTL?98WBK;DXZo=UCm}bsH<_KRH;t)5~?Eq zOJdFaV2y(;h;`$a$ZL>#?Ci|yoIOjus}DaEWYwEJ6ZoK}#!X@%MZobmOQAdUO9y=i zyKd7~1JZ=7H=CyRAH~V`$wbf^=+uhJ_Q#kWJL{u2q0B*zQVu!t!7?dBHNQd1sm_Dh zUtyKz`=)oJj)t1v-f>jTfnHLtO?BT@GW*}S!p1i2W^aBKyMrtsQ>mw$Ufmo^ZO*4$ z+X9>Zygk*~%(iR|Z0YEaW?EMhLSLxyhKPi>)P1#?z9Ym<*;H?6rro9qw!T|=^aVHk zC~vcMyu~`9|HE6d-jD&6=+Zz8DKvygwn@%X8!;R^x~`|z+c6v;Q#=!!_dQX29<2-i zkw{%+ybPI4m8!$`p_E?D`r$>7KLmj1dFfm7!MuR|mSxr*VLHE|eL-FS1u?E7>$(^y z(Ux123@h#BL0x7Z`b*|~(vkRzR-9>+c@MFWdKN6gMmok!$L3r!(i1FnoYAUbWoSJ? zo~8$A>JrWL(y|aOZ>1GJTIr@$4q9DKvle=snI3PnYN2^cHy;YZwD@ukCs_2&H{nag z@YmX&87AFNbi6eojL-aG{zMnXccd_M>%urQcZTW8HQjMt7&;4J*Q5*AYwa^kMr*vT zUKjqUwh!(X!%m{y4o2NHVs|At^IGI$=0#kVN%k{?I1Zu+#_2jEr{S%M;gwneml;TU zqG5(9JO@VxRH0DW7sI()3zwiv*HvCKbMa(4)mN2s(ZVGfxrw}W5=1FL<#+I*YekrB z6;&CzNf?!u2E*a1AJ(mK)GwBUpd;BJz+Ia<2LhlLP5a=;H`&*C6KyobWM4F!#v4ts z*+JyRXo^FoZkHQP6W|+bVkV~7Bnz43m#p!e_Eq3hcDi)N1Rx-*5REqEo*eM27%J2vb$^n%sJPdp~8kPqSjHl`fy^{L_hP!;{+c!v23Ra!;l?g5Jr-nCi@N@8AH~Y%4|9e8HQD+ zqGBC}5#17#uvlldrklA$i**{tI*cZQG~AV2d80K04K6%a8jGgs99AxTrxw{ndx#8F zsI2fjZR1&th<0h@GNY?x!#&<3U6x)8FTj;FcumvIJo`gbl@}2ck47$ea|XjX+L_lP zaq`ybh%*wMo15h0k})#swPtQITB!^Ef*#If;Zn+BF-_;1t96-385~?Hx}h0Eo^)xp zPIhH$i=yTfH<#w)rXaLEYLn_(5DjRyrnwerJ(7L+n#uK3Ewl}hPJ6d@z&fMvZ|G`z z*Fr6Nuh}}K=RKX7yUlf%7Jb;l=>jKp=#B_p&P~OMHDRv_`SHA{6ZV*p8P{H25qdZZ zvmLTS4kr$9yxV%4o8wRvbVS~o?66McxoHkA-Bnfrkcz!0Y)vm?VyI!C*d zTb<><3x4suW7>Fwl{w`;{kpzbYJtOtXP7w^N4|oJA*>m^7+KG{o4F9reRTtC7e7I}K`K)(Ys>biOv1{@upox6JMybHEYXpF(bV-H5b{q3Jh z^UMPqhZk-5<*>9if#(b}Ls>je3MSJ=21oX?%)+3IF`m&yMv zblL0aRLg1_`7L~UReVnV67+K_T_xMH4~x@*<85M1<%f~Ry_tKhadm)321 zRHuJ*b1uW@$_iHAt9}A!WV3apv_(PH-jmdOeFsBzZ!XIXU`_?8WIcN$_!7=)ZDz6` zVB>ndNJx}6(#44c<+TqFB z@~qAwqxZZlZuX?ON?LphYG;FdqoNaYQD{uR%H~5yyzAF37+_byUe%ck`<>5Sl^$Cy z$h(}fC}}o(%S1-Gn5s-l>KuKDPMgFgt(s4>O58B-XW0EaGVzFuI<{9eD|gP9H`BIH zLtguiKcq9n+4~XK`%d>zTH=1s&=$vgVjwrv48` zoTde97G!rOQroViuC%X&dJx(zqo7{|`ji|vIB^b6uN()}A+l{a{9M~aBY zTzJH3Bv5<}@4FNQa|%`}aT}c8Nm2L5+^yC<9Y{O2bEerzBTKcVNv{u*2dQV2-M`kY z44|mc=E%*v5zK>#o0a-BgRaJAeEsjlVZ^v0BEL-C{7F*zKIIybjedLLp4i`CdkHvS{ zWP=8Ur2_QBdl~MAXqe;DGq_9ed{T$3S&odbOx%$fDRIzQC(QCV0$o(b5P zmgCy}$wuxQafVuMw_i_-fzrnrYK0x@Pu@}Uo-na~%2ZI#hKR{wnpJPFmeU8-l=d}ho7_z=)=h3qIXF3H+ra+zI5r;6an1_$rO1(^$QzVB`a;=Gb*qPV=#%;) z>!oCWinLyW15=vSMMc*y-Vl`<>@7L3{pf)@rK@bv<+@(|!;VCM{UN*R7-m&PrHRLgd#2-WA|C^Yn zr3^LDdWqAWP~@TxM_|Yi_=H66MCA0BPQ;D#RX+N7#Q8=C)}ZKyPxg1g6(91XWrRjtn8uMmJCWN?=y}Fj;8+zWQmbumW`v_U z+o-sMYQ9rQ&WYfj<|9)_NTcIp2BgK8)96!y3|}lwx?ikLDPkO>;v}g0i}%U zo2y-LtSxTAf@8AO+@1Tr$s0$p_uD@S%pPBt&=I?P&NJhLuLBtN>tu0G>NbHI_6Gi< zdnXRP@HmCf+yZ+_vd28lo_As+`IFWne4b>x+hnNsUYeBWpD=Arl^s zWp#9c)755jo2gba?P|FW#U`z0#%-3>)2NOD{$SmoP*|z$`8U-^MT)fcX1aghNThZ9f^#$WjV$jSW96larHmyb35$6ircXg_j9rp)+kCeS ziav3;hYnFKEVS*3rr_T?vSU8ht7ZN{vAbQ$1f2nW*G7u^;4}(JG|ly2CwhLVW|~}N zTo;o@Vv!o8`;J&(-ug)C_E0dJ-B-IWdlzifQhnIAioMGPPuxc@Z>wignM(NqPw?hS=H7oIs-gzYZBo@=;l7FmQShYrL z0v>Lx8a)5>dqvN>z3W$IL8&y(QH8fNvW$<#xRoUn#lyQG6Xy|vr7QTB3L((cOh$({qA4kcvh_llVLz7pdLX*^H2@NbP>>I#$1 z@C6m_&e8KRx|TsUW`Am8hw==Agz>ECe@VQ=X^{L2v3))*dX4XNxIQ+H@4>|%0-wjf zCCO91>90DLvF#QMtTQJ5#6Xn8LWMhqbyuUqRqyb;X|g*V;U=tG*X%xcj11=W%3VpR z{O*cXd=H7CAoz*OwiCS*a+l=R?}yy5zvmmVb`6nG|9iLO1KBjAn=dTPs2sUp#+EGE zdmH2nQTwlocgH3zi<7+LUA&Bq_Zatf>Zz@^?)`BU_KIniw?-?J;na$`Ldl z?z%Y4LZ)qg8=?$1)2SJcRp%26=4hVw6nL>mMNzO7;_BZ`>M8E?SCVl$HC9L~`<~M_>}>Eh>^ncXpow^k z$kg_G;tyhdMO|he{JZ}B9lc`oy!&9ZpW4=pG}BNthT-TG`ij^8sQAjm>?|~($3>$j zaBy1O;g82i^RknsOG@lNOw`;G6MA6Bt+RZCQCZnmj+Elbpw`AtOv;x-^ZMwOyd=^^ zNndCYlQNY!uoFWUM1Dq|@tT;FqCoSbp;$fAK;ehX2cprxA$GFx>qmWiBRTZ{0{L4_ z`Y1sHn9oHdr@2m zH!YQ@u2ogeZ1p&s>6GI(kC?P90kWal*|sM!sK+CZDNT@hlXw9KaU)Q~B9=|FJ%RjO zH#|M~UF9D&PLJ~nl^{^hd3VMf>|TKunFRHlBonc?KV&$>lBTiFcQI!~qG{1Y(~;BG z;D(HPF)5afq?xf5=|e~xI%wOA;suONL@rRAMuwzcBfYN;Pn*80Y)5)fwt6eUS4+N) z3M1p+#Sb2*JL8beU=e~LZQJ8wN$gnXA*3D6dI)KLf_nc_%3df~gjp0)33;3yu_@iQ zkHw_*R}j1-HWZxe|41wu`A6Oh=x=P2@)X2c)W01Y>ppK*AnRy<&*H(4O^DoFF^*y? zjEOMb4r97b>FPXnle>?lI`P7Hes);8L6LiB7w)lF$bB}*2*Tj9@(?CIN})S|#_>d9#!tyg4xxo*T)H^oZ0-Q#r!9BZl{u3`0G`#Yhh(E|CY@#o1e5;P3R7k z*}RBNG+RxFF><3(&Sw4Wh{bBQc!t(2w^)UH8CKzt;~9yzJ838t+_Y8akjvIs?OVW1 z!AkPrvPJipvLLtO{SVB+>`J-sRF}pil$BI#77Jz1RTtG8ET`}#cw?-_EEGLmO)U|M z9<9d949BUfPIcLOQ%z0TLx!RiruCIYs|;&OR;ODyp&)nFzN7iF(gd@0asD)mHP>vt zr*uyKVv9A;Y+X{iBL4x4HQ#JqTKb5Y%ky#fv~sy_ZgDTS^b(iv;Fegd%gok-n+let z@^C6vHB}(kORI&I22+b@u@;`TE?Zlv+%{OMz@qe;lAbLZ`!6+R>kR83wQz-+rGmY( zy6hgqvQ;D3DYM{OT20+6xK>vS_ZV8%8#H;uT$F2YRcKn)K&z5rO|FG2DCiz}bYyV) zXoAmL&>Yth^TLFi<31VxmHHXgj!#7kmuu!0uc^0idCSB#O=j*M3zxs__!_4fS>={3 z+p^{pGq=>jnU{T?dJopmEu3jsR-bTe+ADJ&TfA$<7Y}^+h}ml9L&B<~jPiNu)yA#) zIp#Lgr!kn)*kVQ;cwQ-|U6HxF46})uqBDVA3Pp?Tc=q>f|Az0_DV^lI1XX2vhx&W9 z+TN0mTTN?M_&2}Va_5?sfIMk~qQx0lr&djO61|peT*GDz{H;qU*QUWuZ<*}X92@uD zhD1ZRrz?$`Bv2jRz;Vr)@hxZecChx{EjZ)-ozaq^;e$D+Qk%}G-&mkNCTG*|@}6aH zXVE3m&hcP{$EplG(?#xMx5l|N+s$Ee&%%ssbl4oq#`LjBtWCjJ%-A3~9lfYzJ;tIm z%(gQAAfCW9p*5K1|Gju3lZ>}#n0}Xd=y5U>go0@qF7ZHnD3nHCGUGl{JHlBsTlQ1q04qHOm9SSy$yaZe$wuXv* zp4!%Tv)QyJZ~to1=V@$ey>(eCE@<_6PNg(S7Dmsh{#9bi96p$44i@9>d~QE~M+P#{CGoo=2ORl;arUAgiRzk!D%S>lp4~UOzl5*LX6!;;Cj6KYF{u z7~Hgec_sE`l}{%_xsobr$33JEDUfN`Z{YvC)=*c-)7KoQ>9%KVLweWYj`3R>gyCV$ zU~A~IUDnZ}2TSM7aX8mZ9!Xw>9d%%wB>hO?N_W;$Qi!I;x; zvxJKKGw#{#lOQLYf7x*3esS8@q(0F2m0tDm9VuxpR=iYu2m5YpZoYX3O!D8FT z!=$o&!EFCWQBzt5F`@O7d)J4<&9V%+cyDa&M`&eiYJVd3i{`CFd$*j-F7oU8XNgG* z(1?mVWc|MolTIffrq*Dwe-&;cFc*_?JDU_PGd_3`12%EYcno2*&58`YSbj3CBva9u zg81Opq42N6ZEk`T9m3&Gp42oR^$CfROGMK?E)oZtWPb(HW8t?IPN<()m`U_!Vmm)a zO2r*YOmF8RzF5*fP}F~e|Ck*zqy)D!ivDs@iQS%L@}bNqLwGf5IkGb}mOzshV2+Pw z#LmuGM<=aUN~xsTmLWe1vW+1-<9<9}pz=GI5DN4#$|nhd_TML-K%YT!>_XcE^r7}h zNOY!OiU)9yBboJ_)@9s>9qztR8p$r5u~EeN*6|+m-rJ=;^o-AQfmBLLlPx&x!(*9b z_6J~oDPrz_6J{qdH+eJO9KO}xi)?=y#%+|?>nu8d$MBN9YHrI7J+q?(#gzH~J|<0S zWw;;W(Z>JzSd#Qi&>>%2==TkGTB!0<+09D-c=1FEl0{3!gOpzvo%tYf^u&{Cm}^WG zvC_8rWOlQvKMwbEg;Iz5!wvlc8h_dAI$HtiX%sPpJQqkLr1=-39&W$~Y5rxMx(s-! z89|hi7sLub{Y%A?nvuNAk-0&Ww*$kRKNzx{sI^tIO7vp*m!a>9&3dC#6MZJF;O?%VZIvc#49)No!TEt-{2`f9rR?kZiA3A?< zL;ngf>G7~he*@|0y%yi{PVVWVCaihzcASGkPx6o?hVXP?4#cTzcLkS7(&| zIbzAo`vtgv5^*OpwT#?Lw89b|BAK^o3PBk8Yv5bb=#JE_JIo5&aTr}r_vBNLlXlBq6|2`Id z7{)$a0VoBqSI1~oXWc;Sn1^Wu-Uk?7)D^Nz_pJ8%cVeJyU)*llte`A-Z*d%REvyGu z9RCuX?N4J)@56N?rmw~2UyB#IoT_HI<9uvnmtd>6xLMKudRlG9FNSw0Nkw{#+h1>% z!(#n#B~+S}e-K+feKu|?%m_CG;#wxYe1n#yw-3tltiR)jv&t2)r+5pT#-hK8-LMs!)(vV!A={721Z${<`fn`uM7$!unf zW*PSC9{;Sd+V&cB-V{M*Wq|7K;YAOE*GFXN@HW;|R5ytWf6=TiWFM>Ue`J`Ac_KD# zcf-MkPHYe)>!tO9GY0H+d7~b^qC-``#}*u`+XG{a|CKTC0c>kdV>3#Jz4c;RoWF4l zUlw4oiN#c=1Z!AnakhhFS$`9`iy~J3eKHzLe{LCL#11tx<1^F9C3it&H(tE`=f_qb5{s0HFJx^97ZOHGzr;ywOZv#kGV$SN7_&;V@zGi`xJTqueNv_i%RX) z?~S1aNPTNh#!r9jTW|gMeaq|LJyz!>eXIYGG4ESwuxYG~ANGdEkiX4i-1unU%HSgT zdw2}HLr7;s@0luD**1;ww9ZI#{E|&P&HLWoWL!q`%NX{q{$Gx9ABdQKpi(&(J^4dl>(3gl{y$?IZ}qijvBA?#`dVZ+YP7F8 ztg#tSN`1}04x=slnmXFo{)fhZzNY+7eU0ZP{@)L5*qPzCq6J|NUQL-=zs;8Wrja+@ zPI=a^$9#*EBk#Q(>6CAAV#I7FW{oeM_%clz_AO@dRl|9uPp_AP`4+2j<LX){l@E$;N4Ec!`|UFl_8)c>Xo>;!qsVFAlKr{Nf;)u2Og( zWA0@(%LA;_=zVFEGf*xMTI8VxMu(Mp+~@EP)ihyjr@E&l5e|?Bm;?C-QV+bydv4QSzZ{}3IK#}RX zJxDMqb~tWJg-XS}HgqBhaXab98?k4iI2)^P{x60QYBnBdbQxa^@mLY_RP!c* zduk}93Ez%*>}Edm4BhKfBkdbahzc8Xry~xch3?pBhC5S^aVh|L2)N>flzPq&g@<36K6$9khMQu4dKd;IC`uHjr(pt-(#$L(#AV#+tielD0Hg zerkD320566+iK>TF^?j9z2jC^%CwPU{x+Mkazp!mpJDEMT}iH4J8 zGkpOreuaxuw=RB;i??u*>VzBFx_#E|QIPU@o=wSxK!_A9p5GIJEK6BQL~^Gj68Ae| zMdgP^C4-GMAwsY)h<;H`A!fc18WBQk@JZY%Xj=!`!>`iNiZ%WdF#envb^XVO zT0PIUA7(fBf^&=}!)8-fxyk5nhwbkpwmJRBhPZdW_XQWBt$QhypOky(hjM5AOS$Jt z>$enici%_UDf-lS1-#I$W*lmn&vduLw8(Ax>3zA#t1mdOrU4s1;&Ra+u<;uga=g;V zMckZ<%D&&MBuzs9V_oBwSB3NH4W7t`ycI~USrBO(d_~(=`fEmQ+Dw|)rW%*a_~i_= z<{7n<`Q>t6n`~UJ`_sw*+ zEQF6Nre%H-*C&fKJhZwjv2}|jmtn9Pc4xO_+``S`2=i#iS-{%LjWlK%@7m@l>YqJu$ zBMpK2pYstQ^P-^q48GlF)ob5fxZdmyph535d+jN?_`;%QpCpNj^Pm4_yCM5U!yFDO zb8*;<rQHw>0jpGJOB4A%X1@M?Zrb-guRWW&gwb%CG3D!4AJp9; zL)lD6tZ~|GJmZFZx)dzkNOqsV&gk4?Q>hXuCKSq9C3>%|LR z^I4{5pF4)i%yyIE2mOdl0m%BUVK4TVDDe^l8HDg7Lfl^$E}CXyV`_GEGE~EZJ|)#q z>C3}I)QtM@nrTzQlh5?s_v(k+r`A>~o`2FZe))pyKl5+?_LmEv{=>TC>pqWJKhKK0 zAuD@AW_Up7I7=@m-Fy$FS>bs|fxUb0edQ^7s@(ggC&#pEUJTh>Zh=Z6Xoi(c3A}YR zheIgp9`zJG>Zz=PdV9C^-!0akms`vB{9WX&#mn*9Bfi`-q?=|~Z$0~oc=1#5@TX$% zQ_*29@mW{7tt&0o6-Mj*NSC*+Ew>iAIZMS%1<&1Ia)~l>mg)GMJDsv{Ym=@k%DGi6 zQ#QxciSoO-)tRN44`Jv@-~Cl)w&gXuv@3bxx2&R*rl`zH3#7o$IC7mwr12Y# zh~*Kbh5Pq%?&of<%#y#bJpXQY{!e}Ri#o{`8Y6fAp+|UbE%rQTN47WjUjJ`>U=SoMem#xMo_4~>m)mXUFqK7nPt90b$&O_46 zoyVj|@MhSzqs5!=Z3(+4;Ucb~;-MG&{O)MC94k-jjY+`9ax%*d^=Sl4v^6)$&I zEcj%Ev=R$fY~)rqz=*=EM40v6YwAe@;_h>kA}%LaCB~D28(}$%(Ykv5@rJKU-ukGV zTjAh}%d)GCxlEbiQDZJ$mW^M^o?V5AjJZlXu~gWJrQAil#kz=1jEmT)iTrY9_sfjA z6AZ+0d=YURS414y0I`V=5F2fP*l1daO;QW7nb<;X68nfvN*}SA+(&GZ9l5F=B%T`= z%1vm^opdQTwKsRFG559};%7<^@sozJG_rr=g_{^1q<7D@uA3H5pz|kKsAf|&TAi)> zrsvMU2P@Fl$N(`vU77T)3fr=%yX6M^VEIdSY=PMMx(Y7}>Th;VqFis8T&~={ZmlDj zeBqsqbO-CxQ}*ZWzK5{&a&%o?xB#zc`qvC8aVXa82~W_P69JbPXg^MZU2O*zH9Qnf)6D}x73|ihDAee00R(NqO+a5nbh!ITrN^>zxiA{ z*@i;4o4j^2X~FfE6Pdifko_!V!R>f-t660K)h=dN{4Rc%aof-?GYZ6F-DnDc=Za1C zs$Fz-Nw}HWs@|&F#r3JExTjgwF6|B+43_jVg~@l>>$)@Y{&_=A?auuRo%D&V7ZSYh zg%5|t#@NDby_pJ}UW4g=Bh$SAiWzZ8WPDC68=DjVimZ`uGp07Z!XG@I@QQH<#+K@Z zVe(kgg_mFWUU}J^)Ge#_H<0HW6Lle>`cGk;>Ecu${!nz5hCIK*Q=%1%7#b*gGngDh?kNEg6cC=Pf+9 zl`^dI;l1HJ4O+zfXPG<>IjvNzt4pX<1)Ie3>B=HcR#D4fujd1-%D~~-iPoLr;EQ4< zaj2}2oc;=@jfzr5$y+z_5^ze(1%*=;d|q@`HbZBEuGe#!l!3>D!nunt`P*sB028_V)?C;*_jw$y(Wxv4&d^rSWG@?q&5127ffK`q)OkZrU!XIW#oX^Sf{- zrl^;rf;q zKqO0JcFFVkY$Lw);gRp9q=Aw4l~_F~T2!MH=blKMvRfr0@eOqkWj%E(zG;#8ven(P zrSUoPrRpDJWz0XcLF9xs^7`-_3NCQPUnZu1;9y^%vNWZO@)nkkQG?!w<3#AO`5jW%QcJ&RwW z?~Rm)d}ms-7hy0H+TWnUJgD+3NQR7ck+poJfefV$&B&%_GrDvWk?+vMQlIdSiEJHa zMC8Fc&e?Lx)Y3Bd^y&6?Jn6uu{X}~`z8|Pie=2RBR&SQVa6kR#FlvPHdGH0lK$;1| z);RQLoLZp9JdNiQFh3({(0JjZ9i=Eg{!Zc#`KZ3*8}A5eGdO})YhdHpDF{q10d8+z4E)=|n;+Ij}K1hq_*GA*}9CKCS8Jw%3`JVJ=?&WWsOe0wz+Jny*)Z1>R zU1(_QB_Hs1#JpYiZEz5ly&my&9pqx~tNQC?dBgLUq-Xm4FZE3I*CHFEHwJW6y*e5{ z*(Yn}5wY@{g_%xktb^8tbjW1w>1{&}GvzST4m0C0%lakN^Q1jheaJYfGg(ZCa;_GRowvdiwSWSh=Cv zvqM;CSP)vwq&oL!huzC)Xp~<@?MR|3j!b(d_Wz>o-Q$|NvcBkrHI;*SP`A}84?SkZD*9)>R3BNVvA96UWm3_YG;xt1+k2fI*J!MAv$Ok z-^bF{D|9R^ty;8Jz}gC&_q$K<)|ub)`MrO<{WO^D`(AtPwfA0ot?zaoCN{&HXXt{d zDR!7m=`yKAy#Y?!PQAAx>FbO>7_d4|d1H>UB{!j&+59+Y(=2S%8$6k`E>qZ;IMCSq ziY`;+$rQtelH|FR@inKN0+a~7P#5_uKS^keH);FdZ?uwG>-y6}` zco416kWw#fL;DLhOau#GfQRi#J*w;=TloX<4JK{RAb6If^#Nt=-VT|d80dz3c`DsI+@_!7m^bpn;)M;a$XSf89Oq1 zIPG1y;XddBCG__}{RZhnChdBfGe&_|JDdV2k2Lf=97N{h$Ox{%-Zh<4f7?gwI{bV} zW*z#ke&vQM4c-kHHkM6<*-0Q$tAD!jgdCy(>cDXk^$2hX@nR~YhrzII7G=HA*B}JQ zn@#g9hMDjTDQD>o*DoHFL*@%jS+CrfD!0p;gME>-O%sNubT}#G(SFqDHd1~SFiW*kK${o`c) z**GcuZf>S_~vwg3hh}Su0%{t2!{61h=;cC zivpdA)^50=7uIcqEYdFPbDM-CgYbZUDX2?x31@Az`Ns9uLD13F{7`+?A7Scfx4VPM zKw^gOR_aV-`l8zle%5U&b%Z}VuakDuuJ`zI=E0@`4Yz)cf-n-5_ltr?`d(3Kk1#rE z%c<+Gw}&-!>)WIZ>|}Tbvk7r+Us@Ow#z4_aQLge~vQ$$p=nrS3pZc93$An1IwuGOz zEfH;_l)QYl?j!w#4EWxH%@f|PK6s%yvhJv0Zk{ytiF zl0Kr0m+qA@&tC>k&HCW#N|cd;w|gNev;lo6>tXhwbR%>U_F>y=V=34R^H+9C6k*+Z zy_G=2xE7Iuaid8VB1UY=;#V-T;`q-BUh3{lA3l%y%R=iN&Hz|FqB|Q83Ya>A=OLtl zEL05GkliY8CH$wn<+nKazw@ngFQ&?Ga*%S>MCj;pDedpBw_fM$LYJOY?5|d4%fj@( z#n1#3hs=Jkk4P6uR#dW)neMOK@bN8hwH+2q7N-Eu65Gzp8sFY#(@elfmmMT)ly=c| z^ieNt?c;Qji7wS}i?~aIBCwR|QJ#O+P?Q1Xy;#BXqIJ&57>&J0UqT08Fl}>QcC_~Z z5~xBS>jamA&I_y3RG?J0GJH62n&S zwxGlmZ}}Cj4BrvHfYPqN1(Uj*PHsdI&qPZCMUU@&>m4f z*Pn2nbA89zvCuo~gw0t@{Elxc#n|jS;>0kwB?$t+a*SL*%XCyzJC-h*RY_!>fJ}1C ztfX5+?)qt@0eB|M63+C`kU+GP$dQA+{{e3e{xZg{Wa!wiF%6@@1H|M6 zTb#--{Bu-E+F+&(mA&qx{cIG}-;benFgjv?i4{jq?N-}icV^T40$CNdGIy>3U>Z7@ zA+>%_DCx=>VoviNnkvU(yPXmBr2k+vQig%=8|X}!nHi&=MPDY~gujOr(oNK`Gws@_{~XX4%q zo5PGR0Z6wmIDlDv@?v9`_q~aFZ5J2Vm3ZBA=3m;&SJY=d_g*~z_EehGG@Gx}(cRkOF%4LCT(fg>@+9&bgUYO1V&j(`H#)<7^!;d8Y~fqysAHa7(nyOOb# z^)1fn_7>MGtlPO-{jWn$imV@T8)>Drs@HV_5~b-l&V8-NIq-w^I4L7erv3+q?0j(* zS7($TA)%WB@TZP;G;n3r3i!E_AZ+g_^*$1-p)0zT>Nk5`2e1Y=eZV^ke-FMxf<%g1 zJnq296zB(@`3{{@h^&~yRw{cZ7pKvjo>H}50W502_n5-CK$iBjVKy#u4Vh|2 z`u&&O`WqS1uv%;peWbmbeakGW`HVZEy^?*$5Lz#fS+d3!A}HTqW zj!2cHY$FAL&pxbJ~N1j+u1gG=<>+mzG2boB{$H-uu?IkF&$!#a`G#V~{fOHFFmX zXr!2jPtXM7knE4cK+^<5SMX=mx7xWllM=^IWU$k&T^MKox7+@2*eDHPqZZ64dr@8-(Ph7~*3J5>1tNrfNs^x_*Fjc+(6{zrg2K@T)OWz#6(I{D(3O z9|g#FDH+#mH}zt7q#pA_OZCo^V>1{@B#%Hxk9Wmz5lQ9W4;RJbd6eR^B*ptrnWW=F z@p$Y~Z&U9u4EUEFmL)###h1LiyhZOx&0h~MnU8g3S~gqmmE|Z56Ej+h|I=b9mKv*FtyQm2`9JSHGlA33-fxs+4O#zgFQGtr2RB$P2hB zhL*_S3(PQ;i_we#>a-l*N_wH|%V9lGtHHE6hlUtd592Fcq>$%f|C-%?jpuflN`&}% z9%j&Ur^@rM-}dVtj$L!bV(zrib`55dKkOgZT&zDVmtpu&zN{S%ZSytP1ng^(+8^UT z0ws*phj}6-n3$xGlW(fc!?|KT?T*%GnlMeClZS2#4BaKOi9#*H&}Ge|EWtAC;^DkP zMcxaB_5zE@zkXOmVRez^lZNMS_BKr#hA7&2Smu0lWUbv8GpF#4(&=#Dmr#skxv6b5 zwuy`-#YtYwruiGZdB_5-Ya*rHdaZ%B3wab$Xbk20NLS@BTB@gWHVhIgV#+KY z&iIbgZa_L5cxEB4(Da17^wq+WkvcM8PBE2Y;4!{>%Z`_|Zw?#YB*4;z!n6#9dBbpC zIuU2HVFaTv+!}(pwO(oderSG@Hw}|;x?pgD_Qh+iGZ>~qnlE0*(xoq}+$z+BL#Fz> zYY>4fOEpcz!A$JiNgybuN^)#>qc`$;#YNlfxb*Rl-pYPPwDQRfVCRltD(BOnGf!^FSsi4eM;DBhx|I@sTDa*D!%stS zyS%b5@Tsk%XA4TEQN}Pjv_H@jCJKEg&=)3lC}kBp=!_|pFHCY~`_eT#0t+TY`NCvH z%D^=fB38T>v8E!HE=feRFye4^dtiH6`z^1xAGeV!UR$%9mc)~oz{6$j-G`2pz21#; zMb0=$S$cPA2pk>Dvbvv|K_A~2bw}{i>XkS9f54A_j5{!se(Fe2#SC%TYu!&BkX6jo zmT}$3XHJP3`^yNRdfr0Qs}GX{%Ap^M=#a)VQE77NGa%#E(K|vSNCdX_i9p5>tNd794zfxBAS8>j4f2_5i^EsCzv{?q9ssl%8sJF`h#i{>m2>Hs& z4b^tkfCiE>w+>~>?75{HvLkK}0dj}+$?xnkw}z}p_9&xhe4ste?lt^+sA(dXhRtcU zHw_!F!~YFG;WP-%58Cu}@*%-)-p?KA7^F;xQqZBK91Ez5mRGH>3^7b|v+G9=wp~`8<Kz)9$?%UsYD&G~s_PpP z#$p13eGbwofjGH7BujJLLv1&?93znzJl(X^wM=1M6dGrZ9l{AnqbOf>)p~ZQ))Ax$ zXppfiK^UpYg4o8itwabB+YqJ!IKDC(rv@uj!~Hu9i~~6bMQ!$M-q{>jC$D`+HU}r4 z@5p53In=Ljv^ixcp)#o2-7K#r$S4!*_Z&zC1Os*Q5Ho>CM5*3>vHf5`pxx^g705mT zmWd-x@6-$1lOpV~m3@q(*yd&EP21yk`Du;u_o)~=BX16Xrx^+Zs7hk96A&vC3B(Ft zbOR~R=@dCW8Z3~VCG8AQ)j8|r?WyE+*2h#q7qZE5zr15AG}8?&)rp{!ADr|x2cBo@ zPdOXBIP~leIPkcLkspT#OL!Z{1={%{KeJ&s26fBN+qr4`y)tb+m4h!c@gSOZUUt7c z*`wtVypDo^3n=e@XycKWu|BydoIzC{m7-Mz$mj0xEV zofZLQz`mphl~k#{-jN{DG8J6*HuKwE$PbkoZ(Be90$IlwJuq z)Yn9gpy0}NK`S;0Hat-$$q@OLq%AJGFgX8Uvx@{X%U#QiuWU7lddkGZIm-V-p ztr;S!`fn%X)qCsY$5Wq~Q&s!;QxW!!E!Wz{fY{OJ2*E;UbM|eOj*Te`D)jL@a}kd3 zuI^*DG69d|XGs33e14od0M5}x@;B}wql(6&IC8I^FgHKL-_Wo&;C=+27PQd${96`? zs!6}!2f}O^^A@4rUAZUc6Vc#RyF>rZM&NcPP|3}7Ndm=e18~b_eNgJRsU1wI1R}Ef zS9QYbC-lPF59pF8!1X2{BKOK@(UGq*CZk0FlRd_z>?%=E?YjX(a!gfolq;El`_y;z zj*UsHlJ&3OFS9%K5);6bk`CT0H0ie}F?9|p?i#ihnq9q0{dUHlte?AaTXy-=T(!;~ z96wDTyfJB3vR)5!8DFmiH~^yP4nl_pB6#2(Od8P!v!l3OZ8x})-~S}L$-5j$^8<%- zPlE_xAjpF;YyiiAWOHsaV!Lhe_QkuB_2c2SA;R>~-p+L_-k$5$*cR_f)Ol0hfK$ug z3DN_YDL?ae1HIS<&C1x*qQ&JY*8Fc#An2(o%L}xv|0ymKVh3)FzK;pZO9eSEPpc=QH;F1z`%XWeXt9sXiMllnvU90^S1npH~EVAzX zMU@|8UM?Fys=A1gHA@?0w?2x(Dg(UgXhos3P|`jW*k3otv zV-rmqoUOez$i@4XvOVZF(j|aJi+7)aJ0@ZMa0t_n0U#S_^rFT#o-j3gUAdxdGa6=Xunof zAnQVv%r+-5389$qdZ5aH2h}2zFBdWkyy|Pst#Lyt@Lv-E0PJqf z^|U5HUPONh4QVqx>)M$a01G$z5`3;wxT}ca2Kfc&A>YFfpBB_yMzTD@PT}o6|Ki-P zX5zT%YfXqIKk~xsPYakW(b&~H?c?Y9dB8%M{^VALRV~Vv>Z!d=pO0q z7CK>W9QGFtl4$AeqGP$_H~V}D`~27jX|&|F+r8Z%GMRl|1=n^FLZJRhm|O2+&3|Lf zdwYZkdHi0;PS(7uhDM0uUPvWtuBs8-cDueJA>s9`c`IxFb3TQT=6h*uta(E|HvnSZ z3t7XO*G3N`B=26xi>&#j=plqmyBA_+&6b|K2*Fv{-<}-UEcW~a@AOU*Lh72sn&;O1 zh>*q>y55DJnbTOaq2|s2ER7n(tobq4JUx0T7aLAzlv8f?2TgmqXbbsSvK2p@ni@Db zQ3Km#MP$Y%3L&1RS`I$eIh$kL>c*xTF8{ai4`nmn_QyH7{Qu%|t|gGTzi>6rk(}3J zGxm~<9`y$`&vK=y8Gpo7v_*#8)&$rhgWL5P>+qY8Z}Pdfhqu@KokKf3>PDZt5Wn_u z9yKB!hx>ke&jDCkK^z+=Un~aN6NcUC%;PCRvKYp`jDi zoaE)8&-E3`EFH;*2}IH&WDDwSB4uMrv_oIwcD?}s8OZgXo&oSD`Nq)EJp(N?W(lF< zWY(;T{tCYvuqYGk81vZZFEJD-5L1aDp2U^Mxq9lrwU|lGK9_8yrdou2g+v%4B&vCj zPvBPYGlp+U4Vf?eyqrQNBAHK^ro@*yw`V8j3!K|?$*+XyV$9l7w1>=Xz{;R2O(FUB4(Oth zzX|o~qDg+8KmXqlK3VttWL-2u&;p``>q#WcyyTOTXKR3Orw9HQs87ir#F~S@aEXr-9vLRJ0RulT)g7 zYE??Tj-8*VHRvq!b!;}Qoh{kz3-n6z1+NXEuPy;2n(c1EjtV2+vu}WWYY%sI z&0{eNMA$S)X1jW-2Q&`mP1YQ*{$vo`N5YNfDfv|cCi7%wtkDc)?O>BRWO4aCiK#8B zB%4|*QxphRVnhG7stPB_m3g8?m3R?=c{^>bbFH-fDJ;gzDsM4w7ngW}p=~qA=jDk8 zOKhzPSd;%fZ>>MCqcx$7&z>A%hgmG2+hz_a!PyiYh}LlybsWkm%_wSJ-!_rjDk|yX zp!GmY$kD>z5@((WFAFd-i!%Tn@h{i2`PO{Lmse=DnJ1IR#B2pdMAX0MKHzVQ;@(2P z3=2K!#-?(dksAa+pRuSXp@8-RTWf9`d0Wt?j<={MZ=Akznf_0F(#wTGj@H~22Ui@! z&SE3kXunV=seZ9gQak;>=2R_9B`1*sCSWBZ9a-n5G15g&GQZZtb#C#txSiOmxG1aPwnH}VIp~78jpJGCuWnC}pQ#EW*2UE> zFHsV$|Ea7#v9VrJR_)g(xqZ1nzPiXc#N$j(ZqfM3R;@n|Qs>J28Ih+taefuKK&z59 z(5RPOZY%)uC`1oVxCF^5u}<16$k#>?gru4zZZW;(ZZ69!);qZeU@l@&kWHb3>zv7cUVKYANPo@zOS7$9q zHqzP9Wc7y+dTOUa)2Kq%`a5}ri7N}pU@j-RF7@nB+ zfyBoWq1HwaxxS;ezaU7%`OZ*8-c-_hzIsm7Ta*i(R<0Pv*0@c(1M3tu6VBfZ*o6&Z zUJY-D?OOuTS&MQihhfb}Wd9d5BP}u;i_GdGbHXa?05RZ^jw^C;pqeM|*X@(#Cy*a0KGKxg z9<1PKbMzDvro(z|3B>|VqIBk&J#hma>IEj{Uv(CitghG^SkxDkIwzO>)@ZT}(D|=% zdSwogW_qcseOMpKUyNx0G2)*G{Q3)?{U_e^>eoZlk-@-J?XR(wv1%HqS-4pi*$WAK z;)>bNsCrRnum+F8vMiBm6X6O0J@U>$6l7ohBifl#+ z;t^w%J`@?iN6KtQImsMJxs8Dj#g5`*8JltRNY*hAMF#Pa3Y$?m5*hqZ%n&Mv+V=Bj3k~Qd!{-XGYoR_Kc( zYOHy7e7p#A;$QNZyZ+C2XZAYo&dfwwVvqF$m;Kt8>{;M%>Wn9FB_M&z*(>A%PcJrn zPcY?0_^$nqBL;vLt@RrmpS9m`FiblwQFW*+&Qa`Q3Q`OA9QfO@KwvsL=pGAOix{W# ztHyd2Zd8a&TL?|esVZEWY)M+?XwUu^r#;6p5_TbtNDH6UvOr)vI_LXW3(JZZI#Gvl0bs4}Al-^|{4y=V zWqJRpqypP{3|c1WNc4QF)#PbMwyezNWW(_DE2P8|m1GLwKR%5Wc0Q_pq$$P|21-~; zbLeoqhSw9aN*YfRY-aiNZ5R(9J}B3yq_u;bdDoYT(;71+u*`Hvk%y>p?^3)ik`X;8 zUlsD@Q@bZ+N)sDbJDh*hZsDpA8>8sN!;P*@oadAXH@8Noz=6_xxwX>bs>XYUgl;8W z{x!EYwye4lErn$v3HSrfc?fW=BX@HMyDX((3n%v9-xE{^;AOtbuX_xpp2ALpC+)Jk z?k)iSftJ?qyO}Iv-uYYqrb3R7E~}kkco3-2H7?Ir7>h$Jj?!;&jmg=P+DI%vrdC0hsZf~;uUyC^rFTB zTp4@l(I<#CZJn~To>&Ny+kU`rC?RjZOvJvL3YMea!hfe1w2O=4}bg#J8q&XH4)C9jyr6 z8I%zML7|8VGnHN`(2$3f3-ol`Tq@&Pq^HL)agb|)`s9=Z9Ua`eRNKq7ZsRs@V1ji< zg`V~htJ_l;F0@PiCI*Yp?m3ARYe!EX`r@XQG4UZWsj~~hi`1`oGbvvx;@x(uDwN3L}AQ7^GHg*=pq(E$LJUG_6 zs=HN&DNn3b;k+;C*tHEwJ`RH9W#E* zV+-6}3*nTfq3d)IiBsk6vvPdHxDDvkF*3v8Fu7;9i}-9zShBtkZA{z7%T?Te!Y&At zwC4T(G899~R2BEbV`xY2jwHvxc!DbS`^?~SwC-B1APdB71?I`^KLY2)7 z(BE$4ZWp!XOOC1#YR!Z^^w5ILBCk%pJL(1mQ=9qa*2Rq zeB^3|VrZ2$zv?DIYFHaz4G6tU*X!;SsCiydV{*PI8g54*KJykHjG-iSuyk z4}L&ZI|3YGv@J}69ehQzxH!&>;_j8bn^V^#jf|ub+rp&(Ax$&=I=x~Gque+xaz}KX zkYQJB-uM`egr_Avul1ujQ^mQ`6$=+jbA>DNm&0TXdk`$VDM2sMOBRIAl9sx4Arvz% zRo5l}y+8&W4~EJBUjq;txbELd065Wsg@%1nwAR2lNG zq0X&<5f`;7DXRF6vzRMWab*#Ecf$dDjtkV0GQa!LuqnIe8}5#wcgbsjN+KZbkkJKBuUIK%#u{xx>@e0Sgx)49Py(pv>+x_788>o(UFNT zHLgdp{%dE9fw$JQDJ|43^}5sC00I7FR|&SyH}y+%Lz(%!0|l z6bn|-DYl0S+oX*?%jKLD{pQiYo=>^Kbz5wk9@KlChuD0$eZNEdI)H<|<&nlrivF0> zYsq*%Ly-yYz`qUfx8mo@L*uzrN=9>pJ^0bAIgPP=SAOJB8^NJa?Jk>A|IjG@qRLQn zimNmX%D3!R)t5aS6MYilotrV=;m=CO@Zgv_!GtTYuCHxAP=d1VaTwpC3EdCI((LCi z3*j%(lB5+DzCFS&3G)l^^D(Y>U2f16+x@^vK)Ki?h(5}-|1{%%=ymZXK~F2t_5FSJ z^Y9z@dyRR_^YDMJBmcwyTu0B5f2*VB@c*wmJ`q3Ck4X>$(aqdo{T$Q%ZalqM(6gVf zcgy`=F#f*f{~h(db3c^yEqdS2>Mi|`efwFxPorMkxIa?wq{V{#y?njDxnILby*&-6 z_l5hRq~4nMe^#&k;dO+h`i;L~m) zB*K&=UVKPWf^cbcZ_F|7ndDpj&^fhu*#KpNnX(1kC~KWu5ps^_<%0SmIvWardDUOrCc1oE^AaK94tfIepG{ydC?Jb!c^)~w`m!o_nQOvI-*1?B&q%eg4r@<>?p z@3`LTQ;!7oyom7@xQ{B_Wz%t02RAqv}U|xyx@HkBXc^p!@?E*FZOO?{z-Y1RAb}z+K9ji`zaPWiHgcz-UwpC zD|}f^uoZN!W@L~5p;6Q5qp8{n5@P!JJ)eg0r%@HJX6TqOQ2`XUO6y(tJvC0exew=9 z>>cmrXAb^{{N?_=ayc*>WNZLc>WHxKsVc~Y5AVdA#dfE9>JYq4Z70&=?acTH4d4VY zLBF!{<+@^qe9m=DV9m`w^{lU4&mskmF+3gL8yyygyI=^*;6V zuUv3aeK=3}zvmI*Y)|7;iFO{u$BT~`zc-S0TPdTj-xNY?xx2|@Wq8&)dF*I-!|6n_ z$8RT34d;7tEqd;;7pT0%Ib_79`OnRa8kWl@Prs zSeh`fD43+)W6>QQjxfE$CR(05!$L(-Igu z3+eW7+?^JL=eqGyCM_9hiBw>tr6bLd(l%Pgf2VE7hX6j&8D={^jDPWH(nj)+2KL|t zTL=%Uq48I<^BeoFWWOJ8b8ne&(ESQv*_o0du;@cI#ybe8?-SCq9 zN;cTPJ4*ub0Ko{1uPg}+F+mkr1O2T}BW#fPueaD;0q`tfA{zIrCT#WXibM97wqW`x8|XLDq1PM}6uloNog4H9y2+!ZH*4P`+XEtx`TLq2ys%N0dZ z_nMV}W_38FzFl$@>Rh2}p_vz%ThZ_Ju^Ezw8z7eu2N0aT(FQ(!{3Gdi{ycp=yD$~E z1vqcd9@Nomj|4M9Sb(aZ95jW9bjs94+te@uG^Lt$$ro)4B-*C6ZAeU&R;qiu$P|1G zG*K`4l6+kXm9ZZ?<(V)2vP!jje^IdEh0mc)%!Ctb=JUXz*cA*#hhggA8B>tzP4DJ6 z+%mg7-S($E;VxBA}JlHzt^VUl!9-0BDCOUShNcoZ8_;iM4)8T}0 zzdUQ&=dB;}DhzueX)AFZveJVp_GY|>*NjfQ*$Eky3mGxu4+K7Hp<^P|`y<6MNimWT z%9{9jtCti({QraK~@zxu6eNF<_8ojx%wU@(GV}z-dCwBtv z&kgv&B3ncXdXC&NxSBT&OetR%cuelU)ZbD6N{H*`Gp}JWaJpDDCOHYUuTkt~SzCL5L{O z=t!sb;F9k<9G~zM8?zPnQ zCQgvLERm6x=x8DT9f4Ao7O5f?Y?cIIhFUaKP`Ztg?N6fHrc!VQHq!J~VPF&)M;$GR zqpZ8{s!zd~d$j{iiW3DobhFWw+B7Tk{PoCN>1Rp8XBzUJ}IjCeP7#YZi2@DG$OBWdHpUMHp9=0)^&H;+!_3; z2@l|t;CSeC7NU(}?V8t@19{({P(quP~5;4ft)#c6L;i+M`rsHSR#XHS=kG_T5vHB zG_&0N4wtD!LX|$xj5Qe<%$w||yIS7`R$9xb-24VnhwEA7WqM3TsSk&C$qeHD<1@-k z!g)rcoLU%}w{SsProm(kFd742^GJ+8>j49tc`5TG=>jsr;YEU^eCEK1GRuud<~0wK z#k^Q@j4~=gCy_B5_cYuo3oxx~_bCmUuGX~}L?+M}CFyWkF@~!GyBoxrQe#vOezd@L zOll8*-)@xC?fse328l811sv!I@N*kY=+yudj?-jJooTBv+Mu*j+`bx9n%c2C12joD zE4o^L3v{;zQDH%gxWn}>=w}Ino0xdnfnc+&t2OtbNGBpqM!BREK7({uYc`^=;sZ3U z!&Q$cA04>IGo_u$YAYl4th)RKx{e;9Vek&kJ!SDXxn6=MH>1g&qDPxdc>8B<-m!~c zKhVyvJ6j(cX$oxbI@}Xcp*x7OD8;q=gUp|IwoXNCi@30$!#xR6IiepP|4M?3%k!NL z;zCJl3`b((OFrWahrV#r%1n_l>M69xM2|KqC20$T($e<9h^II`(sOdqIEONw97@Yv zZG4hql``YWVbuw|!%YR&`?APVQrsR?qNGepX^~QBQA*~gZD*au@L5JN@v*9Cm8Wem zTl^zj@s=DeW+T}-c*c7*J4e8_kqh@FtkFn;d5lJZFHpz^(kRXAQ_TU3^)vBcB@}9M z7B5*;M8hjuVxdPztYPUf#cP7n*r0U_RSQ*~V?*lecTjx%;o^mnf$63>6eiaE+|{Nz zg7_$lk@5x7OzMnw^4=*Khd(|t4vX%MLn>jN|LbvhqqFssVL!i+ad34$G7jrITTdaD z9|u<#8HYDMU*C^8V}uAd29~_anP2t~h;JAJ;<}o#3fCvU?`-`Lz&uQ##?rBC0(J$A z{4_)yME9(@>aI&4e+j=(xT+I8C?Zi*HrO0MCauQ@Yg+biI}PWC^*`rIJ z`;vUsC&Q3C%!zgDR<7*VwqIJKUvIs|6|aE>pcB`bLV$$uKEn?*!nS5r_}e$RmD%Y^R={N4q0wzhhvt;0d`Sf_B~Jtd2|S?ZdU>16}=G?f5aS zKCZSZ1h6uI7|=)nBq(!zfNv$(n39VZ{ze3A1a6ebeG*I0El|=>-}u)lRpV-{b-4G` zvkWY6!~4{)UBV^>us!G)ZdF}>B{#A74y=K{j9?7_^?xp7VrR|c_ej>umvQ_gOUpte zD@|qP(BrdCzDv|I7(=uF>|{NA8Pg&c?SYuzWPsq!UP?CHMdEoc$z#3|1+FQ2a$ac0 zM3ZQnmdd`)&0his4JQQl!VDe7yov2Y!HOqtFO@_3(M&?y zGRVDEJ$P!-ah!v}Md)$?mXsDL^J2}7TkX}w3-QkH%7rRP1QoIHwKWB=oX_~4qxMI( z;{8RFh{C*E`HG5pYt7%KFf1&=5KzSxK}`Pq#j5h;OPGJ~Y7{%-X2GQqfNvGy7oZ|> z)Ny5N6h+62SC;kP{zI7Sk3X)gxLIB82v8Kn$%_{SG2_b?s*n!WU2EP7gG|D7qsMq8^jzu6!-~#1*3Eb{ZmsOJpeXjmE+OH? zkv)M3djcWZ69C3=Jm2{V2_+iRdFB%2YMr!2+#R3jG7VN4PSZ$NX?RY)W47ymU26S& zs7~HOUs=&nbEqMJk7*w(2_^FNi2O?E`~Mq9zhzfKtuJ1NEX8BvmY5e$3lcveYi$Ou zTg5>A#O{Oy@Rjd~)2_SJ`Vo555TIY$LU+^))O}5zfI`*J-7k@ z%`m%&E@|c772@q#W_HHMod52d?BDxU&V9^wT)3$c47Jn3m}5`bf|=)wHwUHJRfdh% zp{{U*L`kq%2jGau97|&rF~+!F4|}p$mDYcIb!7I0A63SiSx*{8ih`)I#kL?O1UX5z zokPfmzlwD#QEM*& zp#>?L{xn1^7T=qJDUU^Y(4=-=bY1@;lb-NC0pptpydDvS2Sc+cL*Qkya1n?e|DzM+ zewT<3%vk@1@=fd~WnfY%K14Q_4}o;HXoV_opPzQ`%b4xUrjaeQI_MIl1g>y@JA_;7 z_xw0uY(5S+w&=cS1;ngiKy{q z`|)&Eq6_!~ha(vRTb7u(-4ab!tVCAD=7^We$>lb&=_F?q^{tDp&7|fuzUIvchOEyI zLNC;oi++H?1O(!@;lD02%k84#{lISFt2oJ5!7!&$33m2uw8FB4ii>BXDBTjADoGV3 zr#XuA_n+`h=Cr_c-~d3PWX~JAJxv4nxnfqq`iiZUcle_kODhW4Aoad~k(yhCEE|AA z-1$mdw6gSyE>ogb{-6t^jhV9e$cZ=ADHjQL3VGRb3X&1h%SUKEeMsBQArmT1^e7rc z+FxEg5@r{AP8BcB7^P7%6*dloIM)E2Xvzv1e***D?Pwfn(c;WLBy$#1VB`sTY5ZV z-rV-%5i8~<9FL$&BB_Y;p$DjQ`)ORzp?S7+ieQ{9j3fxK%zUy$zz`u@cNuW^A1R zfU>1op*6P<*#2Z$x)+vS1c(^1pwVoD-9UtO7|d&#@k?esCrezsO|@y;a>2Ty;)RON z81u}FuJ^I~YRNamzX4@dx`(v-|t=&hrsi|wb zYY)&8HHFLIF{ejgHUF4hv+>rQ>?`JX<=3jN%_J+^!S&aidlXYX*s<`yv_(@+9#38b zKu#1(uv?Qjiq|4LHMA4Qm;3@6xEc7brhta>go=J^EdS~u zmH*aQi30JfQhBFLs%BNH1c$!pVoe6IKB8)Voj`U^NO4IA(OYw9S_ZG_>-kkY+DPS} zn?YL6zXVQEyZrmgd$u8oJ)3Wpk-Uff^N_TyE>=IPbSLn8i&-boy`f;Swp`#r7O|@$ ziX11g$3e2@i+)^R@#LG7qO72A)Qo*^A)5eHm?N0jTEf}C{lwDIu2<>SY(m zR-JBg^1|pC!kdLTuiXV9+OdCJQp0h6+L{NsQ#QEju0K9wDf|MKKW1Kh0mq_BNmf!_ zT;du9Xls8=+m9oF7x!7P+zU(5z{aL1SCD8b(@2a9qwWzH)^i5D1YCjAm!7d20c(sv8s+zo9>YHXU(qx!2B!YD1h zto)x`8tW|sX>PUO%9P-MVvG_uU4_%E4_g671f6$z3+Gl+1jI6YOr^vHDYLlg3nVyB zHl|9!q7>z+n%aW^wlCdWn(ht}055(Xtx@Kf21~cIA%atHRd{HXNyXcuw5Q)rrrWwW zjRdewI-IG<`kWR?oYQaNzuV}Kego)!zfb5+O3<8zjAxNf!2DBv_dFxagoO|KB;@;q zJBrMpj}LQMk!LzQs$Xl;4w8Mu#L&=Poe5p`b6jGi|d zbK13$!@U&jgKHzk)k&M)=k6?lumvKQ+UE+sJchagNG`WhP=8}ls`Av|4;&IUv!z=~ z(>)=A1Bd)Q^xQ3dgY>Yb)+2b1?l`T=d#Q{K6Fs4E!TehhZ?A98vE4NDxQQ1~JTtBGpw z)<|8LAf_f8oG2HQ$rGZFiVN0+ly;}EB{Vgk1>^U#&j{kv)p!;C83C@G=S1nHb%J{^ z?$j6{FOCM^B;f=4X4jo>zoi$q{tgC<4R}tt!{tDwM&F>;$+<(Y%j!=KAA|S;#N+0m z!&QZ7aJ3~wfXhI=n32{+KH=x9@@X7)rDe%ZeP3B^nL9ix*+T=QtbS+gAsQ=Hd+`3` zFWUQnm1*L!GEL~h-@!YvNn3O`M-ae*Lpdxc{)*swYsKQfiGgE7Z-5)fq^rg-u`V|%w<>^cgo z-ll0N;~eAwEd6FH-FW#M-$DmWa7NcPMG<=fl`!vC3Ga zMLO%nVJ3jpjCB-_op|#(k!awX^)TSA2cH93U!!G*d(UvU>)tZcSRes?dQnZT%6e0k9~U@G*1L;G*@hj*5dr_ z?}yFTugeu0b4AwI&tX-=IbMr255>{OT%ifkuRI#f(_rOD7;$q#781t#`dKAZ0QbKW zOLBjBCC!9I+^4r}``wu#_=Mwwc#s>bkrDJ;( zw+su;*+n)D(UHe3h+7&bj0=w28TSD>cFZI*5&vf5U(%M#SU38K?g94R8RwwJ`Q0$D z3Ysb`ttYnMk0D*jj~t~1nj($0(54|f_0oDfEL9)Fw>A=o_a%NFNBTZF} zNfK0I*Z{BM?B%C5g)W%+PD`lyd=VNE^(R)0V%Y0{W)mR+$`D3WPf*d)i}Id`jQ+j zkil4md;w+T8L#3hXM76O>q}q>E zP)(HWMmhgLDo3caqIOE9qJ8sO`};pS9imM>rLaROI^}_Y zjtQ?W!1Z|-%wO(E&J*q0_FcSPx9iXTc@x$1`S;e+vv8V#!j4I`Y1H6T!cX8$gW?>- zTCS)r8so*-pOeQnN9jea%Q!oh8|Ix3*Aqy~=-MD?Wm5z6kS8N6m30kQY;#u17-P;K zh9!6SJy_yu_25}MJ+hD8w3TMqipPt3W2nGI<%U$SmZ6G;CRPxwGc=*XM z>#Sbn`f*qn`9#wt4*D@6pc;>y)Sft7D6ESCb?hRT^J-j6hoJTbQJ~zC@V$YfN2)H8 z$W{qJ(XzDw8HF}7=d;@xpJFgTW70Rhfq4Ujj@^}G_~5Lo6?ZyKqp{)fxhlaohP`K7 z1Nkd&T=U=xyTkQYgfb#ei1a{Ykh=D4s}PeGS_eyq%L%@*g-F3G8+V3jq9E1%GTji& zr4jGToHqtDMlgr?$&C8R%c*3nS4|_jAib24WXsOB;aFr7N-~A9mE-JqTiBl4BJ??l zJ{P}mjY#C&6QZ15L+uj%A|^B^c<6p#VB%A?F-2K^8?cm4yhyVa#^oxzVdFvAZ}ZAs zj{6g-&zg71F7u=Esqb>mT?SP=LGUATY$l1fM{3w|a)R=f*%SbmW}N~c;jvB-%W@+_M0+ z#hQvgxvf8N=#=#~acYW_Szo`(?xOIuQdWC4vHZ2GBs2hj>ST^R1Oyq+oA3$IWOdP1 z+a8jw@;?6Z$ow%^eEmQ^zV-E7(Zk}=1pn~tnEp7a7jDtixCzsum^<^#QOpAxUf!{aWp=PCz~>-kF* zi>6K0)2_MTToKANvXnDbWsK6f!)XB6`a0tx_ejz-7Azq#=1x#Is( z)KL3&^RmRc{xk9p4iN3I#@>@3A&3*V|2Xqz9iL{^j=}6r#B~6}R9O4eV^U^p+LIfw zy`CrD@v1G9X2h|TN?WLq2~D(ni*q*MJ#s`oCo$)LM)`v55?2IvE>ARF;}YA+1bbcH zyUs3QPTDkNvqXM(hL?Z!89CVmG;P4~#^?Gq#2>qe)-4i7U*OahE-OnFrHG4VV16)w4#C-|82e&<{nE>^83ZI8l!jkuLDb-1~kK;Ujx8K&Z1aBAqhO*Ff<8$UZ4M`XW@!mT1ZyBLJ0O z!o|F7E%r7=u^}yj%Tg-mnz$&MDmo{3$Id{!_4V&xm%Br07#D1=Z=q}Ee$NW1(?VjL z1>kSC0~aMvbcuL7uc>mF^Wd`T{rs%&^Nv zfaTRHq&$kk3|6ZM1!_g)-QRbglhWe#{_pQUpHZ8fll@qG?X}nXuE!=fwP2g$if#rC zNToUn?G?t+M?*@Gs`*oBPZ8m2ls*dM@T0-wMCUsq>3p~P>E=@`zj7j{Vue$Kedsu% z7Sqh|z3CJse+FFS&bPURp5o&5bBE2p>{d^HNH=P(JAZPK#?J-PpKj1%-?7Z&mwLYC z;NQlP?at42t8KlddQ+jnsj=oeLh8x$m35aLY30br8G_RkGDx%UGWv0(O~w(|K)x|P zc0_#bF0Af7Cew75_UI z%pG=eK$*Sj49eE?IPQvgPU&ktk*W73u zoa=pgM}q6Wjov@SZi@(Nyn^0LxR~n=z(}~&%uzsNPvYhyYq3%$;=AC17W}gU|4dXW zjX8Z*)nAf!GgeeJC>dsTnJoWxLTt`YujAYKF6X6AjGZQJp*e0cbXVqm%0CTx zhB-<|;2f{|3tyn{j>Z2iU{pSCWWbnEQ7#ysUO&q3nKsKkFN1fF^zO|;j@oZ)LvbT( zV~tna*>R+Nyb`-oB84p`ton;Jb!EssoIQX+j_x@|Xaacw-}|*&#`pR>!b`#Qvy)2= zyaCFZLm=svNh6ejeOCe_6sTSs*mn!A+4XZa{vFkIIyu(~KMtBFF}~P!@WZiJ*G?+& z(_(IzH^&40!uLsYX_j`(9?2bTcdHcJ65ZijNJpuCv55ADZ@AN~q2UT~i=NFQI$r!p zuXiAh#2=vgC{ra%3~)+vdOfvMTtv`P?i;chN-`x`hLGWR=%~Sk6cYXYjNDS zxTKN%nX^UztjsR%g{B3-)VEN@J199gZZ zRQkuguNRH_ka5^n?tP1Bj1L*(Dvf+|_WQ1_C6&wh%weJt#iJ6##-xaGI9lEC_glF5 zt-0~=zRx?p?To?v^}WsHc!ZwajB9b!ep37zdkFgm=fmxNqdY-^$H;Tyub1``vQq&# zlUzsU+x3tbM9#f6EBf7Hdf>Ya(eKi!+u!*rZ<(}VY&IhAhC%L;z4>%|4)N~;)Zopz z=p_RM-pq>TKit|drEgXTXA&wx!b@Vx$Z@9*?06xjQ@FcVP(YIIbes0wFvTh61;#rl zrD@+ShXYqb;EyW~x5BjVTEvZLDn+arUqiW#t;Z?#bwJhYRQ%olUiAm!f{_rWFX*f> zifyZ7CyB_9+-%){O^jFMt1&0b?hb^D+o)as^@Jaj)5Gjv@-@f?BjM!b`z61u!V+l@ zeoSH{+enP0@CG;*=$z%B9mMmt3ZG;<7;`lKg3J*o1tw`Sk%Z0Ckt%hz0s+ei1~%s2 z@+o0ty(Gqs9Jd4IWMdSyPlWg12&X9K)eebJitzqE@jzc>2EobxUh`hfsaZu_K&Zfd zweI1fd*s8q!eUK8^_S8SDOLas?Fcl6OQvdetPRsTxtYxOt2F=^eJ^ytbmPtc2_m~4 z8}QIl*%68xj?1^DZHEy{alFRb_Fy%U^+-mBeg8d%3k==z2Wei)O^6^iZj6_h73wYjB0pqftOaVz<(mZVpe;qxsQT~3A-|u~ z(LhyeeHU&9PG|y|BSXnU!pXxT$wP6u8mSj89dmfkM5PvXs*PXXJU2U}qPhHz!Uq}S zkx0TC*5ilFt27-H*=^~^dfXJ!cHEAnqTkNm0H*X?5=i)^W&lEQt*Av*~Q;1DA6)TN*bwEm+RXp)=%bt2^{fsX~f+Yy2&X(`q z!@Ye(1Xz?E2t}eq^Ky&|08zc@Q1U;%El;-p*F=J@FPt=fPeKjIoqMoHdyhY$gS5r0 z&E8Sie=E=?3C1E60d_H{f9`jYAUF8;1j>Oc`T<=m54p|#`}n)%bc(qJ_pV~f(v4(e zz!Yp_)n?y{nF zIAvqpuJZ=peK%7wH5UvixAuN8;`j$iZyusgj<1c~U-o{HNu~YUT_$JT8c-l5(_9uP zP!I-q;kcx)-llyCG`mRf*WV4Sy>y+O@9vw}wOZQZJHD+(Bv)m0Ceyvi)K;aajl;g$ zst;t2t}ALRJNzqDxyQZ|9g2J$ee6EWLk>dgzfO^y58SQ8LC1GL;tzKm^`y=bhk$=( z`D4d5U2$2-^BV8ce5sq(sL4J}w~o1-s!c(02E`fxWPS}jhrvY1!|yXVJ~UdBi|@a@m}p+^2J!>>PGomtkSwK zfEP$QU=Zk{DPHBJhD}$RTq+NxE=qMy2*k&H-gY=R;-c|^h zwpo*AK}wAa_qn0H7j$*X>9(y}QLkd}6^m3Jr`qcr=5Xq(UGtG{6esSB5A9B9i)rC7 zK>QYVWuOG{vhkfI+65_Bmq(kxZ?1;`em1b$1eDXJpIc}q@TSBq=!3c zz|t7M!#RvilgAG#c%@DnIjNKRX7tdeLGGll$6o?u3U&S$z};>eB9%N@kdpEc&KetT ze3_)P>Q$ZsH9~XP3DyEVOL+?r`X7h)=Z~8{SrRMqIkf0-@aLU__>9OA%M&+v6^g*Y zX!Rmsy!F^)D3qO%pQ0$6(E7VFrmhguZR>=x2}v($#3Xuy`NFDW3m+S{d2?yfxUfp) ziC6BOn9vXt3R7Et*WR3I#7im@uG0R=ox>0)-PPK3A@AlA&lP`JWwRIDgE&HptShfMx<$IxMON~HM!uZcqnxTOXY=EBDzCIFT zGX($OzISf);ozCi2WS%!NPM@02-#5{*V9LIYva1ShFrT4hHd>ZI*a^3RY>yBwO zz;npEajk!KGLki_#^Q>Q&MM8qcMYao4YUYxw=%uB2YAWgGw5@L>*%4N@VS#AQS#YD zRzD<>N4eqTbyn>tPTQ_)) zsmoqME;AZ<63z>T*C$}4{9KCHC-ZY@*id9N1j`lYDorX?6>ru6^B}g4!Za4}$HStK zgIySGy&f{guyO1*(^R@E7Yd;%0!zq_N2Wx0+mtw9*$5N>>~iu9@>&-t8HUGZI$#`T zifBaB7|(PX!*VS@gf>l3jwEcw^JAp}JwvuzP8@}&Eus@m1PNMs4@F`5fkl^a;N{N)j1O_qp>x(XI<*?;D8PsqLkfJe8Ud~ zA3YDtV8#t1$_0|=fpL;+EPY4&(|7uR1ASrDQ9q92*t%qpJgGqAhtVkMMZ}y;Do~S$ zYSBz$Tzq$3f4n}R%{{rb@ydp0zYq@YI{fSx>syEIZPLBD9oG^f;xpjP6~5&HTANwb zTc!_bCx@#I5v`+Bn_B}|puCQh-!xwMWB}j^V|+x7l;!>R*NjC+-E)Q)sQ_4r>4XdX zDmbt^m2}bi>Qyr?t1^4Ucskmu#8)^k zQc{hMqnFKzmXp``+`phcSnhhO2~~}rkru~y;FI8xexN7(>Tu~&T2PE&ii3IN-|%;A z>y`8n<1N6dBL`u9gdlxT@|23g0+pDc@;%qxM6Iju8q#AW zMH#JmY8y(1TiY3Hs(iT~0)P)Su|Vv;0b*xAg=s*MF=ibC)B_XlOPFvoWK}I)zM#e2JD&FyOFf8cMowY>i;IxZxUUVHl(x5`l73mwKlk_+rEXGm66n63Ti#W(WK^M7bR`hKtUzH{LHx}SVsTB`+hWUT~3+n-)5w6b6yd1urA^iDq=y3Ue* zd12K+$LoHgp+aX1!rg=CTIP6T1LEm>LX29>;9(67%^#H_z%KheeE(6V%Y`@4EdcbEnXq)@_jqz ziCS#}YPFHgCFA2I3hrV%a74NZf*FMrQp3&U5di-MaMaTk2pr~6X%5>Gw3IfP{y)HB;ecVjF_jLB~~JWJ8oqz?f`|+&Xylb_axZUAJV~ z`L(OQ;X6>#uxtIxh5)BX*&5)0E&r=Y8Q|!E_9U-8h4sd2`*yYuB2jc5Cm2#Betiei z#~!$I`Xu(7?5Te|hlw=NL@0q&U2k2q)VE_$#8~E2`-z1yVNanwX|Du-y1o8){DgO^ z|EG7Pee8)6?=Ld(uqkgZFBv=GRVNX#YsvB!F%B#*;nh3jF`?7TNI6`ANR37;*rf-9 zp@XXk9Jl47)uptQw}aZ)3PM!KVi5CP*tOB2Jn<9ji03ovB=e51JC*{09%llLafrzoqsfHzc%;BRgLJ!{?akBi2S+eo5>N+g~NqUW+&1eE+u zTW?0#6@dBj?~V7j6SW6Q@;Edc{c|M#ggyX26fYghlFoRG+tFqf@XEGE(JWN0BtVi} z#9JkrgM&ZQb&#Ya77W;s2Y21W!?bR7z==eCTu$}dCgaFHyy5F8`1uEdX<&ymO(6|$d&&&jj3ZQ?6)P_;1Doqi8K z`-a^*?ba7pZ;g3U3txN8$HCLY*Zwc!YZtx(Ry3=yqK-)_NMXlR1oWqC3~X%pl{xDd zUit?0l`fV;U&A#^;$s~t**)K%v+yJMOSy)~%WU*mV`WWZ!bj0S}8Tbd{g#rJ$)gPO)iu`Xn~RRa$ECq5>G@S_a7m{`Jfc{Y$T+yOSp48BSkJt zdbsQ92p70n#vnmiHZP?hA}|zG+b4Cc-+{pOufhO_;@0)+i%FYt{UlfpN~|p&W*Np_ z&OD&=9%sB`e+KbPu_>q2r{V1$sr4N`g$j_*_Fv%e@hNuP|8jwYxJY=lLhfqIuP+wC z4zRn^*UGJeIdL`p5tUV=HRY{}2Cuw->VGND5BY`o1Va(GeE!Ysg)2_qr=O&pe1A1n z^^!Hl)w+Al6r7_9>j@Q7>vDhYIH9uA*LS{cu}12s(73l?nyUyZr{A_N*wo76I!g8l zl0B(8OA@z+C_Dr%4G9(7-?64H2*D*x;awPidDpGeXI7PFWo}A(uq6r2BgNDv;c$`-+Jiz& z4N7VN!4o8BTQ$w63V{*x= z_TJsAN{8opnKRqw@xl6X8m+EdU8xL-wPCTUQ{cU0$BPGYw!eK~_u&(LXTLzo2;LEE zLt<5!JT%q6LY|!(s*Y2TM)pdLtXqv{NF!BYvG)8>w9zZ@hl%%1YN_YD3a}-K7bk61 zp|8m8w%Ue%+TI(i?@Sf0eTSE@ML@N8kaG!3n)$k_UG~+y8>N@RGO3kZlbm%ANE`hQ z=L6`+?YaT_<>U)+!)LD$6XQ7HaMD@2oc124y<;Ch(>ycjS>5Z&W?yD&@TqU2hg!Ayi+HY)1kyTX@g}zE@@y+5c{XGiR5cb_EHJy+ZDW#y?zCv z3{U6k3l^8FUtm0tgzBrVA+0;t)j_}$&Mo?;QlD~?eX>SLGJKWrD-c)Y1cWnKhwFjR zT2_ENz|5GHpKx;i)dHuJwgHaAw+?U+HblRENBHHr8`xUe_X$qQviNWrRFEW%{Vr$I8t zVz#Yk%gJvg3XkX&^&nv(_8iE{lE6_cWb}s;+YyXJ zOo%HSciBO^Y*f{A*3|bJR4JnX1X)wxZct?r-XuX_=t6<$vQD^Uy!(bw#Br*_ zhIGNEf?F3^s{epKVW!31ix5_1Mi5mRKJOgIQ}$Jz2D8Bgm04xtl*S7jB~kUxHmJKkvd z9J#0~{183f4xo@Y!4kb=?}gxqBn(4s2gL7!n2v;DAb0{RO`ZTFBq$Q+(&vPyx$f(R zYA!|1Hyd)M3$X9i4ca0a1^v3NUa;&x^n$LOax`aq$Hq6%d`Uc76OSsrLjB5>9h6uy ztVx6Sm5~yC*X0WlqkcNqIXov(4jzF@~&SbBWx z5%_A9GOkp1CMo$OMQ>tm**E=fC@$zLE*S7$S+hT(h+3j7ORLm7?_FY?ZuvdexWSQ* zwxpJ5h1)ocrEQdBDxw?SkoKb`QDUY$Ut0a67bnz7uzN)AcU=DVu0@^RD=4WKy zgOW+8`u??V!XZR7Pv_0MS|G2@gv1CLZbFerzjnqBsA2htCGm~JOT4*RdWcQodq;X6 z5u^6yItcavWTk%}ywFA zd7%bquohKcJJNy}VT1a>ZVaMD2~8HYlijzT{=n= z5|$8Wn<6BXt&uWvAyvfOZZY?Qn0pg}_lFVQR?i;9Oq`mZIC99mT&8%^*S$gzG`nd6AWGOj;#j|k?Ar0)0IRIqA>@iOV3Qg z8BLuD(e@&y>T7p;bgp|qEX>uNPUea@GODNbMK^W6b*h!Rkn~-Q<^BT>+Ad3O%)K;$ zVyx6PZp49F%0@$TykirsEH6SeC2KlS_XZu+gl-@jS98r!$K@0V@FHff@X&VG z?>{*?(F`3s$7Fh*MR_@rk3x7zfdiCRUrV}z$^?oml+g@<{b0!EU-KM6Iuf5xhGxyH zmRGq&;yhW;E~&VN%#G7?^u@m`(=6}VFK%J{nkGn_g82kAdTYTaKpXtAkk(kTj`#KW z&V5YPs27=Q7}K+{wd3kykvKgrgt~z6HtEEv*O1FCs$DxLi^nKYr>olB`dcS_eEUd9 zl*nXPT@#NXbHAo^WITC08wxH;oD6Oue`eM_?`<4agqx4B1KjC)ETU86NW&T0uRsNk zDXlS^T63*ad&H^TTzG%U%xgB)lgqyby(ed?P)2CUtLzEB%uboXmneuY7&?D}0wQtpeMFT* z>}fIOQRjLJXiu8Lld%BjieG7U&b86xE=mGBjF(18b}ZR%vVPmzL@sxba8Q?TKUl`e z_}FVWLn_t^j=-(zW>__b6#VcjHr7rmTX=H2 zF)rwrFq1Yv?JZV94IaBd5-m6U%BmkcxzQM?PuN&BQI$O4`(q*MV%2A|tUH8$ytx-q z3YHT7@{;<23C|1KG#{QddWLAtm5sETK9aJxRq_AmzD*)%aZ_)|T}S$P1ANULyb4;#d#4EAUB^+CC+|GgolRo3*=tspy#6u5oXXWr zTEuq4IN?i3w6~YO6*x-y^{r2PW2mIp>7)*3dDi}5`BwJVeMrndJpofB_3(hl`cjp&P9`Nw2#)tsMRzTxWWCHkfB z@#eRRVjEO7N@;synlI4R%0_*Xj;VT-RF%y}*(?62%IZ9CW$Y(6LJWPhi12)F))a70 z)jD~xw&QP0&psQKKQwxBz1`oh+i)akfwW6-s2p zSW{Qqryw+maOP5&u-JgujFJfpEgNrO+C+<%`*Nf_h`%K)gUGo@u7YKAreSY#IUi&E zMYJ^^FakNpaqb=5*WFGwr21CtE7427Dl21j9jO2;I#Xc=^d9GN=OYS zjEN)|I}=Q^7Oud#G88_<)|KoyF*g?;WxOkXN{7ac$CFrm2#te!hrdM1-dazdF^!)} zk3QeDFVIdw@J(0LA?~IZ2Hxqe8vQrMlo{*`Xfy<9Vy>e=;VxFX+g0wwG45i@O68*N zrgbdL2%;UGF;?pz7;l`9(AsU>doI!W_zdGpU?^E@K%>=aK%E%Q&?Pk%x5 z9mKB&QUyPK`*l$=)5GG<^Fw)adauAoQs0wJf0*e+VuqP6-n=y=wr+nL1OYZi^cR^m zEVK3z4Qa+_V4UbW%5uVT{0g_dt$)aXG~B_nvu0Nys9aLW&?sf+&3iPVuU%9 z;~(Y_Dk}D@=BnGmT#ldK_K<|B{H%c-k{AFm5OEtK$`Kfn8a%K&(wqYf1lFZQ4?Hje zs33G0put~5;}@>fjKs!g|e_F<(VuJ782EQ$(;EsG7f+n;byJywyQjvZmy)Q zu#kbeFs-{BXTeNK%>;>wYH2SW{&SpnX!;E_4L#FIzxmi|Ynlk%7bq6!Y59CFSw3h< z{bQH+rthH`m5#cw$cP#btR4AUr}D+w(bpn|0RNjo`h2au8JoJ9R!}p|8({Oa_ZAb_0a*m zAS&sy2v#ihRidz@Ujga+`?4@?M7N@HUPYiQR0|-4IG%7* zv^$;Oswd5nArEZ9WzjVxIQO7&|L_ADcNxc>Xoc7)qN?dh%D@T6dQ{aJZ(4|Ja59I7 z;#0%%V&}H9MWlaQw7m`U_6A@1(iW340~f8aFVq;n(M$Nr z8T|vg&H{xfRMfBGXDgw-&Za~r*L{={bLlz=*9DdO1`0wI&B2C^YD9j0wUM8yC{o&D zoHz`Aq)12Q$KD@gUI*q?*UBGJRa4>QF&KX&+1QzE!r-w5;K>CmW8{8l;-L2H10g6Qjs>4 zGqy3%hH!~@>H+|d7z>WV1ieI)Nlj|$6fR>@Rs*~fCU5j)JYby@hfrzsRmO;UlO#-U zl9-T8kbiuM02dw90c&bTRP87^NUoH?zg-Wv7BPsGuiFAhFlpWQ((vRn1O#2a{D;$v z^-HHg-tvMXaD)r0j?e~^(p@+n~6JuPHILAw(tSHJkVXC7-ajTFDnH{V}Ltkq;!jIwqL(C6rY-uLK?Y zq^zc{f03w!fnp`E*}xajK1-{Va6uxv+2p|PQ&rzo?dEA$VWXNG*SaPhv@JwFLp-Q$ zo%(a@5oLhdWO=)#YEponS-aoOT&qnaILDnPn!=qo6Q#JS8lx6tNLY$kRxSy6G7%@l zx{p3tume%R_#ZqTJTQK<@2*zd9E_XaZkuCy*Rs;4Z5+*M@Su!_8t%!^V*z9ZwqM(_ z{H28(^@ELCy6As8zp)X0aX*~S*B2C(Gt-rDpSkJlpnTF(w5#V}9Rojzq+%B4&+^T zojjOS&DxZ{%a^nMKG|tQrD#cWgza9V2jhWru$}a{58y|ZdO3`+C@cXx{q_Ifb~>fD zJk&DSPR~eqz&?uLJ(7|BJTd6+gF(OZx0c*N?@2Z~4*0S)lmZ5NAh*XVK?c^;Poym? z*@kJK^eeVeedxo>I9szP3qah2gC5H6ZdVpgWIfELq%{f;)FVO3=V$XwKv=lKHMXTN znHGcfq2TuIZzC;Bc%>qJ+j#&gys!v<_5SFJCfK4p)RBITSJHiDyv4p_O%`+p06UQI zerL)vVAq{GsRfif{C{bIeNYW&B|!iosOqA6)NKu0?uDJAMsmG}33Pu|1_dd{ld(D^ zSix=h$}@F?o7q(Ll(n653xF(ivV`t}Ri_4l2kT_#K9W!?sKos;Zz4i#P!6eNB-qfn z{IWH;-H;)eRdDE}Fzfiq)+TKmsYOtdyk+xw?xBO;W=Ayyb|CYQKyt{oRoPSO5d?!f zVB3&2D>hpLoTY2ic~8lRGFmi_@MQ3zW(&qCiepH4SiPA3()mzCg+`U3gJZ101Cy;~ zbk|?c^LpbX*L<$*GG8((q)!!xD?KG+0{RS(aa5=zrB|P(NX${x2gwl~B7fEdBYN|~ zdV|N95-1tX>&KEW`+}XLlz~x5@J?U&p@DpJD(Eqet~h1rjmzbYW5_obg6l6BcD0bx zfQ&HNlko=(FJw$6Ln@=wtIm5%Xfa+%^7iAINW7*uUeOt^3dGZVyqYvnAGBt~kw10> z$-i5rf1e8W)EiFkFsyGipf~V|353~=A_^$I32d4Xn~f&Uuz1aRGogyf1gaRI!I4k6 z(3uo;f;7f?vm7WcTuDPNL#>!KM<@dh2f-4GPxNFY0h3WHN}l;BxVIBI`6L*FJ(=vPao%?raB53XX^CH&Iz{M=>?ODZMd70SR78q7PaRFED2zi z&64ii^L@YW>^gkFLCwS}C(*Ixj3aoqAXmcqp+EYWP`e7Nm%<{193ILNwyXSnK=Y!% zxrPe_>tSfP0tpKLl^S0l0a2LBnhk*jrt+;$f%p5)ei2HbP`Xf2udfLL#SVHmQMi_d zjI&IX*gA!n8u>1;Jm!c91!Pm>pxf$0Yt{)AHr z6fb8$a|km+_O6oi9_B?y@Y5xnCs@Dq(Iu{eT#T+WK>_lH6PQSX2DIlBXb(nHuRmRH z=uI_rrrr$#D^NP}l-~IRM##ojv>FzIUx6V{-Dvr8540nq^BZOPU~x$xw`|W5{*>*j z$G(StpN$%36z4nu1IxpFflQ0qiBY2fpqc$TOX7Hmg5hC0QAII{Y*HKo=CyX~^h*e9WHT+*`ztEw^?nk52`lY(fZt#<;qGX=iG$kZ zq;|JlLdBhI8``yM;eg3P+hWYK)|fwt(^u8D*KW5A+asF)Pc1TE1V++hBq?pi!n-~Y|%7je7 ziE=0k*}qP;uo5WAX|iDC6P&7!wAUKoP#yTVx`9fWf{)e=0;xn{ny+`0tzmx|(?dK- z869DuTs%+SY?F5p(L{RCOw{fL-#jLbxhxu|!Z@IJ|Z}oRd_RG zSV$O(=|lT+=gxHJUvpD-YrC>EF-=yMWv5!TWsfu#$*EQawU1!rWUpGO>ek;9`2N#; zusQhySNHXg2X=Ta8PA6F{rzTPdCV--!bElx19jFrcEFg0d0U4&`UpH+t$$YcWX#EN z?7a?{v@sGr`fXYmKN6-_jnbPC18~p)a3Oh`0c!5f-*4EwJNVV*L07L9Vu;dtPw7(d|FydgHV)VJgX06uI@ z?e_vmGRngC)4Ei!sa@Us98_Ua0<--0yMrH{c4{I5A_Yjw@G2}Ti_4ODq~8F=M%J}> zK)JZDJ52pKB>ZLj+t0kZ(ma)eq#@JV4oG5beaM@B}L>b5U5}fUFAKzf1q8<(eDWFJ7uiK z^3Fb>+JRIBOm`UbFzID`9-s<0`$jL2(H|qqMnV;$3t3?Ek zk=#xrAWCG*?t5tj6MYKHJKquEhk~vutH3){_HcMrZJHSNz!5D&T1Ho#PD8{+-kgr13 ziwL5u>gw#qMu?s{Yro@`?(08xaEb=cE__siPYD7W-Ew|lAWdosP%WbyRGy5>kR7mv zN|WNt=#YpMxEHZC0gAl&cEyj*%FeK4BMibtCI*STD_Qa#I$d}l&I(7n(o1hVdA!8A zPZanvbtqU*BvfJjD{^yHli4Is-o_BUF=Ldf<>zGId(~&EzUJ%%4+RhYAajAwwl5U? z)UVzCHqmML67Aw6-MkpLZna0$Rl1fw$_w>NxOLBUCM(2bB`>_O?z!G%@CW`3t$Qwz ztO%1o-(8mnH7$~$bo!v_K*52s)3bvpJ5YI?M`U#;s+S|MHDw1}96a-H_@JJ2r)Q_E0!tBl1e;AL zHf-6~ZDIDIHXnW{g+0*C-(9k%P8YYN4svNYvSe2YSxev5y&x+h-jNzF;jq5vKzefJ z*}OYq7|8z9eJAVXMO4Z;_`i6%3p>H`&EB=O5ApOD?5_)pXg>w{i_I}3R#K*Tv1;91 z0Egs+CVYYT54jf`0;0OCsT-j@6L+JfR9f!^f5M(wLv$P>gRaYaq(nOB&h_@|dl7M) zr0<>K4(#0qL-f;je)lRV=wbHwF31qEBt!FZ-8DZM;UesyeBiAKZb?Kv`xUK$` zCUpv%{`YQZorNo7!12Tjv3kZRIO+)IdIm0zZ5;tv8}#OllJ{c?aeN>s@kd?{xnab4 zpjJWD@v%g|{T28-FcZuHS`Zu_B+{{S_bSQbVIzH6Q@1v$2`);|07<|}0c8mi9cK^) zUZS22M=9Qwe8?R1Ve&SiZL>^UPJvi4-(PzLDGsJu8#tljW4>(d;HQ7(`|Vy5+j0ZW zbVWw8&i9|v$7W1!bkBb1kc4-ZMtP@>Bbs3&o}HZRyM%BU!at)1_(x$Z4+q<>A(`!= zOJ;X-Pv3z42fp&H=+@)Y>=9-dj3yw4WS`QN}zaHJo*Qpk2O0i8In! z?T;aR)hCTjmQUOxz0iwtoC1(UXfpxYUbtGpA5n_hO-ThbkF%9_ICb3q=I$E6@8m)Y zL)ZYETYQb^k-)I5Y4D9%Zqv)bj)KQirkx|Cbt4kjGH&n5Of~`A)LCs!?YpfEfO`kl z<4uei5jwZmLq1P!y^#6b$i2{cix9#g2U4SSq|^qVIP3ughu$r@Mu={k3TR2I0AAm^ zP1aO4_hU`J1d17*Z)&fszd12EB*DzexW|++#SO`aTl~meXK{Tk2>8cb-AC!7L`aPm z0AIMH(K*X?1yB48RBNe(P!SWRVG|NP?HRmgsgR~%pF(sqth?OUxt1bCmAlhx$cZ+H z|5nH^-_y^3Q2mWpn}ajS+JF2V*1rADwYPl#t$g|jBpAQ^*0Q(7kd8wXu#O}4OyP=TM?}ff z8v?l_cVQ)Mo;;e=v@1B?m`h*RpQ>vO&`n1Ie(gd&zQ- zP``9hC$7&)QhJ0pmM#h;DMIAW(9%WTBt@9~`R>v@oEp3_(E}^LUhgmuyKNog2!VOL zOfrr=5fU=zDH-ljTD?k3r*c9?seW0h0hay33kHvJqE~reKzV=k%NqT{8hkm~tDM9u zr$oQ>>lga*lZ$42q|rzpXw3FIBWED^4jfAXw|mP8n_z9H^Xv=NcNWckGxZL`%a<)p4R#Oma&1hl^!sV1hjPnGqdB^^|z_HXra1QYleV&AYiee1=L!jBPtg>QR zV3$x+fl6RrT-D@Mlxn^fgV#dMh7`75TwL7krw}_MDScx=Z*?1q=0MNTC&45s>^&fs zLp8H14+<5`Plqa}j6yvvPsSU_Il{n0!LwNz+e0br!aM^|F$ZTzpWAJwa30@A#f;%y z_yr0H9WYXGF6P#-*6|Qa&t&6fK|k5>L&n zDgs>8g8hJ#-^PUKm#nETFMLgs--8UuS9eMB;_n0dCyI&P^DQ@|MLq(F$RIMD2>deI z3O(^YPe#0Cm_e-y)-P$^{*I^F&;X2P%e3w#TxYx@5RU>DbZ@+RFs5j02E$oX<9@_& zSl=EAJtXH0B1hH{0;4O-v+~$t2aOGO5A!YAhLZk_1yHi_@ME%zi@L2G@{MDx96|Hl z)W5CN$>8==vnB|WEgnkYTDr^f*+->GQ_2|jNlylh2m1`NEKp?r$v*Lch`lYhH&;J3KqcCoFyh!N8t!x|v$-8Zy#Rm6-919rOv&3tWjc3QT5v~yBG`^C1HfVK7YwE+&SU6VZ}!OaL>w)M7otvC)_;_AopO!d z6F(f+x9uCQ$E zLD$?NnDgqij6rXlgSbb*ODmYO|v;qVk$=CcDM&PFh<7143kL4px z3o1TA$N;hsgp838vLZUH?sBKg2pLgd?mRxaJ|yfP5~kn5V;sO9=%}=1X%FN*v;oA= zlJ}&(VPi;gAO(0;EWY6p3xh(A4B2vJR?4o%9)$6pljR)b2x(y8N&(V>`CIly`y6y; zku&wpOTL*sZ${&T1He{Bq)6+(3eZWw`7G&UmGAuzCGTJX`jvP_Uca24em&V@{76!i zzuxJGDqJzQ!vFuE3%?=_Xu)k6Ag|}u{bR4-eSuLPHKJOaGd<24E zd2pOVb&&l363hYkBIO&BMoY_J6Xp+2*!Dh=uN~^Sg9b`lkASw+LwDjEFGEc*94nRO1uget6as5c$uGvf(1`3L?&^u zcI+XF<^m}ixK0yw;3C9uz=0d0H-!q6ekGs0mpE`yLyBBLP`jHuu;>57>uIGo)l!yb z2|BZ;-ip#s!F61;X@1HR3SCN~EqCZ5ri!>uCtdQ^9&6q&09ApgQb?yvE-P(k&)jAw zEBy=b6G*F;JamMoCVWVOUU7#Xf?f$v()O%%8Obbe%Osu@Pevj(l$*{K>eu(+%s-+k zO=sK*V}vd1iwIEXP9KVWQAD+&fG12h2BsVNNUlY6q`Zv39rT&nzdGSpMr}S4t0o82 z19U7vaArTB0N3O9Nc#p7jOaNXSS1Wb)*%n~>yWbkXxVtNUk|eijMe!IE7ULQ=U7ze z*Z~yjbZ)d#XR3BvZhSzF9_Yr&WS&d+G{EEw31GE%(6r2{C#77*f&H*y)kTbedt}f0 z&4Qnc!)eAG`eXMj%PwO7xMuGGOzWf|?;r%BoQ9~`yxA&Ja|l7> z$B4OZp{^N+?d-AA!#UE!*?0&AHa?9{$iN#wT`F3C>rNjTN&9n?E<8JpoVW}y2)8?a zOoM7xVRK0M5BKa0g740=rv2Hv=mpE352X412)})h@PwS>l(ol$0jUcM&%^|h#w_nW z^7IH&HmRCohkNr21DRD}+77*_QVES{6tvfBXhZ;$0-09nV}PFIS7wYDyJ71G!ONdj z$24h44DU_^E5sn^p<>-!8z4gowP}<$;2(ZvY$6}y&r96*BB%ydC z^2wxVs&WcZ7?LK2>@ZT7UZZf&iIdg?a-QIP(e>a)ThW?}h&Tf?}4Cgt;1=5r7FTTXvU@$gZZs+MGb<>Xbh<&;*Xd z-j$8mfzT`x?F}6PtMfLHPrM<8!|#*7O}%tmV}MLre)k6;om1nhCzGgH4WqW8NZW)e zvJei~IGlfX1LZ-CH_5CU5As(dK-q(NWF91BLH|mmt!jDk-gWg^Gq!wiu3QtG_ZfnZ zp{kJ>Q4Psq^#~P9AN3R~@ylY$jUcH4+KsSCDFRIv8Lj;ygV>zh+6!!A&ID{w42`IG zxnFvyGq5Lfzi{V%<<9-u)!S4%(UYza5&E5RPe@Q=T;if2=32&x;+{d@3EniJWZv$R z8gE*#^*uS9S;i+w>cR5ypWy(B2r&&PfoCV#^a1K~_K84&HbDJ5fQoX|X={PTD)5u@ zn&>Un=WIyYlyDAcmWT!;zY0r zl0(FCR2iZx3;#rOKil09>!(LGOR7&Qh63z&#+iX2I67Nc;ZBzni#zq2e>BN@4f34^ z$rWzmg@90sK9G!oDhaf`NqO571Yk2jlXlU=yme zv$3d)DzO?WFN95~V<}XOOErPnRHkCe#N?U^XftZx6MwClbYP0$(|F110!EHWEI)T1 za%0&<=sR3%n5S|V&RUUSR<%ry*7209RaHyr#*nmkH!w&zhOY$v(3p9CZrg};^}e=4 zfz%gJ;a+%uSM$L`6+4E#XIG&N-ulhE)>f+W&Db?OUMIP3KMzs%uy%GN_0Q3E3MXr; zaRAw+r`h57VG(gor&!P{+8UTo+s}RhTrNiOH=Um=tY^Gb&Z@5#K4$R1Bq;T8N{@C< zlhVVfJft;GiOQ3l4xrcLQk7x1@--aUubh((yo(!}>D-dX!iC2*qL}YK zqN;zDPfV>=qbD!piX`6MnP}Lm6h%kkbfW`*h-H2W>yO;BI?_^qd%<0Btka`PHt2fXBQ+asd|~qp)Gzs|h!n8HkeT{LVCq-=)UG0R@bC#Z z71$>sX;aV_u`S_PcvzR7dk#DTqiFy^mgX(VPlx?8c^%OBsoUq)GUR3vIeN33%$JZB z@T*t5v1)DUaI$aJ4mqVSv2wP1S=$;QozZ7iFg*_mT(C>@8q~@ z9KuK+!;ik;gD#gdSdSjKokE)o{u&08P?aD-Cm0K|$?svoK2-q>NI z2{+)!tzXH^_&&Ie+*S+1tNRHLO^!5(6_cp`lWn?w?c3t*6z;Wb?nEI5rnpqsC!oJK0@&fn^YG|)I}BsX~}atGSXG~X$seO zyFe^IgL4j=fPBB`R-ny4R&bvaNS4FY!Ol7de<0MloE&4*P?cvWd2Lhs}ufloWu8 zA>ofH3#4k+NdHq41>ko-F)K-r@qKX)c1?vz@T*K(cU7E8J6p0ReY19OC(psZX@IcE z4%T$!I0S?$RIyKDeog`#6K4-{CQVRBOvq?e)tCgu*!WoNL=%0+6o!`pmw(X4f9x`= zWDR9>&rGZt(Scje;bD$R;O^fMT-^cZ%Ckgz#@e4iolh`6dVsWeSW4*&Nx=|XE}XUe zZP$Q*)@>4M8CkNDd%m%V9s%dPXbM)HC9;})>GlMP?WQokz9V=8RleU^bsm0{f8XBs zB~ZUyYj@#tz+6Ka#16{$AU+?&e3IFDmL0y~Z|5p_{W8CyoLL_b>SA!fRrpiAV{yW) zfdO$~1y*B&W`|#iU=oDX<_gnRSJV-s0rxH3zj2hQ)VpvDMa_8hDq|Oa;$h-Tv z{o7~FezP&LmYi*|GO=+RaH8ejUBocMH{_a?H3+?MP2bT>%4s!FsF)S}8Ac^*Oz;Zg z4T;Z6I{I9Wa|<7R)2~L4A*~wKE^+zW4s}tI8;ADyv933^2d^CmHX)1#lMpNnI8K3L zRBi>XX*4;6iUPuc=A?&Fp?F@^gBkbe@+n0Y^kY>EUMyDShYJDLxnikWl)oH!bS z-xvdClK65B$rJFsxIOqeD$q-DxmhP8h(p^=^n!{BdUQ3J^kPer`Y};+!PF+I&{O~& z%kGH(nJIpJ>r)PBr^+?q7`v!pLfUyErxP{mK=RK-E>_ge5xF6vcCN?`6}5#TH%!zP z@yX*`yG4!-ad!n=6z`(d$nOntxQF^K-bJBKv{$1(IozupS~`|yUnj@l*IpOpb#RavQ*UJI_{3c+*dTFCcuN>1);gc#*b4c35gYL^a2Z zOw}3#%!k$~>g)5>EE-ZdWLfX9D`Kw0H+RU z3j-X`hj{@`8_*U7xR^ll_<)N6(E~0#eI&pQ<+Z=zxgm%ylzkHpz&`(kv4FFQBs~#1 z%eJZ$2Zpd@7DA}ud*25rY6u!`jSmY8yMj0-;K4%q zpvNI*C0f9yF`V7-&s$)(L#y?m#Jb;?F-60JpB)P^Dp%F}MW}y}UARM2sjSgwwWd5o zL2CYC#q~tlR$XgZ1nai&vjDYj7>8b*j#!Qsbb|w~|m_^Kg@Du4!uQx=eGN zRaI!6$~x3`YuwLFapPN`v(D9+=4#2BTIXs_b2aNK&B-R!Z%k9;5Jmw}9n0F;wo$~y z86=xz35aS3JoeP#2B#%#Ut#k2gDech}{?CCM8uAVhksJa==$q@O(8^QH)_C zYCDlwG3t=ENS0V(BEyK#@(>x;FSj7HPC-b8xw||r3KiTDBomfonCOCKPkUn2CtEy_ zSs6pw*YF0uf@VEk*P>LUd?kPOXjw!KN$@}#kOGf(B7q3BRu4ycl81XZ+M~VK7x=)# zF&?uba15BneNtV%dnz{sO0>{@#RIocdf={VpKxq-6FlF;n#rM!n@Kl70{-p&=KNbx z38;<)%ZUWsaEAocw8iF3CF)zh2wd1=fD}wWDapXD7x16O&r324dutg`RpRLC0M36u zeiP+0->6$N?ylh9tOM}^*Z`Tj8AAj6Z-#{2_19O2bm|SB4@B)Rs$)8nN5lLl>5;Kp z^^=U%`}ZYxn6c4fBqqmNfX^-SqK*Y}?#5yN`{-MTtoq5$MjEI6gT8+?HXzvqJCq=R zsIpI!bD4Ye{bu$SK_{JyB0*9NZ}NS%_}WyT({ee?P-3K`O2~svPY6F(Zx(yWk4gb6e?bFc6vGk!i`pwVRX`hU#DiB91 z-y8YIQF*2Je$#?%FDMLg?+3pl*P?E}i95_+A@a0%4FY1cn$ib3UaM=hHPBuE?kg@V z!<8*fD4{^&1k<EE)HewVHOl9v8o5? zuwYN0aMtz6&DxEYN?hu!()-IR<)!l{3d)9<&SGj3cn+%QNzDdvF_<H!YJ3`510Gyb{zJ>>5?Q1?Xdk&l zFdI5k*_mZ^a%yGHt`(Cw%hemK`XS0sRW&xoS3QHs-2cnk-+(t&o`2x@$w_jOwg+rO z8`=`J=kzU<;@W^vO4TNPAyiZnpoEGW>7-OPH`}qnm~L&*60mL%oD@WtL`zDg2myK1 zewBy?p-d^Dh`1pef{KnIzJZe8=YCGwg4_Pr|94$KE`{Xeoaa2x{oK#}{t|kcZ@HBl zQTOV9+Ed(0~FM0|CX9{#{lXLdyKdAY95>WnKfYU7Kix25>v z?x}tt4!{2F%uDoZreK_|_txF|Ny~6Xdmh-)jX+UsjN&Ap^XJXp zG)Sa&z9}P-!(m!|Xd4hnWCE)xT69P_!<8(PA z)}wK|baF@FR|JiAJ z({q+u3W0|Jpze)lG38UUl4hYMpG(_t+jp~605ZU<^Xk^Q5S6}qZDPmp>fQMfy(X+t z?O4b6yvPC83+rzEK-fT3QaktF=-acADU8+8zEm9%JqOkFmx@5tww`qjdON%SL$sYYZ=UrHzMySiWN&FceSkCq( z+lD5J%+j^E4r^)|iOJJz&;01R>u9Vz4LEb-g+2{_E_glTj1`Z=Wqd|Z$Y1HU4CFs! zdf6vG#?-`#XC9>kk)AbY?q;tMZ?FCat{w4bm@}OdSy;jiJaXnZJ<_dfZ;lS!oq8kP z-QE;^B)*G3xv*Q?K0aDl!u%NuHNuR3+HxX_`5aQClh>Id1>baMcm?0SzbclQ1)&c| z&Ax-=&TgH#cF(`A^sV1i2?I7;WP3&Q?Z=Xq|E5g`4mnxq7_I^*)QQndlP3i@e`R2!-z2j_}aX!5Yjv$*JEfqmw^;Y#Ou)Af!+(yN= zl>5#fTH%bd>KYw+n zZrv#9ciX$rm{;jkE%GCE;7Ss=V^8N5I*qa{^sT={^g)$ZXEqwc@zS^3_dLgbGuMJI zt^Zm%jBIT21&l7y-cwJ>tM|o!Rm@j*Mul&pTqBOwBwm;rt((aUEzz7@zUA4durSI% zJ~uvEc#xTn`?s-?&`S9&En2wuy5GbxJ#JcCx4sL}!^@=h^r%;2bVZ*HLPvP|x2s)R zoL>x~$Ry48Um*&HE|k~Muel?}fPRhnqz9!|!6PSZr}!Q;mxWYZMI2HM0zQkzQ@4*( z@VU9*zubfO&^_6oqJy^--oEEv0uDOZ^o0r;Xo!l9^5@*Ur|0Xa)VV!SdKHAsc?ASM zRHVQTb8If5!j2^4)kDT>a%EtqyE;-^7YEZ+^VU*43gjSf-Pp4v=s9k{G{~?9)vpTM zjn_kNntLP7LzDg1RmdO2h&i`*JMO6$x?zy5g3R&u{Ymp5^QL+rq%Mj*bNDKKm_Osp z!K-GiSjJAX)VzI99xZ~zywGph9Hoc12MjdvEH?2+`d3yrif?&8nse`}o_|LP)+^)L zI$k55fgmeUc>6a=YnOKDZ;QiH;x&`j@|9!3%In5`gnv0}-S)tw@9ml`L$7$JM?y~m z>Wjn;`i83*5KA3}aVaR-zrT%3|u& z{Y%96omr2zsFABEiXOiTSDaZ(@(%(=a5wVKtWAr5h0jGg@lm4P-7gK$ZbrGKvh85b z{GLxQ)560o6wx6L5tB2HVqiJ5r4sVm;3YZpvHXMRLrkp7o?4y!MJ2k#-}({sbmRdb zj>5m7(D*Ve;C1;2D?f`Wc(^h`wG>75ifNm@+SU%x`blfG;5s>rY%q+DIScE5m-35~u`(1^1xdkOoEBwFAxVK7Vs z+IVBimC8?|TrOmd*c<{>ml5VJQM2OF&8Uh>)0i2XhMu&Evn>dZcl`P#@N+^kWw1kF z2w*l3&OLaQyd6&PyAgzYnru4o(xsOI%V|dIFrz(Z6l?Zx2Hx55=wtu#?k|-Xw7u~uHtL~_SUKY<+rWuw}vXVcBL>S)($ya zh;JPSXeLIhDoCg7)1c6bD9(NLs#3+RAEenSH2=LX1!`#iKd1TkDf7>%eHE1` zaqUc8v~UQ+Uht@X?QGRcdrFX)arhmyor29t$(8pVyt-n=g0FsiO85XwZ~03BiB@T$ zRUT4S$#DgqD|aO0f8d8H68J892oWCHzx_CHB`PKy;@cN}jK$-(!mpz6r4-vbGDWn(U z{ffpT9pEX_Z}%V=^AZ|gz+*pa&jW{H+5>i0n{Tw9h*Hyv`*#W_N3HDJmLE^!j>5Pb z1i0lvuV=m#_!sFkpGTq7_Wbb*Y0cZ7njT^LBsts}4=@gb>W5Di7W9^ab9;n|FN( z^9KBhAMWl9Efzh}2yrBm7I<#IB-h;9swl_Zno!(FKEBQRCkSSFS#WxEkPr&D2jAo2+{>eu zq{N!)4y~mo&XOb^>_j#Aq6SNi#*(DB)Mzb9ah4jvqDr<@4YedCSZef^EQEqijJStl zkRq)!DK40lxc|e}H(Z)LDyIpCmYoAOipM5 zT%-%z0!v9`$6wA!U_>P@ikh5MnwN7pm#_J1E{_{^bNQCv19oYEN>fYbNBDg)zNULp zx%u?~(#&yu%WtsP3>Vt!<4(R4xMy3p&=DWW8@1*`_?Sel?ZXXm#`zp&jhwmbWA|Oa z0k6iGnkvR2mc}8jY4AA`vF*X(TrKw7rNRfaKMfl3H5D7rzN+!n-MK61(yU%p*ala# z5FAM;@C-ULa=?Lb-pxMuP#^&sM|`-VvnjNgxA}Q&xy{Z&a8y3r6^FgI3)p*>wsJFw zm%l2*H=LG-UXf@I3H?({zpy50O%gmIh}5vgi*W^OSNW_%+fdZpH_}G?8i)H+gQ;BW zKM-;=oMRz1;}22XAti%10tL(h@B@u+N((eWhtTLiW=67t6Fj$Wt)$ylm;lJvOoL3< zp#>d)RHx0?K!#}6GK4U9@Yf)OMbiEMz=$Gv_a_1yfGcJm*sxBGU<@Dw^E4Ed?xirz zpi?9L>ndhl<1}k!gGP2?tHH{oUv3KsgaZPsEZRt53FczDMCMvitSpX-8ewO2v_|pk z{+;zRlKmb0x&zJjT?aeKHdcZ|-F###y6MIYWv~>YhCXN!dAK?E5qfA&t>26g1?Ya4 zHuALwZv0aTwFcFsr?i!DJ;7k@eirNgrJAmYQ+S@Ryws4`a+)&l+9r` zhf}gsbtL0=(!Hm;Wov$fl7teUAJt`+_#pg4!`fUC=BjkeezDZ%# zh^zvOr*nq&{hs3NQaKT(BC|YF7waPlpq}z2Ni|oov1?^B)qWgpW&8h84@DL%FS)L8cht4 zqTK%RIS;SOuw{srlizsMs*@eE26NN&+R*V%S3g9i&?hb<)1N2F#NBCL;?}^sug6@( zhj^t9GD08<7w)vxpjV6%;zes{<_iD#413_;t9OS~s9R+3-kjMqj(;Gli*;y$a1@{2p^I?z{~Z8Jf?BgY9Zmu!F>DIYhp; z(QwMsygmvmJ_d6cE_(d6OV^6cPIPdkll&?!5di4Eli`3FRri^TJK`UPh%G&}MQ1ii zsd6V67U`x+4iK+uP;Of||Lq zX5RQuZopEXD&|ZdT+?G4rf#zX3FSHG+zD= zBL%0KFe{Aa@n6Z^xlSH7V!Q3BsZ*1CkI9-k(-G`w#UHE6)`9(#)+4L2Q~j(UVc0XgWgIme4gE*PBie-ZXO!PlSPHUY#TLABeXosJBk7 z_9LW$IuMxl1N%ZnDb1InA=eGkr5(`ac=4btclMZ(m(KHB{-xlY;B#x{M$SPt*DntQ zj$R`ST2v_?r^=vuEiLrRkG*nXu$Y7`SUfRLqIcNZI?M%H!O_m^0?<&Zhlw z3D(W0;iAP<_gsz^EV2eZjfi)ZPV$3M5H$9Csu1Fd4!PJuz<~BHRHScy9UI3B*_@BT zeeJ@9siagi8dSaG5g-HdtSPHAXCpidkpeJOxBk|nrvw_R3nX~I!7!m6I#VY2mynD) z*MHRd8uDGuA& z)cYE4tru{)HV4<@sW2|$y0BiYJVPbjcOB%gX2-cLfvpjjw)8cmJ&~pBL9Ed+eFq^b zc80ke#};&035v*Z(O@(Bw*jI9JLj=IXy)96zJ zH(u7E5L+dDAcml}WLb)bSBKxI@KjWIFN_Z<=fpAWv_cQukK%1!f$+BsZv^0=lhLa_zsg>9FK9vU8u=Iz%=~++!y3FT zs9zIGD@6(byk-@bPwtlWt9ik57ou!2vc4!**{fQ& zT=BPKGU;9Lwr_qvqtQ=@*jP5RaNTx{yGV^%DUG>nk#rHBkq9>t!hqG`ltflIHxu76 zX&qt4KK9mbUG}3ff{_Tm3VKd!Y5#EL@GX8;3J-bVaaavjf*b-0V{Wq=7bg+E+c_Y* z`}fyoBX1>jYa3_ryoF$?UFzzw}DX)pkR2j@B~rl zz>z3?O$xr3W@SuDCw6G`49(?LPlHn0Pn(nPP}W* zTz_p2ZK212QvDtX9eU8>HZUs0O=4|C0t&OY_g)rdxf~8Mg7NH1_}n-Tn#xj!mwC3$ zPXT$h%9(a#ibL(QU+U6Ea1F&3Rb1^ESK;1{Gm?lZl3%wz6ExYc?rSp8T!!;;AlmRjoB+vz!Bwg_BV|F{=#Q z5VSeXz&IB7F}z#bGJ?Zb+HBJcEwC2wvSWnoFwOiKA9R@J{Vd*@WD@0!>#3}-i;#6nIu(_e-eO@e)$p;2&I1LV!{&_;ic(I$&Zd>{&T;#xhRrW3Y_%R+2JQ`6 zoA@_y*gfKVR;F~-M-)rVNjP?)uK)u$n z;zU% zFaAI_9<^?<$Dp$KFPKJ+_YM)CD=11djp!ZYnUM^0Hy!Bq@IlwjK3B%- z-CFTrC1CDJNzSeR0yOe>phV~-_Qw4Hyy*or?nE+d^`F0Y8dRoH+vk?*&fJEFw?8mm z_wiVdLA~)D>{m@t{Hpk-j?AY%QLVo9#^v$_Ica7%#f&CY0Cuo_2*YME0nFSq$}A{H z{yJQdw*Fm__Z(SRlNXNW0r^WDwXvq8UOc!o{bmmj89oi9K<0HP;n0hTc0(2Es+*Tu zV&LyTq}Y1mX*awGbc`uf3YRdw5xRAV>CZC}{d6;D+^y?Takc(mh;PhGZ){$$&AsC9 zZFmHq%LN$)tYDe&k2 z_v26g!T5&Zg!ShC9KSid2~+jzK??f?X>ruL_~r>TK+_nQRKN(Q4M%b^q4?a7*ve^M z&uwpu3M}OsKnILqIwjTORQ`Y$7yfZm zVAiWeYMg3DL;65$)SUI(t+zpF4njLWo&a|0Jr_I>g`dVsr&ybe&K|GFK2lVB>JYqsa(1x~6YX_?+3%?n7}2PG~dl-RPK1&1VWdMrkXGKpl$%hb_Tg-gCy2!Ai(3R>lm zk>gsP2D%NI`t85@S*-_$byK|>#r|<*6!pOL<`de&uC1X7BUhfi5}K9i(grlIGPU&( z$}xiB0ZPD5Y(SMpq&(-IM9!rTT=~EMyhj$wPDX0qQQ3smz0c=g#J#pE4f(0?Nfw^M zc~ml`*;r<*qMxD?j*Qq8_~`$x#SuN;J;2W(;N2DPShDq%adpNGij2s1~zXbm&jFuB8(2qpW%zN@NbTfyP%ZsF+pTurxz$*!_nqYBxbxM0x(*@#1z^zes$lQ^Yb4mq zhaefGP1>K-dIAYcaCt&J!X!al%z|_BdFSNMos++JPPrS>NS9`fgrrd@;t+sjGuQlj z7bvXLjM@ieeS*BzCdqN1wMG;+9l@PQHKq(?4Es78G{(Tig90#1LRY~b;+30oZ0f=> zktY1DUW-+qT9{P2g4FrNHj8Eq?$syy0N;?L?*Z#u1Ak^i%V&rh9Nu>F>#)7sS@+jsum8O9%T z9@_uqll}84SDV(XPp>w1oIZ&d?=wy&16u7S}B%2p@`%mB}@<%DD+Uc zykJV|aGVpBAVCUH#RF%XiA(tGlaf4ff=^0ZQM%x}T_j+&5FfBwh!3DAb`TF+*59#Q0Y*sV8du!2h>vJX8*`U*X-X!NJcf3~nq|HJ zv|~=gs70EZ*e{VCxi3B_XP=7a*5#2COat>hoTJW8ggDzD}707C5zL&Vu0 zN1Vqn)Z>WvdX~ApzGV#_Lz>5t;xVLq97Yd6&SSmB!;kk^f8^ndJk|maKfz-y^zg+V ztHr}l^jODu_!5tGtcSnNW4+a5xY^?v;W1=*93~HM^H__|%sd;8q`V&xXJ^wVb8t^a z#IK!OjnAXS*}*;8XJ(vLXcNJRR)jhg6i$D0m-XA+w2u<~#?L6Nn=o#7tvia;vqeWM78 zX+kiQJnEGQOM;>*1heUz7dBTW0b!3Yc;WF^YdQ-$6Pd90@E04BEz?1InS9;PZ}Pvq zOmQlQuSRjwOE+Jd3bn=$EBPI7n>U{}aQmJe>NUVKm^u{0jgAL{7~x&rc6wkhWSV+jD%og;ZK8~zzhCOyLWa?fZ%N4zIgc=NU58igOVzGemt2;2DKzp?cilJEs2q z+dGac^&YU-j;52OpH=!7X{;AsfHni#OkNO^>lw|`^wdz1&bWL?ZH#En;U}}xu$E)mG2sWa=(f{?t$l9ag=aAx-&kk$3<@bdv z{xrgSHg)LQolR30?8w#68+C?o^gjLCKRf+jug*?DxcAy8Yu2DZ!Q>li%m3))RT%2i z8P?)0^V+jyU~mpxY;$0cv7-Ep)2c!dP_{fXFnm)BL@`{Jsjy|d*km;WxlRq9kNPpV2< zaZlwW+>=l;kM4O)CHx8F(C3~4Zc2#$9mfgFRov{Q^t;T3#wX1lj)8FN?A*|fMYCtN zXt>!lv7U&k(f>1isQiU$c4%QbU-_^Ky|itDDnFe2WV~6&2zr(f2Q}jbF&-{h_zWBO zOphL39Tm1h`c~yfa-THB?#m4eis1;sHB#?2_uHd~TcbiqB?}xdMJ_L`6;!o7dtkrc zK927Rz);HDG-qCAf2TqIn%}bXc0KKiDw?25_ zlz-8xS0*je1~nxfbVA>o_ghtCvLU>;;NodtkSx&W)-`}+RJBE zO|G%d+-!$%LdN;F2J1ubyW-%pZ^;F$29^>8L>6L)g-TT;>y0sqYlO{k$0BWqmF0k^ z?P|b`VqX`%%VxKT0E}gKtJlzvaDO)HXS6lEvSSgN|Ltcb&^&IzG==(Sz{M#*yJS&Q zl#34)rbcbkltD4GqpC2?&FgM!knJLGSKRU(CM_OS%h@)R`4JibcUAuB+~K@% zZlDo?{`-WXv<>1#ET{72A1ntm!(jR2 zaWCe8BeZbD&_@1p>r#d_xnbY{eBZXq5Z}x1hE5=B;@8Qsg`4}>oMm}`%a@3KN4VO+ zbgVW(Rbs*M7yj~}6WZGI@l_utv;$=#h1FdDLBx?Kgj3F`6|>3t*{FO=?$b_0fLA*+ zi?nj!6AI8A7Sp#otd>k~1f^?8Ar~IwYLBXG1x@w#4EW`1C#|ZT^duGUx!X>PG!yhw zs1~S(t6a?FOtpyUzRjDrE@|0!74ufrc}5Sy7H5Np{KDs3+8T1(lHnLQ3TyEdzwY)4gc`6{!PfG=-` z;!7`XYv>iiFR){`@-)>Sk+SH5% zE<}v8>SH%!?haLtO;ZYgN|D;%{u;`ri*HOV&p_GWphIP|Qk1<4gDEdeK<#?S*pPGF zsuSckh&EeR&Xl?#vC!tb5!lK>%H0sVSI=QvoO3+_|279 z9%$1B7WS~#vj{EuIR)V%{GC^=d}@;n^B;;M=90n$T1r}sH%az$vYn2j^u(qP6_kTM zt(ojlAQczZCv~pxHK2^JSqm?tO`dGNh+mM}h4R2u927bxIEl?Ppr^C7HmrURGWx0Q zNzM8V_wl=P?WkkHY&FZ0c9CH3O&T3ruUR_bxyw0 z##PpE`DYjUD2FX~ybdyvS$6BUxeXxvbO5T23(^qb7xNj3g z`rZg~YObI$33`aL97qt1yJao-2?#`+8NbQ$l0!q5FlA!S4`&# zK0GvFJfu8{^Zumg6stRCepmy40)y7Fo4J6NZ|6xe)*FfH&v{h~HfPhSll1{P$L;yDP_#YUa|i z(+nRkVKcFKEzlWdVOBcMbzw*QG}iMYfy3fg2{s74lg1fk`%`AEDS>SyCPQN4F(lI} z*B(PJGrHD8rm8;B3;zOT2N2LI9qoGMoCy`UR7)qC&^^J<9~xrIT7qp*HpEs!29!$J zTEqQ6K8*{cG;dPQJzAUCd5n-nuTg%%Zsn7H2K`Ms)-ga5C>Rs^+dbbM-abeZ6naqL zwKg0&e#(_pGpXJ{X4(f9)MBD@G_~cW?&1za{f{goKX)7~G0e#g3rsODlyW)gKQ(sV zV5*pzKD0*#0=HH)gu+##eB*^i%|ypDT}^Wqz-9;B^noL)*8U zk?!hGv_8b_#jVVrQoTdlf#}maf+vs%A$18ORft?Tt}^C9N4Oi53fLv4+cck{H$rQ2 zB^tc`>3B2WfwB*JB)SX+vmum?fc!58WWu{C%oeoHJfu%kio?+*g#E(+W5PR%5BPTo zI9IQ0e)u?;Lepc2o++cF3+olU;5~rZxJ1)a^MG|lobmFIob);_67}J{9g<)YEAgdudaG=;V1a@*nioJ!IT>uJ#fPnUop_5KObB^)J z@dOe%#wQy>p$w*0niW!4hPzFXkR?$$lNo>x;ua?mbZT?cH3S{5Frh0#j}h?8WNelSO7>&Gh0LFN3w zi-Y5Y@dt;F?P>GFA!bXm>W=%1$d*)E#sX9OZAt&U6gvK+<|Vrj6z?sAC8xv{Y?y!&6rKE%fUIUC#jA7k5S>^J`V*pN+N$2;*Z zVh}RS{^mPFX80vz0*PV++m5j{@P*j!RYV#l&)}Iu{mW!`SIc77+ zKIFZET@ZF-BI%W(~VdbhxCJ%!SAGZ7IIT~9FyF)JQS zhKZ&pClyl?rZGN_#j9|$k1t(2#~VxjgcuJ$3}Ts3^XOvjdX_p3A^F z$9OixzmC;fZ@CmYdMD0o;pBH=A5}U5|K%vtCMQ%4NKPJ$TCZ8o6b{?GWHZ_0Vemr>U1mo493MnbBdE; zuf4{8dkaU|*(Ablml0P6LWMs_44S@A`VeMJVj3Ue-4F{Ai=*;QFGmQCZ+Zo+y1w#O zaI;`s)L5hGK&|%Ec?E&ZudhiGDaL6i;*}%*rf?N^psuz?1(IJ|qb7QfC@0W(RONj0 z1sZ!clUdu6cB;aYVFSBHCjbc8g01hrW7gG7w}Tj8t02INF7>SkvR!M-opSl`?(1X$ z_Z_r9o*d44;GG|AkP>?z`T{P1o(wLCN| zG>%1KV}8vC+d)otSr6%?OT&L4MvM4%kABU%a|obw zYR|2kTciQyhBVeCptRw6&~KVv3diBKPM)XtTJc%sw5pxF+GbTDTG7fot@vAT@|c`f zh8xwYldVI|aW<DO1KgH`dT3 z5w5y)%uNv3klw6&A;PP?`aT}H0PwhE(LT(8aPWOEey^}=53gF$mY9>q*SQRy@?z`1IzjhH47O$cBSvOPmI0n==u{{aaY6eJ z>^PKblw@j5#59L2}+X? zr?%ANpEJ<(!Kngyb7G5C*hUYWM~FZk*gHmB0d)7v$Dl_v@?1@&UBir0)`mQ60(0Ga z5c7f(wrjjeNTv!+K#^_=$BX&K9%RB^kXMEMmskF=6NdWGL|qV$uoprvr*_2QOq|Yp ztR$gJzbt7D+&LhbZ7OdPKpFI3_P_koaCv0}HwQC%e`=14luu&j)+`kGt*OR}?OHR* zgV%6b1z^}$i6@-%$ixQ~q>J&Qp94>BYF>J*pv~H}%x^}1o|p#zu+Q#9bVDp|H->Y~ z|9&1|hu`sG0z5|ff!}c!hDt%~pycWdPcuRyBx|romSR}TWRd1mu`zyj%x`96Sg!M3 z+A+qkW_xF!y40(u48q4s?uA4%i1+?W*4f91YV#b}Dr0M4YRw0p??3;F{5Ot`Gp-W= z#W;|49xM6T55_61ItF@b<2lgNB6Y*==jpJQl_HAd8bLvC&AJ$xP6iOvPs)Kq2x6wX z%zAUDL5=BGm+mCX7d{n}7WSAH+;$WiyND{#XJDogxGcf3SxI{6+jlXfdRQKOV8RFs7-@ zn&LWekJ=h$%m>$C@U|u$LsE?sz@qZ&iV@6lVM9IoRw1>09M0P_+JdG98{=z_@)p5; za!C;)OF$2obm>bTSBNzjZl${t6q~S26wH z0K2Z}L+}&G1dhnUupYU|5&uoOt5K4#CmP*;3(m&&kvuLnJ#Up>*|5EeN0F-P+3_6| zc)0VxvcQ^^A2)p4jL-q3>~}!IqG+_JBSKZgP(pUB4HpfH1EoiLzi8s)&KkBKP<8?o@sGzYXzoGkRm-?YPKQiUqqn~el zR}CpbIZnYz&T9gTo`y3(QHfY>H5NBz6W<5SVDx219Z;9YN}h(%Lu%bX@nt1X;{rNd zC{Sg5usKCJD-Qor<-CE=K@-7YP;mT_e}|4w1gK>#v&B`EmiiYse!HRfv{_s7f{l%) z#HGmo-(-A{0r|}V&7lwcjQPVA(K;IjFGYv7wj6~#j6>!4`Z*YQvvCY!Ys;xh{;Ec6 z?9}wc_uF?fDV85-)dgu8hE*%jkfg&|8wO-U7`LTgJ`a*~tt|HO*N6W(D2r_!eD^%U z9YRyeH;AF>F=ZMGd}+xsn^qNPTx<|*=wp21;VI^&a3S8oLFfc_M&iy`Cv1T2>D_hH zJ#pu1dDXfi(N$-hT+8!yIb|}huIsxEN(x68$I?aPEw#M5gwK5{hcuPbW=+Za(2=nV zW^hKuNEx%ZPML_@4AVK~j>it^QL6@w%7>Tg&say$OZTmrfuw4BXA!LMe>oF=`%1258i$qI z{C}AARFVzLe?Gyig;*q`fD%IR3O{*HjAz0@(XaN@eSP@7DAeNq`_lj}@hF~)J&^-Q zV2v1*D?IrexL}cb&#bSDes#DvD#nBO!8qsRIn=iH!Q8|1KK~z9!&y{}i)t~P3;$dZ ze2D!XM-0?P?Ho|`-h|>TPw<;tSNTR}H|@;m5-3g;_BKrwbUk1BRlZv0b6K!;dy{f6gG zX>6*^?x;)AUO17|cPP;@7gpv4z!V4#l!iGHNa59r2-$-0G!|c6j9X-{fFVK?;})c^ zkjTtS)yzcA2hG0)n+ZLMXeT7x$bAXS(h-v>tPjNIjPg5G9eq5N$c^ymc9{_Lslq%M zWirX+da|z^ipNK=6I8n}YkGTS`BCwAhlbD@;GwI^En>e_E=JFsM-+PI;Srq!idJ6b z>9<|Uyb}0flU@lD#bOpZP?&i5Mt09I=4oM`DA~VsZH5IFI5}rnxs=%f`T~*;jk863 zIpWX6ds`4UENdLirjFJ=*b&*W{gkdl>(S$OOD0-7i7$hyD?Sm%lbH-@9d!i0snSXQ zdeU#Y)FgUTTCHn>rZ?<}n;<)dm=$`7M|`xH>QGvU+H2EpmT^`SCK=pm*(x@ z5t=CXT&>M|7IwPar?j=&-&eN?_4*9|rN*4e^^$grFfT-Xq`tECip5-wR1N z#d=(0Q426AW68DUzpn%-;|iY*0WHZm3)*H%FrBXiYbk8I?qdEF!rz!4&-Q-hMp{-a z=+>Y8_Bh4*-N^G0z#1#3H5z!c+*qB}U<}Il|4|7BDnmRu8Iapl{U&6@ksCYXa?-0> zU`Dj%rpL+tU*x7kd%W=i;2|vv)fpjwlPW-TH>tK90tkj6q==y~8jh7v$O9)mh|L6l zA}hM=|2`up(On-}=QP9V1mvZ@WI$wk7PwAT9GGocfT_+NN5olsePFpQi>h{`1}b)w z<7Q?ty5yctego7&_(dOV4`KqSfHQj>>i7|}0i%I)`b6LwizM@3CBRm`+imOn9-5#lG32J_^*|`|*XO2Bko^zjrr$yPV&<>mL(&a&g5=}KCy|DP1__JlcT57T zL=3N_W4D|T$UdwIg`vlQ_;}1goE3U@6Ld=HDvY4A{2tp}1?1fMYzA|wC4eQ_d3J7y zoS628#>Rtr?{**;rze4%vTag&yv<)bDP1$=(MfA>zJ7jZ*E3=Us@gAOSicLHK}JC; znT?j`_Wb6{!)FMFiX1s4hrJgsZN79^Q6>ROYSg2V?WI!fwQzhQ-gMv@era($_IT$k zW4*Rz2p9C%hEj(F{r87bb+h9`sX_~A!hgVR&kyG%y%X>vbQ3ZniEGp=Y|qp$4}UPY zxA}wf`s;t0SIM>Wg6EVEO@MTeyZcVG)~Y0w4<6_g(?Sz|0H447a2^~m#f!KEHWA<$ z=5foHhd&&g2js41DWK@j8xQ|L_l@b|%RUbsmwoCIR4TIgudZ0KDnHX=RTVzE-eV;y z!+WU7bBtEDD(jL&+Gk{3_p9~F8ivpsCK-`}M72T?9{u3zwIjR;{Z@h(7!DD@s0JcC zBhsTkoPPAu;j__#og{-2YE5nV_Ku9D-`+uW`$p%oy_VG&_zxM975r;6${rp5CR(y? zwJ#&0Rvo?+_4(5&B%4P_w#I7!8dD(ldF(3cBDZZm9mnP3dKy^w2=6{z2Mcel$GrSh zaY>pJ2z-PBJ6k@uggS-)jK=2hV|s5hC(S;LIQi0gYeqE;KV5vIc24!#n|x}O$-6?b zLWphH=g%!Nm=-Oy@I7-mQ_)fb-!qRBe#+(VT#D%Axm^DK+#()=tH=Kb`fUyuR`cRI z&%sMjHkZD_x6I}uLG{wvd=H{(XK|eFW4>o5JpDK1qHr5zOam`W=REqv9jL$VfKJ}D zJ_)8+F?pA@w3BL6?6ev`Nr8Y@Xk0(Zmjo{X5!3vQtn-!Npc0~8sH*lDN+8fRh_O>R zSF z=)!ro2H(82%pGxSpd)+T)HNmzH6!+0ceEu_;Zuk&{`Z!k^gWfXAl8N~%puTH=^~1s z<2~{*6>2US4LbQ4j{+h_k6_kCQqn9bNRye|ttsez4H1O6k6pzjL=bipGbEZ0tFFJr z539{_bx@yFz4l|EQ?Okn!f&|84xzHA!Zk z#83!wKf>_BeoVzt?C(I0zp^zB*as50l8J4O9c%fPA9JCJ7IEu%e0-Vu#K)0b$*S?`vrDGY zJufg`YVps(gO#he@w*Wej2>EUeC=7o3C|OYR$S2L?zon}P_|w>67#CMHESGf85aK^ z#;4J}ApXSVdX`}cT+Reu`13V44|5-96t9bOSes|1I7t%##kLTMK@B9vCwSfgH~?baX^*PjQ8NehW-k=i3s zzfA<~H|D01^Ng-_;hrz?3C(1BpSMF)q9PPW!8B|_S&`aiL(&~pbb%{S_H&q?TsgDy zr~T`3U%wt=cJEZ)txU9M7JkHIfDGObv_f$-p$0A6tuSQWYq6>=!fcCGV-fDNShW`6 z#}=z#5$0H|I*T#if>UdS*{g`}(lhvsSw^6R_0vJISbaEIkn7;HL_<~($*|f9yx?hk z*r9TVk%|fRz0%!N1i1f}7slh!7*3_&KC>2`;4Kuog%B=$NA#A4V1zfYx&k)Tb{NUl zxPceU|GCDKl_p$tQNKTw913gc?KC@C?(P{na62lcv#T*=G48ZhCJ+3`;DJCBfY&zV z3ht9-{I`khVZeC^uY*_>8+tPpY3+e0`9IeklabsFe?cybU68(e3kFzdDH+**3>yRehPm@ z)lqavS4!1c48uo^=^@}C3CKB|Ni`k-3;c7X<1aYt^>Nb4w@M*E=g|A#U?w;1 zdoV6EUWu^~@;GBnJi<8frvw=Y4|~u|Jp6pMU8v~b* zN8lt7AVectze@v_29gg7cA?~6+yn()>iSC&>Pmx0z|vQX1@FoI;_yKfj)(QP-`=;8 z)`(oRR9d4~Tlm~tAZm~%P)i!ELC6DddXuukR*m0%7c6m*O-eSbUYlioA}og1l&*5u_K$Nq{#Q_7MLyEOHz79x}CZ-7LMos>`$Ob_vhWa3|} zUOU^%2fQz{x+oF@DSUcvOv7oT-OCt&9e=N{*7hX((nW%;uSJ?HnK`d*%!s&CfU_$N&*Jc+w_cggP5rNYQZlJgx9RSSi%2O;i^(=# z#J5;D<027e5$IDt4W%Z?{`*O2k~vfoBx0vK+q&NzN5siC<<1s_i*S7?{P&EzZiK}Tb%o^s-q5$F^pn#dafl9}>(Xi2-zDx2!~RD1Ms#O9<|pyX z?l1&H3YwvJFyDv5@uoZtDnfh*LMjP2%mxS;Np;T_!9~DGqb!r4x#!fse-N)B&G{=p zRN7|ESmSraK}>9T>lq6q&oUnyOjhh8Pv|Jy{sv>Gj$Ex&_-RaI0@iPWjW*WL27~(2`*hx9NQV}3$_mERhai2ky=aUKQWCPFPOe+0el`rBz17TiVD?@ zTBbr>2$D%_5!J0;jaEZ)%091(oNuUuM1nVCS479%>z^Tf6r{qx0vS(@Ndi_DgO9W7 zoX_w?PnnKZftbylbg@zegTeeFFM{E4bnr@Sh2kr^_(|ya$mWYdlDEN|i@=-LEf0eA`kO{{HgzTycb3|%Rh^Jm z#1ZZ5FAt38SU}?`VoRCnby^|-J4rMY{_PVoN(KW3#fg~hs7cyJ17qLSl=?TE-qioqE4X{!M)sxflm z!XTol%#dAYGcQD3;GX`c#3yJE`ya{#?n07f4^jNp13{Y%zaPczK(bQIhok8MP%F@? zX3l+K9q?h1ApPzT8D?FSM-4>eA>ls}{|HuVFxDiHSq!UPx{Ys{$U*s8IXxIwmvqGW zj_`eHH=j<+@C7T^u0kAD(1w4Ke8F=3Bl&`kwX0BfZB3ysFaKh&WSJFGqj>oXI9bpL z)_Q(7PN}C1g*sy70$WgcTM*H}6the8hHRaQO3dz!umJ`P*R5Gb8paHf5&{u)MJra9 zt-OVS2}<*9wCy(Q0)p~H#GgzFgxA0+djL-AGJ@01L8P>266H7Z&~(_VuYr>r=bzx@ z!udZ0xdP_^g;BaRBUONu7J2Ec6iVVCoP?=d51g3lGDlpnZY0HV`GzHv*lD;v6&8RNWsi__laroeye!b6kDbMl95R;hr{RSFEI_bQ zz(qhSyWdT{8fX4q1=+7y+o zhPS1Fdn2k54VM-Cz?szr9@@puY<_Q_Kbgjq>C6rT@$~?&if34m;hdt9mIp|}NP(J% ze$8sg8Nf?6gIFwwJBe^gDb!GA@tfF4p)q%hsfCL_CSu&tPmCw#&lTmF@nan;dqL0` zIja{SoP)x6CSSq62~^9LNb-Y$0g~*@HV)ED$5&6&yBPDn=3SL|*H5m0*O>eVM0s_5 zzVw@3V$mZZzqsJ26#&uc*`XAiUHnI zkY5jK5Wqs(^ID=-Y zM*5(d)rdr4o`D*XKjKY)==DEPgF{7O*QM*SOSX zT|aw^oe71xz;92aLl{AJzQDhCDw^&!r4DVVa5}?IRZov14f$qJBc`XB1tjO8(jhjz zOWhMs1nl%qh1Ao-{a8a(43-iZ*>hL@c$Q$=k0mkuPwoX9LeVtov8TH<9+`7y#{3r~ z9-YwiuX#)b5j_;G!0{ly19RRHwdEL(-ICRxt>dMS04?AmPCBhei&hHi&s)DJJVgW_ z=T51WM4SQdEu7ExlE|=JW_p87H+1W-MT6t$IYmwo`I*b-=2sA2{@DGNU;6YQcEl@y zf55fe!J|aqf&0ZfA+T&jPt|&K>@BIyd4{Y=0>N4lq6fBHkuPl`NtI?~#-$=;ty@#N zmsT;zmn&#aUI9m-;jM#ckU%on%$N)Y{%>52ZlEzy@g7vbLkAE)>IAk4;tS;6pA1^s zy1PvXYfF41+ptG*Tyw$G#p6**ib-PxvwqQ$Rga?H+rueK_Zr!tFzdg;WhUVA#~57D zGXe6`pUd+rNq)M`-G0!k#*869VY>CeH-H3n_uNbTLA#Un@_I+({fJ&pVs@}SjV=8U z(PAnokG+tdJcxA{YM&;3qRy|ts%$`yuNMu?zZlq*rORvcZMpH&P^U$j??3sHi|-I% zN^n(RJMt%DfvwA3Jfx89-Gu%yIL2xswVt4trw_iIzOr&i=+7P71)J6(%A&e7a~0-= zxRVdpGMcjT=La#f6;JtrDn(F6d`P;2iD928!^1iL5pj6)BsRTJU}?OXb~E3;G`>z& z-(%#X9<`&oPUBCn#FR(z zWo*xl7i3(MFH56|Am9XbvkE+3mD2nYFm!BJ=BnUxzuZf-DI*5DnA|%+o5mmfpR_4C z_Lk3SkElNa?wk}0cI*1Rx_x^Jjik~5O(O`{dMM%^#V8y zlDIT1?@Cc!inQHI?{@?6MUBEyY$0ZCSbaNVXcYHG6l7z3Jxufif@X|xvD;*nIg9NZ z(Gldz@COlgmXSp@%Ny4+LO_Bu3#-*je>)p;@;w<`;Rk<#oY{xa5~Q^zoI;?7MI#y@ zRlp?>=BukmL`|vk8~2BHrg+JNMYT9twN=r1vRL>s3f(bw6?@8SQMlWJ(*yEbrvdP!M7|9=>J8@Q;-><|3TotZlW+>`-C z1gx3M+kj{=mYT7}jDVxDtxRg@>aI+JXtk@e?)tLs24lgfSTMc;X?y1?3z8I!R))I4 zXlSOpN^fSq07aRZ>zY|wIsfmuGpM=y`~Uy@S#s{3JI_7mJm)#jdCse=u=AoH?~oG2 z9SbrW{zj6{2$D*c&q`tumxOi~w|JgYFsS=~{8~WdFqufAp!K)waJF?Z2nR*ATj^A? z@Nkw3^`76ofmX~SWO0U1G@$mimPt1{C&LL?Wsw)*DC-$;lwlwHbpRHkMRkxC zm`A1_OolBXa5PMAj^U9#u8m&JB`?TCV_aDrHjaL%YY1bQ_qT2}`JCZ0d@k$3cpl)& zjtOCBd>GzO`kLW4f1~9SEVHG@Gq|ro2*jfL;J$*L;tAaB{OarDr^pxjGd*p=VXPR+ z-}Z1nx*f|27E;sh(<7@RurbrAIHEioFAa1Yc@;3-X3Ha7ryUL`ewg>S z>u$%jB=-K>EKuo@NdChFA!z-K#j3MhV z2pD(~-T}Dr^T0Vf=8MJ?NFnlk^SW$QnzaJ;v?0IA1`ZQClqcM-4x{R5R=_4j3-BdK2xV zQYu3m>0+-~f!ESb>Wu_ZYkW$!TdBlZ;cMAC1A#tZosr=Os=vpW!M)tDgx*z1b+-bm z#wIR&yxwj@J$(T+9&h=AtthYEJQ z)HrT<`S#Bn3x`5x;t(M4-gkeLl&aQN^50NVGfc8)19`=uWXyS8FKc9$NF3!XGZ~AL zwM=F$N~LA8(xRkgjL#*BgQZARWPJ^^2Ml3J&-P&p3Z5DRhyu?Rte$wj*x84y0+WSt zS`-;&-)4;aqtn8gEZ8cT9XMaTfxk#7r&;)$h(GKf84Irz)xWcFocRF-j7#J5YE_eT zRs|AerYtrued%aelj?LB&eDBpW9kf~L=9s8qo`{d3?JvUOq?UbnC~;we>kdodT_1b z4fq|m!&jM!8dFF|zPfra;#;^cnCSBlB`=thcNxA;@^N-KWmn}zh6+xwc~_XOuPE@d zo~@XPAID``EAh-Y20l*Q`iRL=;$QCXOkN-KM)7yJ$m_<3-_y6dnXGT%39a~qfe8|k zY2?t{5N=|XC0j$sL9#=SO3VvmGJjilD^&E83&;2QxesqX9*ame_*^$c1b>i%U_l_J zq^^9K1-Je1=!N60{;q>0LQIJDM`F~ZY)jysQEY{ev9L-wRS?<#7Fw;bc*GLYkEh12 z4>hqWRB&0x=Do=nd7N+qu`sXSjN_bScCxHZeCBbqW@*L2K^Z>{AG=zZ!ol$NA+a81 zNRd>JQSN^{W_%&%x%iq~Pz07{D%Xpn3#%$b+8egivNWj$IM@R?M6(q&xJmJ@@Jl|=80p|l zKi)>m;QXPq)$a+8Wbnq*jOkv+<9!WBpKfu`k}rZgbC_EU^5~8eWq1s989yT6a-6)#;ded7;k&8<>nj~Ff@mMpgDXLA64n2$F64) zQ<3?vTI*o=m{HbEGwu&CX@NyLCtWx`($D4GHqcE%<~>XZph!(5Tag7q?gP5yTXw^& zLUchq;G{=yCspt>BJA*efIK_X$>)d4wznqgCV>#OM+Eu<3uF8^nkKle(WDwYi{k@1 zdm#g1U}06s5&~SIQ#Dy2OQV-_My~UZhbeqw8%!e@9{FjO0QT!2A=DomyM96d@2Cee z-L+QkPNew@$NzH!+i2$MfiJNYm=dT|f|pfxsxBNqPj+OIN)r(01D`~})lG;if=dm7 zMIwzhqy&{%ABaM6145SI!3$b8~>bnWp0kKZ$+J$a9)#qHH4pN|L_JM zGiT|_DGjQ4j(3R_>m;#5YzXJaB%dGT6+8I6H)1(HnU52nTzOew`vm2b?nGWa!>~_H zH9nn1k=;d6*A!ps+-9x2D7>#I;&PGBX6762?L#%#%LZMaA!0^3QWB~3r`vqjwW2Q< zIm~)nL5Qs&)Midh8rkPCC)v%T91&r5^S$;6t-wav(M`cT-oCZNaPO8m^D^uO@uh6H zAD?&Rno{(*ug^o-2jw%u$D|uq9C16m*S{x`Hoh`>8D`;J2JJ zZ%(5k!O4wdhQsJG2xIZ@!ozA*_q?LVg;yjNq7@OQb7_-4o zY#gHDQzSgJd}ULF?LFo8X-&eV%Zb~IrL9rTqt|T3>YPPzer&)hPKxRKWUDexweWpD(?{aR=<=k9*?nHa8)t)=a6v5deLQK<=Oj|oL#$)xf{IH?3&P=0dJ%2$t#W(DEBQrC8R-va6dP^d^1X>ttcZaOQGy z5h2*65%vl$8mJJj3LYB#G1$*NWVggQFtvPKxnbMEz`5mWqn)L^r^K|GL7rWxSImnn=5*O^>Pysg%KN9ySs)N zmd(_An3!y)*(28J(_TiaIB|RUCKRuD06xc>UvGA&V*3o0QpY-r!mfER4j&5Vnx68bqjMlwnU;ILi4gQOfDV;kv zdc$}(uVeNkFm(xUY~SqT!}(#%k%WUUqY)M|!r&~!|J;x8ac{N5W3_lnyLc$9ZE|x* zS4Z!p=GG(O%?%i{z5U=r>fR>*!BKiCjBk5sBdY8B!gLs?F`cbA?)Qd;;|*^#hhdrV zq0%EfdHWCmr(p=qIzrPuks0AicCp+){Bc6EJN%ea_ijzurNwE>crEuP>etz&-_3cV ztc82G?I>G(uy=3lQTE+7sgq4Q+DnIxFBUGM$!7MQ&~?U#daCf+NKVJvi{A zhQqyv7dJ`?FJT%`W`aV7FnQu(J%W2E4qeT({jm`|U<%WwMBZcgLu0)9*k~Ol+{!YM z+06Z(72jsupOHN}9Jd}|iB}U>%CZOiWQaIO3htkD%T0!FUgX1El&~o09wKoXSw7f) z=-g8N=Z!6@S}Mkm7^o0f>z}Mq9ds2m?qRz^6>S&%t<7Rns7Q<=TM|-XD8sq-Jr?Dc zCS0&h_(>2B;IuDEd&R9~INkb0G`wPqKj^h9zt~Y>SN6l{KSp-?zlS3i0Om+eFn$=6t6Q{xbOU>_>DdJwe%6`NmxI&2@lbur@B64z{q&k zo-BHm{ZL~#rsBNc2Efqm?rR!E4FJb!J=Hs96KobQ=Sw1_7M6RlY&_+ycP(V>qTp3d zw@-Lz`X{6DW1IR)bna-F_&h6jLRs^Pnr_jLX}}R_s#}Z!6QrjEgX#zvstTYgjhvrm zSLWI$t4kB+k1riPZo>S@56qOEOj*JaRM)>eb3<3`VbVjb(kC)j3 zFN@EI=jFfOHB;$OBD4YyG1XGmkunR9*e5)WP(%PV;UPZ6@tzX=?^b4=x>id*E;;{c zn9L)$uI~cJI1Os|dnoxZZSMk?)^k5vqoOxdomqbEZ6=N&ig0Y;wUgm84ERTC&Gt#t zWMY!qPtB*$b$8;Ric&&W2q4SDZ$jx_x8^R0D>+GS8w&xOC@u|~m+Uhg4&FkKI^-ZQ z_V*}cF|V!^i5%c1itOURJ>aVkaTyP`1tD%Up7>Vl2Zy7v$id^0NJm z9gKF)3%`=Qa%5iPFahAUr$fOS0WVpxi?|ID!{l$w6Y!GsG*d!d-pO5; zo)jFq6}gFpT2HrEK5ncks57TuKx_*NJSEw{{NQp_a4oS#Cc~^gQ)!D#0n6BCvbM-1 zQ)HqIB%P@SD`8>Qnq39UmyOdDB1)2~qPD1@h38RfE7krA_XkloB?Pb)$c88vC%t*T zB{_8I?Vz2fXaiYpj1(jf!4oi;9O-L35$Eh?`4CC)xUHX6t(FdF?^EXU{Y!h%Nae-v z149keg*g3oAg9Z!a!5y(FOKuZ^H61z{?sc_u2V2+W8wzvc5-jU{EB(8_ce~uMW;nO zVNXI42)1hq!y#umziVFXZyLvF@?W198{PE?&R{6T6e5VlDX|%x6+3}&N6v(AbWTqJ|RTGyImG0Egoc36yVUF5~O~Male!w=>R}vmX^rMNx?Ew4j)V z1m~q{%421g3E5tsBA#zi_Z1CknAyANll77z%BY!jUqEx&5;{`TXBaXO27~!b<9(wj zafL!<#lg`e343+=9YNm-TtJAgC>Ah;?mxtQYOw1k-d`I;jee+hVt3uS)>bE7WY|-S0 z;gZ(A8g!+*oj?@?%zKZ7iloeTbNyzX-bs0@BT&S-&z&Ig!^vaT z;;C*9_lf0hu}pktrO%vg=g#ezUaD$ARmxC%@+gvED#U2nlT)Px&pyRbHHBz>nuj=j z?2IbJVxg;UUxL`8Zr_P#0j*cs3pUu=zOx~#cMI5H`t^uH6=FpJI7JZ@4e^TEgiPSx zI&f3_PJDq|Ru$m3B)%eJfsZ(l&-yi@&Eqd15}L#->sAt2T{!I~91Zs*Rj4Jr+| zQ{{EJ3sIIKj1^r71FO;sv@D61StGjO#=dPl9O*XI&&Fs0NSe2;QWPtD7hS3iilyAAG-W7BlZkZh)q4zIP!72i*BWmLPu5#EgJ8OqF=>*P?{fpS*r z%&wls_vUpY$fT6tW~d=M}RsCniolXGiJ{ zvD=^;{ePUW80H8XqQjPeeXiim{opd_9#f`^R&`MQNLkmSg!cpSaUkVi*yNcpR~Kla zCx_)FVQR>&CHKe>m^>r1l=aMSr6WPhK90}F<9sw03;$I6F8kz={&PKE)tI%Rl4`8i z%DGkJ7CCECgSb{BS@?t7 zbkQALQJkDAN=u63+6G6rt4smc-PrpkR18LhXtUST-oC4O8mM!F&cQ*wcvJ^0VOk;}A;|ptpH8(K|a&L^3$E2-|_VJ`v@8l0NKN zbl8m)V#JY?YKh3`Wi6UbF+(aJ;G&m?konq)R5(+m>Gz0*2GMW~kh=(g;+VWe>9sO0 zX2cVd9b6Dpa%9Pl$+vEJ#qk7<8teS=*iamPEthSUZ)~E%X8BLBD%~nP9SE6>!fcY6 z9VS<6sA1$fAV?A*kbB(pIhC)tjkZ`jnJN24xra4sdv9{zu@;nA3s1l?5r=m2a#^`YF%TQGBkksO*2@IH67Y`&{E;ThWs~I_ zlc+G=f?u9%57huOEBA|m+G2~{R`Si>uCkv!+j!#lPSnPWneQa1knP~i$&TlxPJP3^ zp4xK5iA_$=VIvCV)z++jwoX^;sWa5JA*|EWT%R+^EX63iF-l*Ix;sX5Ifm(rVcjt* zOAN;}!{h_|j1J1IAfN=czGsiV`iMUJ^gvY4m`-NV6gL9as70;eqz@%6!PaoJTS446 zJHgz$J1MT~Ix_Vz+q|(6*`6aAC|1x>P{=`xN&#FdV+&&dYM>HFy!xm*ZqKUDByW%V zeWiU;7)tEgC%NsO_62jjp62#lM?u`A)*eZ^dmndH4Vhm2YEO;0$@@OqyLsQeyG2nN zQv6EK471I1c;?g@1vb$+b86oZg?k8dIcmc0nnRuwZB6COMV&2qaP>u5ml{}U;CJ)d zO#zmNUV;6A_}$eh+o7}+z~PJr-}f>_k?zz^D@QnQ@zGjYN^SONiC~EME3-M$m95Z~ z!=u}6H|2|2kvCD1zL>u2XDs4V6Jz=Gxf8Lwj926>1wl$Xu?Q?2vrh@V++xYLA{cEl z29%^haj!Q^e136#kG)%AF5WbKL5P>Dn*J_ohI)SSDvtN@e~GWcDsywy5LWKV(d}OT zss1fJpx4^acJGtTv~B77H}}-4oCe*1q(c3xyeiaD?`9=7%Wb{)!s=3$kIl9xZ}3X^ z6)BpqvCDLj^(T3wwxq8?kQyU!o2o2s>jk&9u>j<~E->OyEgp|+$A7_3Fp z?gbZ6Zr(Z}Z~eftyBnR4(Y-0PQzfZ$0e}(Mg8T732s9K z_#cNi2=^9sVJDv-_gX`F56{8C%x;=jA1z4{`!txJBY>)*q6f|jgAPX=d(Jw0&U*gW zl!?$YrL#Ki$)_W-^a5RR7OaxnX#W@)<_ZWgSQ?FEw9+`Qcz z%lO1s4!`r}ac?~1i&x;SSgP;z`b6*Hce>*l*9j?B@$r9vaJTrn>p0G#C+p7l0pZKT znC@YOv-@tw)!TQs0zU?Zz`1p|o{&GHyL9>%@?}Q|b62MfL)>mYzkgBB^pjx#d2^`~ z(;WktC8VhYrn}W!21ayrqhCZAOek**B@ebkb?%K#gFq)yD)V;geIlQqMQXt;LM1VCLN_)VKGi|`aAvVu2zge(+aW{G_ z3{^P9SC%jK4rLre6__TbQs)r8%NKuq+&5H#2Wmfdh_5eSys8%yGL-4YGer>&(OG+Z zxr116sG_=AU)y_mDAW2TnGS0IgV_MfUAl+~i2xH~P9S(e+1kz)b=;eLe#49&UQ=M- zxCD^_&}?LSPjA$M#?2CdDq|ch{B$LvKF9gZKse!l$~@h?DmeF zbq+B7REy;yd7qObb1@5$rIz#uD-B(BEbk^b722H^x5&|8@Kk~PFate*a@kM zUMwlPv|M`_4km8T$@=vu&JwrBo|D}Yg8BVbPf=U-mQWXl$8K2H3$WwgU8}C`oy|2q zI8-it-gTV0I$j+eOX(!ZGt;T~Li}Z%B)9}7rJc=tn?XDQo6DK`>QI5ATEG`Aag`8TvEOJU}s!Zq03N}?l5S*#4mQ=bZg zuyt1%$y02M1Cc&5RlMR;T^?p(*kX%bacZ1eP>!HQ8>nkU;gP7N0+ho& z`qbma**$J4qJF(Y3au*;-d8MN>=v7snd{xYVT?3P;TB)1cVmrv>7%#a-8YPJ4^z-y zz6!MxUav=MZl*gzVLT2|*U_wpoa;HHznrM=OT5R}4c@DkcXy+@sZ$ULa&m|VwV2yy zbJh>sVy4KqLBQHiW~$%RrzO%dN$p(KTRf%*Oo45?Qx8ey6jZ+--3O|wR_GlnCmn~;#f$RID$EiXj_!M4-pG?6hqQ7c9?Rw zQt;Vrtf>1LE4J^tgA?Tg17gmSiI>Tin7<)lOQa(izlVQHmY|4}g)WLdv~xP3^V?Wv z;h#jSCRiKrpD$n)CJm^i$c&B*bRM`DS*u|bzm&j0J|rIwOOJvERFNdFu{baGGf0%k z9=s0C#tfr2EZJfyr1}aJtwX0HsPZt~<~h}Z z@ClXV%|i$PmRZTryW|@PnFdbiR{=~~5J--=7hH#;P?`m2{G3tHSLxI)ze$OMnE5U& zW2-98iylwb_0U3O9lV$Dt`Rz9nS{tboKdVH1vM`W*f0VoE{IMqb|rH5&JHCBYS1;B zA_Jz}hJ3;UE* z@CrNGWJhNPhL<~6eXm}okRlXlvFVLKkfORfLW9~%&Ipwwf;4yIzp;J-%lf7g59{c{ z(|X#_A*s>YSZrQhxlfD50PC-_D7^pr+4<%HxlYKE@X~-5w);}Vj2z2>q)B?guNAm7zyh%^n#&b{f{N( zqhGL19%avY6n;T4h&`u@rjhDj5&em2@GJRLy%%%PqKw-ET#zekWQn+71PzZ@;NE~Q zL+0zE=C?4vJ)3l3?fSfds+Ts;$(d8htct7$lQwmb@)PDeE;Ka79xktQ!u8nXhdQSt>1_` z)wCIcCc)$OQ!>_wcIt+?b4Z?<39v*_39&>)DkB(Cn1$GZy2L;>bC3dZ9sqT4#j{4P zBsM&N<{BIf=n1p~6{z74FkgckI4$9X4>N$Q*unSQD zXVSOM0AHBhVN)DnZLD^bh#9#a@WVWUR37{czz2-?Xk{k%-w4jv^yHiNhhMxEus;;u zs@sRU;jF zM6sdpzeK);8eG|v#8QHD(aPuPjF*>9q6d?Yf*Dj04A~X~o|RuP(US+~-OprQ!3hx! zf-E1h-CVX))nCxR4iOh0#l&N+ga|@K{L3gxJ+MD_5?qM6XPhaF=Z%-4(RGU<$mRe( z>DU<%Znrkno6{??SR7}4h*1pXBRZsYQcjQ8s+Ck{fvp4`Sk=@1I!s#pQ!UztH_xsO zZ9*v?vTlVj7S%Z~mtCu)Xd;)q!P)VuMaqcDK5Jk$W9VQ+-rRClseD z>qrbtzc8QhTLR`2iB)B#OSv+!a?c_vkB@cc!XE4jX_Zz=xjjPe7oe|a_RDqVKoSJ( zg6dwGf?7#^wtW{UX;b&KXl+&vxF@OMtQEc|@;hPD(I4w?flonuaV=_gSwr$iz-CMn z2q3WzoB(qEx{qq_h8+uQrXv2u_zR~=<_N)(q%_}ozmlQ<{^m33S*r|rlVD&WT%a)9 zbF!U;i!-;^i7I`$XC>egV<%inLqz9Fr;H0+-kvnz0@=(lP8kvBWUZ4BLDmBh;h(Zi z);t~BPzyW={vaklgFovlzz@7gyh$LkDhr4#8n>=-3qJtfg$nRWccNHzI(P^54AuR4 z!x<^JzexjMo|Kln%1~#1Q}=Nuq}kV@E<>$(x9&tHYNttv#1U0ePBvmIv2JpEEi7xv zJu9#voqjDLQiwtq6O3y7bU>KmEik{Sj6Qi$(jK6}`#?;zU0?AfZPo*OfLX4!pZX8v z*dQRVP?@>>CDeU$E47uw63Ump#6NPZPDf!^FOtdpkaoon)q65J_JmizNG5Z4DO0|7 z?HzWxYbP5|+%rOuq~A3+>|^;I{m-5)_|{GNZu?LjCe)cU9*feVlx^Kn_ZWWr5}$i4 zhk}X5u}oAplZ#-Y?A(lu9113yBnJ~=Y5QO=g-luGSPQY@(iHu)4@TggT*{@Jq-ar2 z#>RzF<6V`pQRqD#-5kf2Q1BTHZ*v*$NtrFMdB}WWE=4O3L|bC! zX&}jpnL^%|S`y2e8>B*oXScg4bU=ihGuR)!N<}=KgRVrMP&!$*BxWqht2Hz{!jrR3 zVQ4yh?m`&gB8Z=T+>_0G)hb>8!m~vUZkMiXB47Q(=o-cITr2Q=Ta1ER{yCKTZ_g1q0-CQ@Dm6S1iri%DkY?V+m4{o5Ela? z2k(&yBD(p8NnoS{a}h-{Zh}`Fjg29C!B2&(>A+KRUS5kb;HHg^{jrdh4lI^$dPNt8 zjy``q01M2&`J{;QkvuCVtb^()Fkv5Z&631|T~$VQ zsd`E=g7zlZ#CW(1sOQr?C#mPtIA+n^?m`V#mXtJNwgz)ok~Z6@X|mzd$k5Fv&C9nV zl>|vBQmkt79v}KlG?#UBtS^4#ES-56bIMvz%U4!a+qNF-)XuY1%Gs)JLd!C>^)p#x zty&G1j!;?W;v1t{F4kgWr$(!}LT)$0h%-EwTIF&i2>V4Ud8C3$Xw6iNLm)ZD37NVT zCS~2;{ibf#q&&BGf+?9nYLP7>7THAzE}U|tgG%#J==skxj&N#%%raV#yAtFGS@$V- zRC#`}#ic#U%Bx0045I~_2&UVo;-8WZEBb$NHuGdn3-XBv65p9Q&~j$uEELp9F76G) z?vPHxd9L~6M_iq{!aNJE43{e4U&#NyGB(r(9m)83?0oo+P~OeS^{@DRPO09GILgoM zW`&)Fkco)LhvXj~P^Ij&&;UVsD#18VNKC=1ni$*j`K`l&}*Y1?Q% ztpB1PPSxfHO5Q;ync}>&cJ&vA`kEbic6C3>HcgkyHho|-E1+B=)rcY<1FB_bg#wdL zhm32oPFevQk-4F&kh2E+U(LmXo%aOcggG9s1DyR|pza~-`XD_~Iy?0L zAmS95pa^7`Aps^IQT(Z2$o-y3+=5}*Ef~IB^S>uDA2UHPjN-$JKk*v{Y>>s0;a4@F0Y!KQ-#_=i-hbxo@y|&| zqxX-J-~UnY{V&{l|BSr>ecYDFnBQ3gCb-E;ODkh%QTP{Iks!Z*BwqiXA6cn9Oz3;< zmQQK+$R(L}7O^pbsq9ZZYhyn*7y(;Vt{{AwhdA;98;s9w#5|M}uQp!qvFm{UOyCC%zvH`x_dKUHIg1C;9=lf7_zGvRT z_3j|83tk{ftE~fz2AFE|u>l)6oM{QFbTH@vzme=3H&1P{%o+GrKz~SegU@fXd`fJ* zjo3ITR;Gjexp>%F!xt#(PHg%X;Tyu3e_T_DSK{Cc%~9sjKb;NKP$nKtm*;0+5axti zF#l)Iz?wG~-NqkTCn{spvd&f3Ka9=$mJQtePBoUiRpn!$@l|wl2OM^1 z8-7D)5H4961>=6W=8iQ!u!o?6=MNHAdYp{G!kNWT)po24b_QZku z;^4Kz`}r7Hba%_e#Q_J*06C}Zs&j5uQ`O~u=LU{LucwCd+AhS^i9d;T;qG_*)fMZU zIj8L`nqk^=&XiKcmO%Vr*14h$)s^)_tT2}ab#R|6P5*?dHtF~P>dmTNDgu&Lk68a zet_rzn-Yj1Z5z?BHAn~e(vPyp@aEqwmIg?3FJv`nQ~v#G(56;fuyPL;7J|nS7rs2# z3g$<)IR%TP&zP-6j7nabJST&||1aI-G@1Ve)uX2@hR3VPFu>0FyPiyXYj7d~8-eYd z><@d-)l9)0xdQoXZZnU z7}VU~Y_FNQ$EaSu%nA#R1qK+XMJgMPV2oj$%pm-eh(-;_7R17u^Vg8c251C$_u!cU z+DO|5$?L5qNQjSMBLIEOuM-_ysv!wOM1UZEA`YVXPlg~GvIsU-_pY!tid+yf!7F7`Zs2_D(zRGJT7+;c>T5#zFq@o}X z8C4!$1Eb6i-J6!FTH{&ub<}q2+nCt=t~q4Uk1nhU6?DUw0HI5-DV7_>EC&Vru^IW2N@$Z5(e;4%!zJh#F z2lNQ@&i0~>FJKA+;xDi|NmC>pcXnu18i)M+MZ;HP9Ry=mpk83F!Ww>`ouNQ$y6F2A z1%F%ZIqxr2x5b~aC8;~lQ6hp&B9ICYx2PNben#3xvEzE5zMi``f^EaQVn(3mJiq>0%DE6F@U1->xi4Y|F|FXIiWgV&L z1g#(N!FQ)Y2b9_(*`Fb=pV_x~&%C&u5J#L&iD>?86=?;9TtLA?xA?SQTpb@0orY3j zIxaB~4>h`RC(9X_yh!-njHo_B-a0Aw%I!AF2`|uIbP<`4JQ^6XLhcpXbR(%0gEC{k zYzV~lJ@WNYGVPJJgbV^$#9?6z<5y4`2bBLr3lvrsxu;LXHTS#E7)HwD&H}sQH{4~^ zm4>nOdO!vM3A4F9FoC3Bw5`Hp_CzKi+S8}ct2Yyq-i6)vmwqS9+0j}s4}NJ5!6JY5 zLZgUis5&EuA>6JW=*XT6T+Re&TabJwkBO&m?O%5hZIi4)+BOkfolLCotFVF=QisB*wl_1W`PUs&Pau_S(n`OZs)>ciBsUeC$)UEn80 zT@74UZApJUWg8z zV-&8MI*;pwTYhL&4g6M4Lns_qa9P1s7&P}DA@`Nr5K;!u751Q@lWLy^y9>BG02{?7 z2X{!XSVR})g6fC8KErFzlVOm7LksGrAW+?2(!tD!R^6e`SWX{r3hbBCwlGI!wB&?1;C{x11^P|E!h-dD1$qZ>AI zFerO(LXt@igUm#)G*_6akSnIIkPfJY998RUWw6%FKVw+^e4rdnz|~Fae(>zHC}P#q zY_|T2dCQwYeoR5SgS@3dCaeuD`1A8et_R8sG*g{QlHZXO7zS5$8&AfQ=ulPgdpf!y z08-_xIpKM8VB*Y=QrttYdHmk95TwI{qD6&~O>}qo5Q2>mKFOLR zvG+^XT!|ecS@R@ztYn=ivEwAGRbn5ItdpdO;Zk9e6mhpym@KgmN!CZ5TccJ_Thmad zNP6tdCksL_Yr7^illuwK5iwO(%hMul=T`u=0ap14t>0~a@{a~*rxT$ zwINlPdF5b;^Cuk2DIDG}qgzMHCA@Waj4Fiq?Q=v&Z;~yDnUb}X4?9U!Hswf>{9J<`10Rwe} zIZb6PNEjHL@-Ts(Fwd;@%C0LES(P9IX#7{Y6pUe+{LIgK!US=Ce)nxW6<{dCkCiyG z2*EAwX}K;fb!BOv7d@GS1exVaiB$_?NlLv%7yul)Msc^_{M)sg>y5WFSs>buY9>-> z9^gl&XGQ!P_z0*#7gbUarw<$VycDd1R~Wl8TT*6um5(0f zk`DR}nQNn$ry^g)UZk^g7pl6DC}RkRO&W^@VjJOIcI~<8(J>a3*i_ZLyU5l?xJlOVYj{8b?rM_H1T|$0q_>91_124 z1t8)N2LJ@vzFPp|)dXO(&SFG@bTA$lK3MYRAGrx&3-xgTd?;B#@H*a8*ge<#G#eK@ zLGi8>D`830{Y1u(rRt@z-63#nKu&YFv={u z==AMhv0&$slzsey{SMFdBKz-M@B|{uQ3IlR>uEZb@!xx;5UEqYy1r~{ zM|(5!)5BcSB&I}rUh-T=d<$hhHGFd#sjFqErmA+Q-t9F+v}liVf1xmX0H7Jj1tpKv z&FeU9R=8C8B8NF5V`W~UdQA&atqHN+#5|V7N%#`NO(q1Aek_SAe#7kVcXlF4)&ggkTEzbJDE?6kh4ZR&U)gP0Fz`7Yy-SDFP!OV)*O>p%_4k^^N4H zkyUe(6LTuSYmDWIsg@^xZF$0Oo>V1yTvk={R!ibgnYSd*R0?mvLBTT@Nc%)B&`tX2 zwB%XXymgJ2uc9-*%*luFMB{ius}^rX?|^TY;_m>I|q+9Kx%J@N*W z7sOFp(Xs$1q^i}=21H`qn=M)_97X@J(?zdUtPKtBxvK(!HZC1?VGHIXuE3^nPggOM zFUQuTGWjNwIYmKts$1O;JCI>W)kk&9-0E{ab>H-NVk(NEJ7eQ?ry^N!6@p100{6Mq zeR1f*xY(WB=h9WasWP$^c~I~AKf6+uhID%df*uD#tDH^v0v}&hOipkPD#d9&;QN+$ zMLB9ZkcF3O81E_rf{}kLg1F;zeJtX^dmJbO0fPI3v7k z0)tc|8AK$+4ZtV>MggrR1Q|xtGJtpT%Jh?P*`DK_{Is&9m6CMI_P)X^ofUGcDFM}4 zq)6(%;?f}^ziN4M+VJG@nv9x;Cl*B zF(R*sJ_)ZN7tN~a4uR$WxfYg?qb_^oZKaw5bpESAzfH6%`DX=rXo;I0__}k_$>YzE zj*stgR);B}MVkb}tCg$wdtt2AHXQf!2X=u2NcX2QiS_7rvH76j_Fe>bOcu^ruot<_t**Uyf2To4n>s zlX>*GPS|lw@PS$t86p)8ldP=Cs(hgH5tn{k2O4*7s@*4_A>M!X+Qa`w%cbl1Gl8Ed zr{MQw18w3EB~sveeJ!$DRXwRXlnbjy=jE_8Sp29)gd7nb(V{{5u(r$3HHG=oCU}d& zL0_JMt*bkh+0R%2riRt>%Unr!lG5AdsEhj8j(_i?K%O51jB*~J`@Tb zCehyc`NzjU@mKtcW#~a)%KGr&gURyzag!0A^V{1V|K#K2$NXIrU`5n2`O$&3>d-3Y z4Q2BlMyo^CqUukHV)L@tz=A)A-P+F=bwI(IaiC$LDyPD@;>wzF_?BG!dP78VNLm6cGml8|DO zjZJe9?h1WKxHS|&PX36kh`0qn#b5v+>z#oWOd76b){ERJg+t58&E>NN{HPn{C0HEK zooqia$iw^CU}meOFW$7oG$^=&W`$K8B^Q%7QG#tB2`df5egG`EY~I!%^8<*C+~mI# zO>WW<0OehT=W&3BU!hGjL2)}g55nnqCp^81TkxDwpaIwp6MlGGPOsW0ZSIzkYdZp& z?)wyn51f3T^gyV)az@Q8|AUk%Ng+&^x~@ZDeS} zlG9do3k*bZM)jRg=C7%EUU3IzU2ojNtZUbQW0wExigJZptH|o3yyYDV2_!~9Kxm&3 zdJdsEaeMele3mmOyR~(({+)H+$$bYOT*w#lmHMS5@nAlI#B*4K5)TO!5&h09ffa!w z?LbSNgj!uf@AzZ>PA$ z=l3Zfr4eaIz;^@qyuT3cyxejzCmU1aWzRV+efaH*II{IWlRJsDcp!%4LQd@$Xh@fal}e*NS{oa09m|~`cfW5;lw+6I6sUVpq;^h~|uCpY_xqK)*! zh($oqsxK<~#A2CGtx?Usz(j@@UHAHdixJ20`EFCuhQ(zg=+rOyj zxIr&>;^kcE?Jv(Zasw|%z9ekc^4o`D3<05JUYQ{Xp1XcNn==1+xtDJc6!8u~fx3;i zk>R#s>HQy8h&Kq_KBCw8+aCnI2HsB(zCn@CT{~q;MF7~YGq*oHFe=u93}EoUi*sZD z#T(cuqOT7za{LG^@}tUbQ6c@E_G>I8L0bb8lx#x@(5F@%U}EU&aeLgUamZ>w%@e9P zqvMAsuH0O zL?yZ#Y)MG(=U&0uAmR&zPxJpze0l@;Xfd;Y#~x?mM+A-0v_fe@;$&rm*9b7PTIw8Z zt;4bjNWreU`3*-h_%UR_Fe_h$;)Yo~q(N-7Nh`@~xBkzl#qSrv zuj%o9Md9&l!PxS&y42pNA+pUZdSoa(dX#7GuppT!!ij>vb#5Ds2#>U|PK(N^%5hrM zuEbRqrz+QJ;aqc9nOsrUsjGxZHY?82@@@vDH|(Y#vCk0hc$9_R*f9KAD_WkA8tZ^L z7lK1Y3!rn;M^K}VSN#N-$*%Pk{7++Hm%=$M5XV#yu?r>dQxy*w#wTSuSHc8diVE#i z{RrVd4)!6OU+qW*fj5(kTZnvbO~tdGWgo`VeFgxfDg$9Us9Q zIvke=NZbBg8Yw&SuX^iMY90ozPY&-V@N}VV@l887_atl*gKMvk!yI6*@ zNDE5IDGXGoh6Em~4L&vtRe7lsAXU<0@aTg1@^h$gg-0v&OesLOC;tPlL#?pk;4$vX zktIkBbZA`BOSq*#A4jp|dzAGSWfhlJZX_T{wkzqwcy4uv#*ph6^AW zN#KJ7^2KOe*jeOp@ib3(Hc+Li5Z@!j%$Aghxe)|$bA+L8rRP~{jvM_EYJRWu)6$ju zE?8uy^sL`$H5iqX#|uJw6G=9nO{JRiX2#I=;qXh(esld{`h3Gb{L-}}e*YJ!M{&+| z?P2XI)Qv-Z#1n0v>wdldiYSGb2^rhN%|*AlnTv=E9vgIF>mB&0bB`!4_+{&8i!)#bW4;oW5+K zBadOm3mYYR`@nbj0#|8?8Ny}!pT_$hFau6~*%h2$P$_=8l^Lm=o})0l+?IhX{?zcA z@BG!H!^>6zd_DajTeidFdG|IZ-icF@-Wa|~tJOTAuEu#*f2C&O#-CkY@#Avnz_(?t zgb#N!L!Z!QX8tWhexAk*9~hHQ6KlgUCIEp=ofnQw61Rqnsq6Sjn_TRsl`4J`UQ&6E z#$(neY@ETkJs^yJ(>ZMl?&KtFoXS`vCR@;(zw%FXsfRwnYWmf<1YG8AEx40%+Z}o{ zbN9pe`$nb#-s_BDN*)W#{K22$3eQ}(5z2M)XszkhyK#vqg3POQ-?Wv==*6jN7XMtGCw8-LAyzt|MMss65- zXIfCUgP&2Bx)RXvHhG?$3gZ^#xN^*~q>Gq-LJND!5r;)QWONp}j5F?l*B zKB+{o7>-r0_`pc9UxIKy@vbV&GV%U+^RVZ$o1Lu|oj#{SpD5}DQJ>~p@maPI4j|+K zgh&kVx?RD;0W(rvqGFNNRrL7AIXTjb&$B0)=j4RjBbj;kv0e8t@xtqKm*e%+5Thi9 zKjL%Zw|%ddmQ)}K$e4|*6@6d>KxJsDybTt^cWd>{PQ0kqq|=Y?z}Y(k|4;L!s<4RE z4{$5Kc|b$6kc{@okhzu+CY>#b3b#ZuBXS^h@kWz)XyVR3JOdszZ>$7OQ2q*L6uBlG z_3;y%#Y^LLPS1$32>SJ;yHLcOlZ=!}V^xhGA7}|9_k%HS*wDN+J1tzZKouu|3^ZmD z19`6FwX18~A?Ta!&SBg+TwG2`>DL66{LW?n^PSc7PVotPr#Scj<(*6a`<=k!4;%Cg z7svOFz3;(-qDttWLN_M~1hP^6G?kII3HLw+Rx=Blvzx=k$2y8iH)KykSChwI56u|g zkv$Hz{-(9sIshCnHEcJRY^wk$PpAH1AVotQB?alF9C2(Sks^1YU-M)7R5 z5sy%836f`QVs!bx%5COom|d_lIgP*ac19nip6I6*ki`Xc2%bN6q`gJ?BpEcAJ}(z*p##x_=Ei8P58sVe*6JOEM|anVQTree#5u^jA~W2 zaV1|`Hafgyf=aJ{A1sw%$;213R7ABj7le&rP3w+Bf;dNyr(BVSul&jH-Hrd2f9^N! z@5vwx44>g%X!&P;-YMV00>ZnTN(JaK_MB?Ps%jzp@lw@_6X5q1wV;qwiAEj?8w(ld zs|V#vmFAr4scU#_=sC6X)w8%~QmP;SRPB7_EqtDb4=vB&12Z~dBN(xT033d)(D}o| z`S|nu{mLo2@9-}}^0WN99|E~a>r8uSbCXxg^22=Ze$Q(=R;@$}^y%j~@4MGqSFN00 z$hkug@y51)`#UfBt7e3yf}w|BYONJ(L!yVNx6s9tf{tDyv89apM70xS*}1wF}h8-0&uv zpQzQ>9v1MIhQBfN2U!2*FB3#mz;lLl?nTai+jo8`q^+!0kI^e_m_Vf_(54+wR0F`<`YhI zd5>bo?$)4&sVf{;0MK&x4-dy2z4ovLf7$q)gTE`oe|Y#Z{;)pvj_Qs|-RdRfSN&#> z|I!lO>dI`3=#0VYF2feo#Mo4O?TN9Qw9z$<<(`ZF+K{%d{k1cEjSs9c;AG=6)O>}W zD7yMhltZmIj1lG!oRw*JB9%_9XqyubtQ(wV4Jje*K92JoTf2O(HI`%D#ORR zFDXv%oZ^HIV|^lzwZuJ?sjj|KU+X-&cYGaow4S<-56{8oJ#zJ0T*cLOsUSQY(!$C{ zowMbUvbANni>Ss$e_X$?E_~7ZHPx*uNfYUwo8X-Kh&N}iL-a3+O<(k{nq$of=P0X2 zVmC5WG*q;1k0(&NZpBYxOGXET!5*6FH#J$IWecxJb7LJ-L+7=}+f^}}OC(PJFQ3rchArcPXa`)e>?|wR=Tzz5DRqvbqG5G1d~3|KWVbEsZ3{0dT7k8^7 zrP2g<;Uj`|uSN7v96qY8yynwA*P3iFo6`U*qG?uj#LV>Ul#0^uG!xKqJDV$ybbtwX~`kKg09#z>`tyD9abd;5ZyQA`LiNd@++KdHsIcLtC%>G^Tc8>O{ z{`%vH%q3-@n@h=$M0g8&cOYF*%iv@le;FN5jj#)5l2(c07Jsc(a0;wld@_9M&rGS( zCp&pALy%0;BE9f|;ETB==$yV|W##6wRUMeanx1uC(38iz;-o%fG2w+ntp$qqNaYaG?YQPXY>X2hDA%F zzcDV+^J8^9e+=%{xNK%GWqh3o^}XtEJ(6+kNOD86(Q#TF5ksfEHkZ8B)M-^_Q=+%5$jTMXgyHRl< zZ#=_5t&@@;s$c9I%5-#GiM}vsdi$UOhy>3^)#-OYwBpCx0eUmkv&-MM%ip|BieZv|-ri>bc+(($IDkjUr3`%vpg&i{hj}O8 z1m0tPZZ`^*r|y0dc{4ypN;aY;CMtB781Zp)tY=19o99MTsIT#(6Ei&<{HS3Fd|&=K zzOmzKnr!o2dM}fzs8BEPGzvnOh`W$x@$x`qeMsZJNeB9eLRn=ifP~2P!8RE-(+kzz?J1Q&8 z?5gfKq658Aj~tJlP!SAAWbyd2XT=ZV%NfTY9(T~pZdZA^{d_F1YMs0itb%bYdHZSB zVn^2eiLl_S0(p8~obNG8jy%dOe8e0Y#WJ6^>gHGU0qfm>$F z>`B!a-OatdIW;>+EPup*DMz<@J+{v8=CfUeeoOSD(NXu;T>0so`8=Yk-HEA=L}T=J zQ}n^1O+!mUS#CDd_8+&nuA}pkyR|NS(_U>xeFr{NSI?269&Oytc1?w&lJE#=tzRjr zyxyVe>iTM&_^azgkI{drPS?C0oZ=X&0$m~ayB=U#Ti3TQS&~Lh$wdZ#TathIvcS>^ zlKpXn%j}x|UD%>~{B6fy41W1pYqK6B0A=v^qM?52)ym~{j$v?>ToIQLtsOG}$lHsO ztHbudUg*{gIjZsIyiL2-u#BwGMTY8*Jvzt}uq+<#PLXv@Y+R5j^&aU}e|3GvF`y;q zS=MPJ)dA?K8gbc5ICCX_h$H8KJT)U~2Fp{E-?JpJq-bWA+&ME#Xl9m$EE1mCr*@|> zSOD%+BpoWGh7_>cQVl=Mk&+1yd5?x!wE9_hq7kL(hN+g$!!-(4&ow%xPLmQ-Yhz17 zSng@2t;SvbhmOu_ck7byC7}PZ4t!X+aE?3b(M^qP*IZC*zYl~L{R@v&J7U#f%7ta? zc}>R=@%W(|mp1E8zT=B$x?@#Xo*(UH^B!PUpZ+MF%^S<~cHTHoRh)Vc+&FgZO3!JT zGP4*TsL%7ssH!xIIsT6uy$fGFNlzU+_8HD&D$@8UF_*u>cD}L%Y znsEsO{FCVRPKZw?{#_j(udLbm!m(pCPIu0MH{wUuw7!5L_+RxPb_Say)&+il+C%^S zm*?`U{*HfT^kA5yfnmDAmcw}d*gGrH2d92X$I)ucC5V%p!shMvFWU3h(;-coed@ln z3`|g65lzk@ly8I~kGnNJ37DSLThoKZabzf_$1yimo+*+in}?cB&v+Kzz~Wo_6BggL z`?2^e+}nuM$ct1sXcZoiy0Wt;Rxf(#uULzALnc*dNdntdfP$PFTNKje?*j~FqZ7>IZlJX117`lQ z?A-8-X{f4qr6QMcvt9>#pxkt0;W8ri!X+YU!egaK=DYI|o-hB}mhlq=c*C<0;ORFY zz&%Mfe6LnEH=@W`tr+{z_&i*9n%Xm5{>hLVZIL&c z8}SelA0^?T_9fUa_+hw)Sa3u_91!-7$B=D$KwiH!!V7@K8#2UUIUv!d`~ML3C2&og z>Hovz1fxwj0-~+S1Q67AAy`FQZ4x6Y+Fgi%O1HZtYDDV+sTM@ENvIGgc0=p|w%tuq zt%zD79!P5`yP{&)TOl9_kjdFMT!`+44Bo$vvr=U+RJRD5<>iAc@~or7T|EV}}qo3d)cP=>) zBcH0n!8d^|AbC8n1tbFqUgigg3XiE2Q{WpS^hOf2Ty~DNm=nr`lmSR5B4hCikFOJ+ z3cK!4&uZG)31NW69G{r}rXf4a5Xnz`Hr$Y%X~wxq->?#uPo5>e9JZO3HYs8m_UI59 z7WyA|Q2k7Ro`Enw^QwOZ=%ds?sFq8w$l@9WP=Pk4fFH28|j%EUD^^qk5TS!fA#; zr0G23QO|hD-wB?QJDLfJ>3S&yd!)%TDTDBUS{yL|r}r#2q#j^!#!J{!&+?Va-tcG1 zu&*FILAfICh!2ptIOt=zr=%@$cw&CCH1TOt$0%AY{8SQpWE`Li8bmZNsh>XHYKTiv zM+&mn{hV6Eg02nM^EAq@?mgEE-ZTflEbKq1R+fDe*JALkSCLQEvFu%((He#ObD(R% zHyEeCfj;SkVI#w1lCs~BM4)4&Bjd>mFXDki(PSm&XGt~VNmFz)DY@ZsHQDi7wLjQf zr^-$Zw$OXC2S-@wPqRM{x6lXQ8;O841dIHMvM|y14=xm@&}CDooy=z5>^oiVlVH>6 z9i!=HH@M_FM)wU|+2lVRV_`ZA@JW9*K(Et%rlYsU;efBFDSPN--6m4c1aXx1yXBsP zgw`2&Ul${2cAvBxDZJwd8a>|srfiMAx`_}uYu-dN?K3DlqpFtQx4PT74DSpu(YL&H zl-1d`UL0xLzufaNIRZ4~zGHf`=P86S0oPL#WDCAu`5NALO{Z)PY~jvHw$atra<8>Q z+fXC3*7~irZs!Jfbv?U2QUu$!{5FUf@%J53sBOz~&pJ}$tq#=q!39)j^RktC+uv)g zg$iL1W%~#2K((NDOD2UTFP0VS3*KdI@3Q%NrzIR9Y%NOmmVou$L_R29Zh*qM(UF8( zgkd_JUk9o)Ql-7TYMA(Fp^S>uP(@_2YWO90^SMaNIEjXQW)?O2Y5!E2_BA#qS(EHE zgi*RJ6ks+H*M)01@Qq@IsgzE)4SF5rishb9??ctFzXPg528hC`V5Z@PXAkqis0lniia6X6@R8KEs;0xidI zKtIC&4C`+I!{|R__*>&bX(6IPhEHZTQG-RH%E`+;&l0^!H9CW}g3gSN_1k5Yj4g!) zqgrVvBQzZbCn{T2N4~R-%fP(n=ih=T2C(NHQU8L`%RNuBMWRM)hh?w;>x8U0D2kL+ z!HN!D`0!#2DzSqujbjV>p#@JZ_r#LYi#v*@ktF~!k6|GxE@n_nXTWSI2eFutoMc6^ z6LM$mKxjYK1{44&0ReT-c;oP&RsZ$y9}Kz#d$=Ex6e$!b9Ep9EqQ1g@m*e_2_B;C- zC;zv#w>PyBu^PtXCdxjqpUy5j{cj>B;biL>N?={W#XBM4BJEqOV?xS9LT%rb zcn*;*Hjr$wb;PLE))HuudODS~pSA60M>8O$0QVukwJpDAO;&W{fNp(A@IT?V2YWpt zFNt0SxM$~!M@GdYMXeeZeAFSMqBK+mS*mqB*A~`VOC$}}3er^jOiE4vBQ7kM&_xWD z8b?ufy3*=!`cokAOnRSfh2S$q9Y(1$sH8P)_hnF0ZOQ0`*=UMkNI327#u3~V-?lPZ1vYw=$$uMycdW6fiqQAAFYCT0I?G})*9n+A{YV-Hz%;@W^04VVAROg zII2yo$HY20b>Rc%c{=6l1MRR~_YVS4`VX@0t{N5satd|DivxsHNjsP^C;^aF3u$q~ zGdztRejjL0(v~VaiIx*y-ap2+xk?g^7X$C0>`pOZX?HA&upRGNBrH)Pt&ZUN6354;QL2*H8p>@#sN*|Pp4U@bFIG? z%aXusvMe9BNhA)j|C9n+9DBSRbAP)ZGo$+6bJDjUSB4C{UwbttvUi9jLu+fQ z@3Ov${cDThq&G3rH8HBzQGJUox$FuSQlXlL-8R=mxohn_*Yx1(R(3Pp-2W&jS>KGK z)z_^)@u`~NX7RsWKOlyD7#I)CuYMFy(-6Ybzc+yU-f{8P+9D`d zo5d})4oQM*V*lzBY@Z*Yh#GpN_j8g_XpbcL=)0wdYtbx)y?d-Lv1k{h!+|xhnRYt& zcaPvf))jRWz6HMNM{S3##5x`Ru;Ca;v@02V^Day|CgS%Ve%b%9Y&6kjtcuVpqP~P)8B+Bqy<$>P2y2v;nEMF5GE_}(HPAkZFb;>NE~Q+IQq3g4vzjhT zq9!uNkKb?(_j`7{0r9dgbc%&xM(z@8M)`4@n3!vPmmN6CD?fT9&GcQ6OSoxZ>a>%z ziT=1@oGelAM<}OxbD=cMO}1;#mQ}BPLzC<^c?%NN->UaTwI<7S`;Ka~TFqp?Rj-0* zd7geiIj)>V(zjz+FY|O`?Hl>?{7$oU&hEbMIphMO**zbo22nr9MIdNg^_pd#T|{1W z`d-b9rcYQ%Q>))v=GjTI{zbBOu$WR*OsSdS7UpT4Yre+WrZz=`WSS5x*H$hAV*`5W z=smEfZn%noTB-?3AMb=4LA~Dd3Zb;?*OIBpp{l>Qm;ZoP%72(vTDr_LzZ0h9rCD9otJ%ueMvjj5MiE(>bB)w}8%Qq$Tf>mIP?5Nu8jv#=iqdF9eO1io0%zpGl=Z z?eve6r6p_iotTTXanSC#=rhoG5p?4qJ3gTDacv8@-Qop$lz)=)?qC z^)qcR5=35EikE=>v}(3`=Q^&&pJuRD>wdh0DgrfX<2r3q*|cQniT4ULnzdHF0q0FFm5^W-4LQ)BKu z0#q~vs3_;ZuBQ7ExDpnvocDSUB>z2{tO5GJ%AITwfu9|BA-7H|b%?9)-1Ukz&NWc! zLC8Akpj|xv$O+pouR>|f;af35s+QukWQVwpr-Pk4pR)a{OTwSTlk{Jv_C_5g{K+U! z$-Tr;iSA^ndiqiOi6FJO)-JBGCd*)XU{#a9oC+-o5o9XS?+RX0_!|Tw)N@oI&t02n z4M2Hb(g|Sf29AlEM1bKNuuEBil#8?)aKL|6?EfczS@to1pQGfrmDS_-F+a<$!0!&E zO!O1@JgNC^LJ+h)DL9mSw2AjjcIM+%uSjB-3#PrDDv@h1vKq6~A`E&_M0^3#7du@d zYL#G4t-vA*Y6+sCR)6iH#ZBwnlr_`o62Oz}Sv)iddLCXdxas&H+a^}Kv9r?N5KrKF z9zDNZlS&}@B-;2j+d3ZH{F=92!9o67+4|rpM7wOfaTlTwZzvID9AU}P!hLbHu;(zL zv3BYZc3n2V9kPP}-m2BLz9TE%Q2*iakRb1t|1|t4Ti-X@Q(N44nyW;3A;+_qtyLoa zTtDhWQjL6ZVbrJ|Z*vn6c6(US^;5E049Cw|cR3xkgHDP36f9Fg2uR_xir z<_Q~*+|A2w_L@+U5EWH#WT^$RcZ8wUD~dfE2yEGZ7vgd6Ou&}v4_Uun_6|R^y0F-@ zmOR_bJ)4DRCBg3qLaPgkJ^vv2A9MM$k?)Y@&QVmaVG$MyJmZ=gGCaZfGo1$a0lATZ zH&*g^Iw!@RM05Gt>`sXUPco!;>VkTnXmzg|cnBDS1O9a1Ae>4>`j@M*8lgGnXB4t6 zZ?OKiIozey-)+?2)ezcNtGR2SHE{mbjCa@Y4fGg$f=WlrD@z+3Qn%xbb)_FL0{`kA zA4aujj9N811>!bC|H+bggCWEayww~Ll5vT32_%xIohw&2OqW@+{MMCjtHW(S=*W2D zRl6bBA<*eyjxcf*1G5dBLSJbM?W&GjWf%9U)Z6i4&Em>r7$l|MVhKv)XcucGN4xaX zHJ>Q&&)Ak%4kUEXL*xtSo`iiL*_2}dzn@9`f;#jkaB9}!2dxfz9ofDWfBj}Cq_>3( zxXMRy^Y6+MLKPF4g72#O==1f`Nj~j?6_~&xe$rQWNT`FS-QMQ-6dw4f_o55FU+R(H z19SEG-J)qtKe5QHW9%wb!GSxKmH7@SY#j3)XDsv>xJ#7HfTs|3oYr;=7rsOA3J4vr zdUUkT?#(A62Axh7Es30vBGJ+MBeN{@bKJRMI$CS<-D!ZTM2|tN;oBPSP=zvUg%q4Q zGM4gnysfQEWROh=Qz%y$kxiIX(G!BBv|E;XJRQKbx9$XF6GWmwux-wS0J2@v@es0A zt5nt3?jZ7Bk8C0_k;oruF9JNrVN_EB9BZ>A*5dQ8rf?+_^niir|jl9AXO_HcFYh)Z@MjJon)pg69@+ zc+S^bNwl(|qNj%6!*kck+5-*yVTDWFZ;Tk5jcl_IDkMYx`!?HTu+v)Qh&$L%Ljoo% z%Hem2Nnz#+80}#M62wHzkM^Z3^%Rlzt+)ez>KtjFE3i+%##B^DR1dQ;t34$*ovR;W zW2nBeK>Joa(!OOClC=NczV}?Vj{9C(i(vG2TE3I1tg!3k=NniuWRx;&sb?x_(+tw4 zUr3wmfi^`AQqHQ7OzPn{0xWIGJu9M!JYYKh5*dI^Gb(h1uZo%gzG_;<6n=M$-sE^- zu?~EdKGCh0I^QJYLHMfU5~g{NE_9?lbcl-yPjl#){@_2;h@FYfThMs!bx@;ejsfHz z+QPTvS)DiExA|{P|0WN1Ir@+X{#t2y%ng^Rzuhp>Zb)&NqTEBAe$Xe3_E~x1O{RpL&=DAb8ciDUxQrM z`r50J3!T_#-57NzFp)wc?V$T)NKN0){X~^F{sAs z1R-(ZedOQFHADAQ5R~c;(navA_S;osy;1z^!~C+p1R(~>!sUR9-WUN)`Q$^obgHq2 zXuk2EtRa(+Av0uCrf`17mxOFEWpUSEbYC07`PxI|+5i}FiPgb=Y-JxkP~C*>wD5B( zV;`HYhYZgR(S!DrH=CoVw0cCM8GcfT3}kJ4)8}T>>XCn5eNv%w`ZHxY`i$uv#vORi z3H1^rlHk{jakp}NMUv2BZRcKI_vW8pNUImNvRdz(l8&_cvR~N@_nVD%Y|!c+jy5;XX_^2+&!id)ANazU zFC>D3Rc}h-;qg^Du+K2bl)kWE#Td++jhBnfIw3V6%h@K={GvU5O<`@5Hn1`rnc{4d z9_23FZPHfmq5&7zm3ZXG#ZBc=y%g7)@k-4f6}nUk!)ywt=ESZm^RvC3@84m3<GHEs9T+Q(OrG!dd zD(3DBUSxA;X?wC@vER}uiTqOR{Jhl5^Sv)=x^b(aUUs;?;gAe;EVNlok1cQ583Rd3 z$tiz}6xI(#t08vIU#bXb%a(?ezpaa#6?uEHATD!ci;#+2EH%FtAz3#}EXizv#&CS?aCleP$#q|)SI&Pf@sh2!p7*^gub2y)#Cm86*6$Rps#}*GEc{Sr&*y% zMH6M|nTq;CbbN-0>=d5Q5Wxq6&v9ft4!Wr=M^AyyTS?$s1+cp>BZ?(Y2?h+@M+ELO z!pUIH;2U^8ZTaOT&BLeIt9*s#}b5fyPe zp+T_m_@Y)F8m8S5E4V#A4P!PW(?44_FUz>Py&!T;ZkE#&L17izCOD}c!tB6uY9g| z1_J>+rY%;3fS;bBH5`baBM3JxEcE=d%M?d7Zo6fQ6EuCw~iT^`l~ zYKH4C$fffDoUs2m~epUoY)#~=g8@F{? z^|CqqP@|#H<0Fl$>1|wqdqAHU)mUwP7efmaN-fhI4^zPjbhtLP(6gb77|2!K0{m=R z--Y?mzTK7K?!x!E=}Qlwetwyp(&2+fEothk?xreV?=lDkq$sUj-Gy#roHVK3spRe&5iIW8w=vdAEUM7T$s?V%=!q9_7+5Ep*3(DI$E&$dVqe2hAo#R0x;{ zZGM+ApOh)$Lsp+VhwR|FWSoll#syurtlPa=9O_)y1=N|Q1F$IwLhSi-4^~DdrR}_D z%<0lFR?K~Y?lzhS`+4JYw^11xD&R$)PoaOHl%ChClrHX8N(UHrqLgOL%u(gPmU$x( zxPS{8=T(i}G+H_P6o)!+<00DvGKB?voPU&PHV%X|q~n=?1q%J}GFr082)Dk8Sx9-~z_91=myLkU1q8!g?S+CGqdivX`KZEL>UTS&p3N0F z?7{1vRbJ1B?05WL(OkYnl=?dKMKS8x$~{q@WQQ*z`(SaM3JI2oL(5NmRY6 zez#ZfkuNKIK)rYTM}gWM8Ic$F%$ZAP=XK9J6{OS6V0pC0N?S-hD zSjt>1Aht3w7#8?s)fgK;b*&2dQnc%n0reFbvG4zIp}>(*)NivGCNyBp3ikE1qJ~Z# zM-}+X0(4Z3NRn0tTSUqgJ2rd9V}0I%!Pt%j8d=pl%DSx=qnYY$Ws=vswGA5yDS9v% zHgsG-{2uq2%*q;4c<<*ToTANq&9PJDm-?Tm8G8 zz5x_zq^3{?JCppYiW*~8d|43UGTyv_yQ1JTIYEKOV@xE$`Q@zzj?R4OG(h-5_W#5( zhu9m>BeYXA9R2ED(R{0;HNS{^4h>*gPluxh6}QjV6z$$_qLCg8?O($P}f_%M| zXhZ@gfx@9|l7eMK^=L>6Px}PagRL6InV5KPWN4`J?h;Ql(WQ=U0{~k;A6q%8FRQ(| zL_*tPrOL*kJRqB2PYGqnHp0*RjeMrC23x{ z?yYP)@2Ta)afQmyjNbytH2x#} z$;u|OnO%T2VaM-1HwGyLH278c2!h^TKr27G`94n(=Ptsj2+V}-uzjAecc5wTYC5%) z(hgl>-64zTOK>WBqGq?^M?OAQ3k$ylw6Z2h8?yxVeewL(5jfN|DKUL9C=!~|o@YhEttobaG% zq{p$O@t>rqCmuz=xJjfFgi`W+b(4anCTG*@hMlXzHHXCToamL4OUVyAPc5u&fQYj%QS3Nq-VKNzt2Fq zvz$x>1^*eROA4P7X7Cu~!?=eD)g+Ct9!ZBL{c(wB6$`=1n>QgiS*wOvJ*krQejd+> zO^ExK?v8p3)ouIJ28S6*SR#k+VKt|WD<%j`kLdy$PyE@cEMfg0$=p}1ijT;wVagEE z-}gmyv)df|#~+x;$;`A6w80xHtg2K-;^lY-?>P-hYw>QhmEl7pc=lX@9z_kKU zXqugg(Tpd`tnc(e25$k_xC`X~Sb9~uLpmTi73N{y{0ZyihRuJ&qo2y{2id?gHCV)C zX~vk9CO2ylgj>`3b0UWtpIHeuVoD$PTZD|R6B0X?S`YaPwN*#{vP9VTg2}+Mr9$IZ z<(7R)5Ih!U45*j6ktM&tI%@ROqZp|DHCeL6EJf0er8+}M3eR8=&sD2cBRA9VvEfnK zqx&DHeboZC^+j2F;^NaU%Zg`unK4eYv$|h3Nar;>B%8d4rE`ORkgZGn;e@QQt1IVy z{|~a0wXJhy8G>q*-L(VDGG{j?-g`KD_ESG(v~?jjC)*c6H4S^mm!pAXe16~h4+$-y z4A?U^eP50!Z{(V@YHX&rN`^{C`!}v`{QK=)JDLYj-KMkkq8++8D^ixXHdm2O9%m}1HNjxNi3;f4%}f`NZ`;b8Ejp=+V<&9OiN`c zRNx>5+^~%f*hIoJjovzNa32RL(|FUf{U%oiWq(r)mSN^d0mF>Zg$fJS-NbYiC+7u` z4^5@;7mNxPt8(UI&j&YwQa0Rx+$D>^cmk6l$J74l#%Ysm-f&VIg2X3s+_y$9v2BDQI^4K ztB;(y2n^s|7mu%@3H#zLgY~#9=zAAzhAZ-@eM=WqUsi_=N(>MHIJ1tZ+NK=^Ho{P#tu9T16m}i0qst^NWQ6*#--YGka#!yp&DN3V3f~<(>^aMAmZ{F!v zcx|`y_LzrDb*eF5m1-hixBs?V?=PdF_<3GFOYBuCq3-Q0gCtKF2ifJ;D|799~RQ8AR6SnSfj{V9zl~DS1tj@UUF40{YNL<*S2MUd{mQT}~_Cy{;IH zsB_A$QbRy*8^I{=mktzm8^&c5^439@+)g(q!ZiyzGu+RhO)(6^zdCQG+$CoC*Y2w` z-Y8>YMx~cY74iObMw;<@+2E%Kz1K|KvaTsbFIzvB#nX}qkUrjZPo;A!5(^1$%3XYh zzxTe0;eUERl;O9&cf%etT3K9Xo$B`#mnpKO({_myr~7e{o}SBuzcM%$Ub>9Fl~jCP z2(>hBu9KTq^{mmhdDji$3z_f*q@m_BxttGw4)bAX`)IXsb{WIJ4x5Q89~$0=NjKPY zl5wkiv+Q{I^Gv3g318Io=Q1WUU-E>6K6p?=sTu}qq(0-kGx{|HpnE{l!^lnQ#T8b4Dj+luHRwZ zZO{0CUBFA?;CqR*Zgj4*uFOwrsJ2OkC<(5XO04spK?jpg$Sx@5 zX#!jLouOv0SY+qRD=Y1Kxjj7J8y?&T@8{b$K7p*vV4I>0-@=3J3+=*zki9Ce4=i(+ z`uz^+0&)3g#2?Sk8GU@egHHXFEfd1veydl%%^W6I$0!Y%^VPGGnORT!W(^kxQJY1v zAF;~$r9JxpKPcyw{tp{LQ~1Jp$wqc1CPH``JCK@2Y-pe>d7;!L?%S&?nO^$e_fM@D zx`-3Eu{m7m?gL%Kv2I;NtHqN@_R5Is4|EZnjRIuo+S32ER|w2M-YOAjbPysN^xHBH ze2RA4!xyAamF8xhNuTZ~^1*poA4ar;`W&4FS@EbCb-37g@QuX8Z*r3r>P&G`%SzLM z_C&LE?r`I_!p(dKm{tOo%I@ZCqR;+^) z1ZJvv0sG-W%Fpar2b|rZgR^w+wjr@TFe09g{`|GOPg{HY6l-g=KdLE1pMJ;S&)&~R zZ#NI1Q&p6FH)S45rw*m!o}qM*R;R+R3F!oK4LGe2!7`8ojgV^>&A!dc>iMC?|%qd|$hNp~O z>H8u?v0J)sA}bt#B^!(QW&J6ev=DfvC+vewczbV1pgDNaT45zRy??So*y`hcwzZQR z(An>?&}rDBEx3btD!0{|e3x za_rF6+xdNo{p)nQqyiZ2fuQJj>|c{EUIVqUlecMd(!XAT&k#(QyebkGVobLTmW00 z*Maj_BfX787=Ibk0Hi07{s=y2DfstoNOxiH+>Ue~sSAn1Ga4ysngp%!^szH6!yxb#{8q7s<$@J)5p-E+P>M}icTJ&k zr_jnib{)-81L3jCU^{oRVz1AHiGeQ{ahd?2f&mPcn9f8g-*^S5Y0wK0*=ZC=KOJv- z+;F<(XpoM#EiQ&GQ&V-efiK10?W(h#{}ZcRaf>+~q@(LK`qtJ=nby~yHeMG_-8n}K z4+Uu(+M%Y=WLb3)lxDJieYiZySpZffh1c}mHML53Y#R#!CK+qGUc0tEF}W3{|FA{N z*w7A{KWPoj%(+LzNFZFTBO;%Pe3VO1h6MQBgs{-0k^;})+rdaTUrU+VZN*KcTO2yc$2eBE`0U8ZWQd5)M zbEgzDcJgR6;VlUKHiIm*1$xfI`MZSkhS7u=OF5qekN9n@lFC zegnq6q$Vrd9zh7D<*#QzB(3y7+8A4$_*bnK8^ATg1iEXI2r6xc-St^ zoE7q2pMd8T(B0YXz1dy?O#1l50b!jY<91h0CRqzvlvfx8o4M}n>knn~3_`j)`$})N zNyyK*)aBix$;}OSo8f2HtAWe#c6g|}Ihg_No!cz+6#R-3z0Z;FIoyU@@+kh@haVXt zDdU?r1FCQ|$}o+}sBJ4b{7_xU1@DY1yqnlS6}>qnyMB}5-S|imQhCtohbzZYFh|T` zz%Pah-%C@@St1b-307?*;Tu$AY8nj&q4MKv#y!`DBp5=wRrI7?u&ijfmNDnXkXi{b z-eYD^+#oVpRL1VBy_X+fXK7NLn)*R&bJf>)fi8DsU?=qH~0Zh!LBH#kqfXZ#>%dOvSqom z?Tq{Fe6zP;d}*%fTT_c#VV;g)KMX zBeGPe^X*vHsJelE&6`EOmrWUqt}5~acb06bVDVK&?yX`yo|!TszT_LGhJa6(L>Tn_ zv`ei9ez*?qToJL_LaU_gVXn{;Lz&<&Wln?^IKUSgW>H#khlY{CWr&$7#yrJ`CL}BG zE(XM9Mj{9%kkx2uY7*dr^4FUgvG;&QTy(v2X=`htEN2=J22e<9Jf$6UZ$NEYq0%p#CYqX{pJ2+g>%$n)4e=%CeC;U3C#K?j{d-;;>E`2M_b+xbOJ!>-ne zk3HUXVII&3;`8;R1{7Y-GEeyNNM@aFFJB00h_K}_TW5Rrh4W=ViLuwaT0pc=%I_96 zJ$@DV`LQk%t{&YD&_hQTd8F4s56Q2B9t!S4zEWjX2M~1FRHf1i1pSc9%Wq832#u~> zzgXM&tHTygYf{_{Gl~nPSI3)uuM3LIPZrhTK@DFay@hlEsSBweo=*~40Jfo5#xVm=Wpx7xuEJlGrqJq4pHYvP}xiRA{r(i9Y&uR{&uq(RL{Vd)-CFS zujc1n%0J)CSbg^aDMI{mv4!uPr&G(Rj5qG)=nb&mc|kuiBGMO5X%{VO+CloZm+Ko@ zG&mFilt$^@2SkYD?juA<>D~Vy5fYyC!XnS|yTmu$^DBJQo9Z|+B>!$k)}r5%AvM1q z^FBg`l>L>Oj+4cN-dIAPz8HeTeRzaEjYhxr3TA)MVdrl(M~$%a4_(=rSlaEiQt>OC z&Y+O9M?s|(jN=8)8#{m|VZ+2Pe6BG*J7a){ykvkj1|e3osIF>zGy_{EHs8_3DD z>(+Lf_@62zH;;@k@%L7l8JZU2U5ddN>*X_INE_BY!KRKto;v*b_inmkl(q=FGuH2k zutO>_c$YXm0U?K^3PrAZU)M4!BfYm5>x!?Q~gQ7cJP==6{-98l~nR%vRy=)=jE11ZzcSL&Z!?wEBY!gOgTLYL|`32VIc}*^nQjYEJi3ZUL7X*FS`efpR#pfQ_8Q{mRdI6gwF9%38@0_ zuclixlv49*PX&^dI4wKlnOE^lCkPuHu2PPAb&Bw4z~eZT$ij*s3)65gPm@YeJfWQr zUjfxUk(RfSK|jSPzgg&Eh&nR*S7I+3OBf(LF!B9;7~HZN=nCQXlcsOf?L&pKHd+S~3ag5S~A00>~438h_F~l4-EU+n@4r}$kD?M8x(jF7- z^5$cKmyZ(0rUmu}z3vYkKK}NEn79G`-rH>+8pmz0hOQPV8Jjit$?f@{x`g1ha9@l2 z*>841!KR$K5T`WIP4!m*RClqdM11hqg-sulK}5*&-en{V@QXRhEi3*95Lb?PS*y7M z>rPEFf#6;hg{iLN#U29)Cm%mAB@>mpuxSRP^pUwNUIFgg089A@CaGwJq`Z4Br*ZONUdf$D{G@qFeXhXQEQKd8jrQ_1P2aQb z949f%UXlT~6N20A5fmV^i>FIJBK03!Y)#iAq+8Ar*Ek&j8G@h0e$j~+;Z;4g!@x_C z!-<-w%U%N5AN%Qj<(cbReQGu_~m zu1o6hjz7c*4#@$21^zuZl%H6<0w2e3_P{P?yx$v&^#3=fj1;lsd;(-RODo~D$pQ1kQvQZQvF zT>cVnj_8tm4au;AOoW)yS||;$|C$M8?@gi!U83B$py|eCthGgCt?|Jo11zH209bsQ zQg$r=uc~0OY~jm$SrG%*7Woa4n%4CJ$G%vt(`By?R?{g}rId$Nr?($0R!VxPsFEQO9 z1;yFj9}WgjLPTLSrEmc`uW+vbr+MtTd~7r;1n9RcX!?ZoG3C+yguUW<@v_fNHM-gC*I#n{sn z8t`mN^}Xj7g;LaFB&rOjvEAu`KxGWy&lo zwqXCkTn;9KrkN^Z>s8C9N8YTiFMj-ET+lQ5zroM=)sedf_&@}F2 ziQF`<#rTKi7Gc=?LX(@F6FJEExN!t#p~om?EVr9w#6_G$8jmMx!Q zF;B-$COKpi%+uSgIR^0km_=;NDI!c0Itp1p#v4~HTd0SgNg{in!A{xu`E3}_-^Cq%r zR`nlP>ukS%`p9^=uIN}b7Mws}0 zxPTId8I*w^qV3Nnnq?D&VcOjJo+n6Xmk%!yyWD{+ScifL);eBR$PX)+KHt-yh=~4v z2~jwjB8l(Ud{Lnww7@Xm6HXq~Tq>H@6h`tvG!}%i>6r?xj4ig{gE~GjdMDx(&D8?U z)f`5X&d<$~TrZq%yKEw@)Cm0!OUwU+s*`5YwdFpS%l^y9VZLB^l*3EI?q3}Hv>h-;>9>QQwZME^K%LI$xg zhkKN*FL@Gy1R6(N0{^{@@ZXYVJW0Crl4r;U7L5#emtGoP0z|w65o&pb?c?s|| zgzD!B(?i>1K`^QD}$;!ALw4}Le zIylCO&0H{Q@~nn?W=CxNsuY;R;RzWiiYf=rk)tDj$8RKlmBjZ4_RrUsp{@lywLqSr zC4@s5qx^N5BnIph;YWsZh?_>RD19RQCliMgxPV|$f{5<2XZ~kdt?eZy2A-4{{}in< z|KjOn*=WnCj1^TiW6O$S)dJ`&5* ztBT+<>qurZ>+uIN6A*4;Wv`)EUNX&$XQpN`a(Ors@5V9n^WHG5^ zDJ==L@DROD;0w#j-gpTHAmct|up`w%*vMj5x6AF6nVHM*uFKUz>W&2!}5?irt$Rh{CYp+^^N~tzW$jM$;R~?lWVYjT?wOr7?v`q%B$pOo2c`? z&N3lnEuwWtI$L;@(l8I`FP_fbq2SCa!DR^KCW8JI#wV9Slgy!i2Zu$M!ukfS2Mvy< zTg;S65Mgk$)8vCPm}QdqqhtH~xT~m<%A^s_j5AA|hh7x&!f6**7zDw5}P91yYqTe5W z(g)W8F6b|S!;WEe%SfuZKmYUHblKC?r6ZpYrOT2jUpUoNa4`TpFi1X}^ntOR)d!p| zNbzGYU2Gayc2b8@$IK{o?tyVA5I>^}r6785#qq8jfx!q4G>akvvaIn3){{7@jrqlX zhKr-hkU|I|j@YLF0T1G+YQXn5lg)dmj}C*{R}!i@UP^+fiXx7W-@ks~u*Sa@lOU@4 zKoHe3^y}70Z4ClJi!x`+;R!WDGj~|l=+7XO>qQeJ}F8O)&;3mydIos zq%uYp?zhODGiRwXfDrNltE}ZoF+<0Cc^GOf~m^?dvIb9~J z95RvK3HD9iCTI8rW3^;aE(k*T`;TuaS0s>Cg0)cHegVs2jSK4FfYI*2RlVV&n)?W= zuU;U-x_phRH@Eti3%&s~N9Ovlhpt>$!?-|J2BMo8;FChuJl&8$z`PG&UeB%h0Yj^A zFAW4J<-j~F>Jge0bNpz4QVz-|AXe@HV2A-E5_Pkl1M>Y5hFbaaQWA!`wkHfVP52Rn zp?<)XkXXlo_@sdGjQ&%GzpW}1)+&%Nb1;1-toY=|1=TYbR#wIbr-%dGYb_bJCqwE~ zjq^(s0eC*I1V`gOGn_#5Kh!{&7=Y*rDjk12%2 z44fy-i^F}{T^4ZKSH0o_jx-8DS^{SCppNwMwjvTKKp`@08Ap=j69Tp63{pkmv%W!w%ZD$B5i#ZdgXvt0Jm-ScoIh>P-*}JvOV?R zICC}yXIJ$Ql|a1NzOJ$p#Qs%|_+Wd1tG+@yf%GH6TQ&;&CQ-3CiTVX#B+-oXu_(Fl zF^h0}_ME;+tqUByUh|{(5o=v#YhUJG=Xcio8}BW%)=P&uaF}cA(-fu>R#VB8?d3eL z`!$Ey=Z25bP?wR9_Ib@?YP9kY5tH`Vj1WWI7|Zy6wXx(kOK1>6lbkk@=ZztYWK$&u zR2MfUh3Cx_f=x&WS}J2y%ErETemZpJ`cd{v(T^g)fEM6-N_i&F!(0I05dRDKhQkCl zv>;oTod!>b)a??nP)aF($n*3kWd@Nl%^b;{A`GFFU*~zkNPd5kzn93ODCJjqo_-`R zoaBANl|A?*O!O$~CK)H#%C+PvG>Zu!KvR|5e||AUL4<2nIwtgwsfZ-XYZCqfQ>!+1 zGaq78^cxm;y~KTR1XqW4dmh%;bUs3Bcw=eQWBUO0Sncke;;PB&7ybw<(-eMF+s}@f z$8I7T8!CwhhY+tu?;dX*6sRLn8%P+XA|BQfBm$uiiT8vlHg zm}pKDt3}(glljIe3sSHyx-G{XgR7@4b36R71Fz0rh9Hll7|Dk64UgvuH^Zcc7zLO_ z+s$!&SV~58j2cXg%VJ;b1mJ>K7B5~<7sL(glbm>x&~G@nNcnsoX2wCI^>y)Jy2%8M z{uv#y7P^Z>tLXPbB+Z*X_KLRO9ukLcsJRXpxXwtJ`t_1N10}?dJU0G2e1y1?V>603 z2X}8qtRdsm+}sHRYbYi#cN~1#C$R9g_bCLwaeHtE*|j=;fo#D;5F1_jxxGR&sn?j)Rwng2RDh{hb=j{N%%d3d=oYMKk!R#DDN`HA{@iqy=wVYtbwNGw zN&YQ&ZV$d*au6%29PwtZ%)zm8a7I!8OybS>u?OJX7YM$3_HxM~E910>5?F|NPfQ^| zRNWn)GrhMiL=&@bV!P`*F~@U{)b|8e-)j%o_s`3&O^9sz|EaLDx4vA|x3QxqJ3m$`5WXE}|r5)#qTp9KkJI}+GXGk&=hOuZH5(}UPy;9Rh=cms;_A?8m zAPu=DBqze|MKq)P+kcsZq3e+cJ%7Ge9@Mw`qe4)I_TccrQH*j^Awp;ctW_&L=)g`I z{ng#tzwA3p-yH!>9?*TVZACD``R;a z+bR3np9a_QiPb(+r9&3HEbyu3scF8MF@)}j8j|$4LVR&pAJl%3N90DkJ;!lk3l}t= z+}3;Cuai&PXX4zdaPFNEN%lZHkzK>R^Qa#%uLXnR;5W@Z4^Zz1s(^+_Og+g92$V2v z-SqL|z}RF&lCha6Ab2N+;2o_1bHf?Uzqgi&8MDb`yY*7Qnmcg9+y+LSnI`1pbl9f! z^C>frT_vC3qf)pU3A^!8WuWdPYR*G=@!GkE@Z$3Ue54_b{C&LW?w-4AX0-2Ny!a#P z>BWoB2k_BT=YJP3Ztw2nzeydYSfXh4#sQWQ{@eD&xdq+zEK^VZST}hmsY=i^fK+v( z8^u28615+D{;Tdb9qwt<;%;2Mv!_k+$$ZB+Kk-eV5F=LYMT-YCQZ{^VhJ z@X^KU4IQQUa9trrIIS#{3_90DAoSy?7$GHm~o$*rN9j5m7dO041>^G@hjgtQ7LV2ao8&1U=Ae#b|crt{*1x#h#IZWjh zP+fovAi6M_6O%c)3~*b)3}`48$BW=eTE|G5(awz2a}da6yQd4}vqkFJDqYrOUDg!! zYz8=Ay@?vhmjYdlxd5Y~M%Ov`Qes+i%})Oa*=Tdps0*!T+2|42lEe%;R;68aE-^je zQHkhA2*YMT7&cAYG#;trDXtFNITBt9zQp!(P&=B*tJx1Dz)er^G&YO{!kZErv*5K? zOn_9PC=4swJSR$Jw7&8i>w4j%VHoUY$|yUR%eeDsd6~$_e+lj@Jq`o$boB++&Zu0b z$E{g@n`Eis0HU)rL=qm{d0Uoo}ky>#Tc}7Xnk(I)N2~3Ha(Fd z&}eeis&P8QSa0)u^kq|;l4thl&VyK6QPgtnQX$qyM)5oFzRc@fhU{#W1RFzRdQ+Bl)h$J^5dE=R0UX_^K#IycK7fJ;u}Q zm+~}S*vl;#*LI|!D2~=C_;xnx&l3SS07PIp826ps5ColUo=|>U;u3C+>o2Vld9LH^ z9YJI0IhRMlFq(C2FzzV4~^77?XzIsF@C^|hXD7aF%;aMwCH zA=rb1pj>e(Z%e#0*QYfyI!H2{{$*Z5h5- zAlamI)8}9MR+svDYB*K(CO!vyufgqQQi?=K=Hi9dUeMNFNOU;WQCM?r8qNtuJ)J^> zQbc><|t8=t5K%Q$hGLN04#p+2=!Y^T;p>MRwuVstXP>N`QHX&XPfbU6Ane>^z~J z>oJHGTLI}Y9CXy?KDPJRr1w}w%4+4G=c&z5l3-%TaXa`_NOz|tVe9_O|z( zgeBDIJKOXxvWkF&;zdnc&cf8^1iM*`esGEt(E}dWgm%v*ZHG?iMKZrQN3~7`G)m^T zVabajb|Dw1{i7vQg1a$)g$FzF_u{lCJ$IJVBJCN+@IH?V6~w8<5JgBBSdu_C?(^*% ze!gEjp{YM_A-tK#Mw;q4+w`CArUE6ub{5#~6d7`YlGQ>nCzTqcd}GO!?x2`?G*Q5G zJFNh$qAjCn0{kJ;=6d&dYmS1W1*^MQNgi~D(T)AjHl6rM@+7`WHC%9C==a`V&h)2F zUy+`^8ea8BH={@mqK?9VO|iI-!*ys)oSObFuM?YOO<-J-B4%8;e=gKUr}XGKrWD-Elv@5qR)X1 z8F;qoB3m{P=94HkQxazy7t+!nP4V<2Pb1EPNfAa+r^;-aS$lMvMhU_ZN_ij{?5m!?{T)N4DkqaDQbTb&d5a^rX#pNO7d`k%rkgCVi-mF zai5Rtzv3DvbF=Glor~-J$p06vH{$vruJ<5qL)wWnqKS}lqhv{WWWp0{@jOsA9F^d( z8MDqj830H}e#Wux|2UhM-T2`d$brgaRGzHhk7x2a!K@g(p_wuRDv%{JTm-x^Lm;}AKo)AW%N#cx%{G{<(5&yA zQ429sXty=XU7#{6H6%?d?`dAP`ns*%WzPToIcGp@fB)UzkJsyA&iOp&@;uLZE}!Rf zd4DWyn!z;gth}w^B9m3Th8-Uf%4;-S!-#RJG^;ayVTw@$tD-*R(XD4%RNSC0U+MXz zBQRhPG~C+ghFjRR%eWECO|{MUaxqTFrBYZ9>s6~wkL#!1%rrjQ=nr95Z3uCNs1}-F z&>mM&(Qt`F$X0jOC6|w>m-D@vo1Wj$2SAMrE&_m>d#-kz)@x#)e@P~s zlKq8;s?%a}PPpXT&{(yqaZSU93PI1hbZoNB_wOZfeC_J>?#Cs6 zv3~V(cbx>3QnQdf%zfd4pbvvv>Fo^=a0=N&h3puQTgZm1y^w7cqSQihtPrIUisJ+g zE}I~rve^?+Um^Q$cnS*HlLXDpLiRm^X0VVw+0!XxPjOdBt3MDltdKnwMeu3{uc;_q z-@(Ojy2i?t%_=^7jwyYqD?7ubK*C0kHQlomIyu2tN*cLlxRlZ~&O(Q|O9kIc|DepB ztp;#3ioULNA#JK$umOJaLZ!hQ(fwEh7ft)E1_T#?TV{9R)ci%G`6x)^mKx(bsgG6j zQEKDpPJB-4d51Q-QZ?#|41@jc^9v#d*>`EMztG+!0zUmhF{?PSyoeDaqh-5pj zQFEgQ@puFkzey*HMmLs;U(hXQ=@tWGd*G!LnoQqbw*2EVTBMR~Hl>UUcV4;-;Tp~- zurkqd;WAM-Rf1YclJp6zMJ<`mUEWz?7@3qJo0=4}_^Otci^9GDH)NrO)76)+tQyhS zxVmv<{F>45enznAov;#TRp?K!(II)xvNG|di;%zk?F@m7oW@KFZPenQRN4@U zi`aIy{q+n*E)mZlv(AGryhzOr$}BZ~@La9fDdq{4Wt{$fXg3ZIosehSLO-(Q5u&kJW@TjqB` zWLEvyMP{_2RvlS=f0?+P^46W9XgvThN9H3JQPf&CqI!Cn_%LNYCExe}^6Em!D9&0Y zK1B3YGQAvh6sh`m7n?1mWkzF?amDhYCX_8X#BA?KRWXSMds~2FkBu%9cLd;NvHT3h zFPjQ^hDWS4G`HEe1?ra>JkFBB@P!0&*tpD4RbfmSN7X!CU}#p+!?b+p)IwL7rP<~G zAPbl^n!)(@9$CnwsVWcks52~V<-L2-)c1as_VC>&S`7QDu@YlHhv~s>?*k=;&ff>ndr(-poO^pP*Lw_=)%E6`9jON3Xj!hh5KVdF*rxj~7g@l( zZg_TLA!I#hG~6&D)UqT{%I}=W7afAu3_=Vh)!?y=OcZUGae}9|k`yaB3^hjhL(95T zBhA4(+0-b_{xW=JF4CC#jA>q=eKUhgu`AFFuJ`2ctTDh;!dUBr#YX-6LdP*fN^RGg z6NopIvcIeTgs*;;kn&bn2NWT<3n>*s{a9<3yx0TGnnnT@L zft?l9P=H&X9_T2tmbyBOC(f?Y#<=&m#0=`RYU;F|)~T*FtkOlfx4Xm%0U8niI!zB4FK3MpDE>Oddb>sLKAT+P zXlnjTr{N=Ik$t2r0bq^e70FuDT>*|@CW~3qV_!jv`Tg3$V9wI`)z?LWqv^B`brGyX3FM`_2Uf2(MB!;|4ffw zm{!EtH(kIafSF-rVzUWTLn^D{*!rZEm=@L)IJEMlP=N2b)P)%VBYUY!+;9Q4-%WK4 zP6?xFNDWGjx#`90Hc0sej zS7Ai`b|xE|?5EKw>Q@?N9V!(3br+gVm@`%^Yb3r{S8h4xi@!zHH7 zP~yO#$A_7qwXeKX!qX9Jx@m!@6HqNT@jW51Sm%cOO{#YE?*l8*3|K8gC%=&z)?(Oo zru@5~bsh&-;PLn;+`c46ASL8nk``a1NIWnL~xl7$H(E9f_~O3DT2qbNNY8+sI^0 zYMW1TX>Xn$9dF%VUE{0A5>GtZ0@{XqG<83g%7OhbMsU6mNXkB*vDY!KpR7;zZao4L4}nUr~V`Cq>tD=Y92J7(%Rg41RS69=1;p zv*r~k9Up6G#mS<9sV!+JZ~JPqz&TlG36NX#BUZUw@6PE;Gxt8esaN#5war zMi;8}4rArJ?p=>NfS`x~F681wFF9uJjH>83&=>97ynmq%aY83Npn!^_(bWa)_;|ve-vq25+Orye|ZwJ zev;Qh!$#Hfw6Z3^^YIlF}zNqKW#X`BdlSV4oal zPrFq3b;?=OuT!Qa{E7&WKTnx}K6>%M&r`B+z7W4T_?>}tKN9uX%u?&WB(vH9oO_-i zUQE{>MkSZA=EU1wBS(yE^%)aJRxC_(X|qkOYvST0F}DqK^uZIO&?8=%Pu7umI$ zDb1u_3<n4nFf!*We+r3l@Jmclxd_{vBdYrfoL~JINk3l;MUo)*733 zOTjpzu<;whSN~PoPV9sixPRLv@6bM5Bt%Xg5?=}f)Pne$A^eI8R{>wCLTkXu-Bl1; z$pZZdTh8cM-npz)#OMdEH~q((27x|JV3;m#MbdEc@pNg;L%(7hCNuuTaOc{S2uBVi zy{et-`~`efU6i=`ioVaeir=M`;EG zI$A}|0BcGLb!0%qq(Anx1#Fvus)$Iya#V+){P3&#lYBTKsgef&MH4f z`wa#0!`^p5NnkWvlNdwqU@Mc*as%EHLvI;sbmsQI0uNK%W^V9ZL7@w$-R4S+Dg5fz zO11yJ8LlM4%ZgqTVi_X2cC5k}GPBC~8s5-9yli1Q?qRH@DVat93Zn)Xa<*93!Uc~l ztb`k{k38)I{_>dAso5Bg%J|z~g7tZ7IUGAbo-h6sz$pANK#b)dby;XW|9hikORopR zqBj^)W3?$&>rysaqh}4aoIBx))!@;9Kp3<>eR>&206IU3U!ofqJOgJze|dP#QLTSO zN_q;JkW_zm!avnq6T*0RtU^;F-fz?E^TiVZ__=%$K!gIAlOtHx=YjSetDrzYjWD;v z>e;72XBIQnmrvFrKTNf0&II% zV7t~8#Q@D+A=rk*r(|~63gT@;_?*$H1$>%HX^m8QPQrw=f1+P*jG!#uqf3G!XbJ4*z@BpXJUWSvWH#3cJa#_M$G+|wRt;SukWgX#;xHP8G* z;$Aqx(b92Q^6y~!;YhjIpxs>&B4bs!zm!bV&%UxgO3A12J<=DABt^dpsaro0mE((; z1~@EEoi9E_ZSWwqfqxv@Ku{0kVRQ=Lkmr{CUtra_*DmquhxKFUtzN>d!E8<@mK%r_ z+NHk{aBaPQt)u)o86VA^G+&%aTgLkXv_-iWbwd-8gd1RMwaRnwgtUR-P*eKDp_1Gj z5-rY)&HjkUA*RUros&?J?f4ElIGp$RpG94wpU@LlRR&{mEkV8RP|Najqos67P-{{^ zWo(A8=RjZaVznhH;0JKpM3v=SS-(vC{2B${&+^ke(G-9mk1+sTWk2Z;9jx4D&$4^( zU@X~7;A2~N5f3)2;Vo2OjxJ|K`zVdUR2WQTC)NChIWMzImPh#J&?g=dL~49{-kL-#`6? zI$eXb5&d=p(o0AUNFJm$Nav7zNYfJFFN)tkAvGd-k=7wSht!PZN7{_^GExgtD-y+F zeigsuZ%V$VU*Y&766=#BCQIJ8Syq=peb{FWXOEiqU|5>g@2gCWzr7ti5@5GFdhZF_ zs)@clmgLWs+=wlI`=lmgSoI@kt%smv=HMpUEeRRXg1}9n zdYA`(grhuq8b`17)~&!tvH{KhU8(M^{t*QljQVlv-|>h3P_4hoZQ4bH5UK`PZTS!f z;g==;uu+P&4a|q!?b4($JjRbl@09#4^7M`4*ZK~&2M?@21%#;JGjP3-&$wTa{4tC& zUBZ(_0Yt{Feo5RUEhc*#dZ;+yqT8=uH0Er(Ugg*K!9O+ATiOBsq*wd(ec(^)`iWY< zUK2!wYLtXys=kXi`St!F{mK4|xA^s&gTz%qqF?{A`w8GrMJa_sV~8VG)YqT$d5mZk z5YZB-T~qyeoWit?DEWX0RM}Xj-eUmLt@TmpgZjv78_NdC)$|7WTCI)M1c?v!6GLpQ zE=XM1PYkuO`XKQE1hSzO0#C@&+7iOCv9j%`zawmVScElno;Z)TV3uCQpFzxQ?73!3 z_P<@h<$ONFhj8^a!z@jNU79Nv5@^hbUdW?%U4cAsv6jS~KhG8IL^lyV<6F?}_e;hE zV!rqS#xz4x5T&t7{N+k@w#2g`?z>JH`+O{oeLj}PnxK!R@nKD4Ed&~xssf`A62e5I zeWZlhI{3V>UMxkwS!(RM-kKrgpB!}Yf#a*Xw~iJp8x9c=NICfNnsT6cQ@|gNP8|$C zgt6{fjyI(9;ntg_ba`z+7M1>1X<{NEl#mrn8qL|XCA9@flkHfGEQZPE^p&4QS zd696xcdc1}JiF-$AYU|x?$LTb(|VI9LUoULnyNIt5FhTycz}Daa9^kpA5&Nv3b5a@ z7)J(dW5cuKt#4J?^7PiKGd9i5fZ4O|x+b6zqX2pV>pTc0hI{J!yi6Uej$4Z9I=#SX zZKDQ*)r&2HHSN6S*hXCo4QASWO=&{Ku%0MBg+hIdT2%c2pOI}UabYLNlh5efu>Co_ zPsL}Ho8EgcRaqKfGV;!YecEzmml@QSE7lIsmWKq*(C*L@3qdjm=e)U(1H080sfF#X zQ8xbC`QTQS(vazMtgD8_ySG1hWBkm0%7WW5Ao@4Aul|Yfq%2lf#H2T_i{3iK{m``* z{eAl5E8KUu00gdwakp>`XeblC*kNE5HmR0r_~}{vi10$ez>kP2yH6JEVn;^#b6SaJpJZ*w_TR$;` z50j@&5aarZp?sJ;ZGt#75S%vA!^h2$ZCb)n1A(T_Rbi3tx8{h0iCz2hSCVmK?!+3( z(SyKBLWDt`mTaFhAd^7ZAq=V8M;fv1b71^T^8X|9eX{wp`(kh1hy6=xqnD;nthuLo zL)|XA$2SMI*mTc6<(@y&yT0hH+kO2WUY>G`3i(w^PvFn^Xu9iWDLUUK|Y!7Sd#al-Cd6K^br!Kfn{5+)&b+{EVn2bmzIOp*@ zjuPgzQm5sArL2%NHKM8d6Uei(=pFZ>C9cT0k`i0waLg}2Y2Fi(o8R%c9LY^aYHpp1 z2{`(@LBMjxHJ5dsau~JM{(eFKU49T|IRPbg#^y^+5P;fS(TN zRh5MBy`HeYn+LV}bE~fU^FnL#!o11jVQ}9LX=5k=y`ysmn@p!2tbtcYk4)qusw9FhYEl8tmv=q|*BDag0$2OT&6t8tNnL#yQ}1u*SY5 zL6s=pNo%Z6o{S3^>&+)e{5jpaeuXIppXWAg4uFYx6);_()CEp`4a?D#dy#U zHb0|ICs`Z%jJq0E_akB=+&|4$4DcU?Os`9P2EAwFS@-9qv|&4Q6}%Mf*tjpaNr+{R zjuj)=ohj5 zQ|^348zcH>x0z(Am6?`>Pp`}VZl(L-*jrW80p7T^prqFE!Q1H4pT5U9{CAWT<1nsP zhZqw6s#&e!j_vo#q?-4orj-u?PsC9e<|vG{50;kiofJY{uYgH@-ClXB$#)I|tw!65 z@K#sIhZxcdfa^}X9|(+9RZ%rlTdSMTai6bP);^R0fZr=|w{$L_jpKbB&Mq$Q{2>76 z7*mh$B;<0HUPLTWtsd`zT!?riZn`s`moi>mGN{fy7vRCA8g zQ&|_?;w+fmc{tFb+oK13q_(vOs5u4_nJNW}^Za9dMb_cyRl4fVlAd>?ibA;C9f>4i z>+Zhle>ntWtNopHZt>i(^M`r_^%TFDCQQ|NpNZvSo*${=^v&7q#VJPgV#7PqqXL#!LvL61c?9vH1+uJl<%N1 zTp#G?U)_%fTJ(45*S5M>lwh^FfrVwv829_V>h$3lCrL)IYknTiEK_Z;(1pJbX zeJXy(AWcJ>h%^alGEzE{4T<)@nfN8_rM^Az?{Qv_Gz@#-acEw!GoC zh%j%S-j;WZjg7WtOtP`qHQ$4cmMvpS;!b?$?W`Pj-nd6abNE}*Vtq|ia1%1Txn2?M zDxMCC_1sS z&#muYY-Tam6_VTasN7QL20qk!v6qu4BCLTIdQOu z`?@~WFiRa_k1G*J6Hl<7_T7iS?%$6ODG~1^`ZGkIe;IVZzR(sr-gtc%Jpu+}cptp# zOdo%3O{85p7iLV+zzHsWw9#nQRH1QjVAD{IaFC&C%%n{@j%iaKZ?psg!N=t>Tjoog zmSm?t6pO!*@y60#lAUhF3`1KtnqwC9di2pTVO|z-7MObILz|86Ul9xdg&@%qs}>;Z zP{=g|dp}Nh}--M38BZa33fZ z&l1yqZ!b6%g=aq%4yhVV`k8-Fdh<rQLckPZK+@g1O9k4V^S&a z!dr^i0bV1BhzQaInv{O5gr3I1MiLn8_mz;EA;kHRbfA?|$^KnW^0lldVeQN30wBP=P@b!vlc3cX4HzKZ(5M>1czJ|@^FOz#Ig?5i8=QWSW~zu}ko)BX58jdU34Q>0@^pCcVdBA)aleh2cTF}ODtDTa7b%vsL{ zxV=T{!g8y1=d2lPmTC5AgOHx;=wBu~htD107?7quA!CcrSnG;V*FeL!0MFs$w~hPgx0^CQ5JdRdJlW2hq|2B3ZR`+r9Uae1Ktxb0!+m({4$kg>Kf+i7pNngh9dEG znmk?zz#hT(6wNv71B=PZHMNkjtPgNWICSMP&gTOPQvfs)SwVwr=QFf4(!my~e~yB* zxYp=C@da{f3Yi+c$^``rIMhdt&W$vY$V9aZ3KoSZYh7fb)&&KNLR=SAu*mdHE+|+O z`qTYS*y4hMMIo-~C%)|TfVGWM-r{VKs=GfA7VwXBO)5&dvhP6XJ8%aNEPs$(k+i+U zd|CbY;VSrzDngMw2K4IKQ%V+|gXVBykb-ZnFpSqlSUP5j)ig+QNWlrd89du!NobJ( zZ5*7p706ArVkPEtroXM+X$uAYsH$Z&2UAreR8CC;Ea99i{)gjUXZ(td)0M}RE(ota zv`8t{G?sy-7CjtPr9hTE39K#(+LEf26C7>dTP-64oGy4-mQ=m^VY!|ILcGJ5RgspC zHl(D&&s}a22Z*w?R3YBePn4yl3UNX|QI?h}#4-IuSz4+PQzQg~Mj60Vnl)f|d7gx& z#Pmj3s%8Q66Ycj4DQ6X)Hwip%BrYeO_qNM2&l^EJZ}}|IM3??A@w{=DiRX>G9OQZD z%@X5?x4lTb?NH)v6&+O3EHRqsXNm5=pzyq4QtgI5sTOoOgRk?v5tpqu$vm&_|BdJU z@;c9(SRS0)C(IHL5Wo12%rCmA$_UI!^WT%;dDmuneJXF(q`q~r;s3w~pZq`b!JqYW zw*&a#BmKkyeDI-u;s8E){{TL?q43}N;6by*_lOUE_BtQjMbClkTIPe*v&84AUQfyO zdLH!(^1=4r!l3b~)zJ%mwC2@FXrDIfn@-NYKBsefp)6bgY_?g;mxW^`-x!e=wf1%Q zk=g!8jYsdH5UR;hH=}dme)?8B zW@7<5rt@6HWx=wz$1iRgzZfmjqHo*~F5WUnF)LY5GiS5@x#ctlTJ%k)CHGy6fs!O7 zNBczU+N}1_Il*TTkNaIvmU$Gi%Z)|N=5{^TrN5~qX5$AvJ{D^qy^C?T6e@Det0dv{ z5xhXK43?NeL_9UC%{DZ_p0Kx9K(aH^5ysiVZmNt;ix)e|-EeK!cHJKB0S$MH(oUvl z3&k_UZs4B-aLm|#fRB2*P&`h=FJ$6p%B9TP@a049m0wU!4KR?NJub^XEx$-kSp<=# zw)`ZS3u$2fp-}vR2Ifa#6gt1B7pGgT+@NVdm`RJ6{>;7hZwkCD*P>11k1Y~6N;T|F z2Usse=r;kXc)PABkpPpluwh^O3EcQY4}?Gztl-0%78Z(sp`zg*${T3V0v6277S{Y? zautdwFAS1o#wk=OG<~m?m~57M&C$o#^Oe!5S##WfT*yVp9|kC!_)V5|wvIyaf9Up? zBoAc1L$9~1`(erGTiULl^U4b`h%sIn?OwXD?vngL@vZSo`doKLVP_-cj6Gta++XRN zNK8ja!e>8EX+&Z=0)s!mFL;8c*9xFTUlxi&Et?Jlxe(^cO2gw}6I(iV8+Nz0B_CU@ z+S%F&aqaMJK3}H)!vOFN;GYh@v?*75l#~D_PpEcYg}qW7(QKh%Ss?e$PhYXaz8hePJ=_%Ft?8S8)gLudg6@z>rI~- z&}d{}35$^Q`;2RN4ssJ?ZoV-~)mUN38I9eAZ@s}f;WR=qbv$fKpEy6*FKHZyNnA{`19+$A zXXIgW4&yrk{Z;w{_%P(#3%EfZwhLGau!7!9z!1=1A%yur{gvse=((6D<)VBayM>3djG zjDcricB+lN8&MzEzALbkrl*D2B4UrP!$7mXShAh%+lLpfKxm2b?@3;3eZBa(^rrN`rC-%cZg2g8B#vj8Y-gCQIW_ARA>NA`Xvl_NRL~>RZp|Dlxt`_AhmoFi~_qb%R+ zqrQBcsKa{tsBk9dJ%6@lR>G?z-4l-J;qOVXtV;KkS>KiF-B(lNqdD$O7Znj^GTdVw z$H`Zni$o8g-e;OpATFcktCgGYFTuVuSLrYAViceBVB-qJZB&zoXeJjs@D<74ed5L# z_g&P2$XOugyo($+_nB8eq;JE!<(MMZPo$Xy@0lyV=V0(X9Q3)QqYA?>zLZ|pQ+4*~ zsm9(;d)RiSy0_STJ)VGRjIqvaj2`%JFfa`Ztr6$WLOMs`|T}n=f`Yx6KXP{kLCR4}_NAai}@ucUxeh z@>z&C`8IA)OVeXV4rsp_^j&8-mj9+TQqM33JsrxY=WmK`dO2TgAZ+}TWHbEA1VlOv zMWn+fL1IoAyu)CPe6{g}vDwInpLDIML2KrXWo*RvsC zTuAfu-{gHxH12i2aKi4+=hOn?MphbNEU0PqRCc}**rVse8eaa#AFbpB;@ zV9TsyscOUwjZSk<;LEqkU79gf<%?U%rnW`4EB-myr!9_R)06+EtD30jsvgMie6e3w z6(`?eKaz)r_GmFn%2LYVvMxDvZkRXc=Dk}anUAX-pvzhs2?QtC z^-<`rmOoSdspNkrW%$UX&%3SeyW~yDubXwUuOWG>nAVm< zX=!#bt?_jBCUjb^2pabYC&zi}mEER;aj7l5I)%LKE5uTl(X^8$O&8HqO|mu%$EH^$ z=cP|Uhdr20rQ%hIu%NkLL1*`$8755zc*i za3}#E#gL3-(`1s7{IPHASjdRZ+yh?96Bm%O?bF_6vpQ#e1vV35F5tS}oF}@7-c9tgUxE&|0oY(x&+V(kEXFkZ zx+SLLD`zqGzZzq@rZm$~nrSpTHB}YzflC9C2T{s2VDO;v!7*uk5{%ZdeGkiLisQFD z7}WVJ&lB5etJWrO)t*DYA)SvTNxfL7Snv>*>byR^$Ra=?JVHtZi#a2tkx%x6v1$*L8vtXkm) z_4wbzl%!}@`urymZxMXs5scq&kkT+N7ytFT{fby-gCBxE;vW5Um|?zD22g3mR(~Cd zR$KISR~s`^e3{{m>xct^FZef7GYkbs41@n~9()(EpyMAlZM*T}XjTKrc;2(wntX)g zh_e{6Z=$7_5ags)&0sOLKyQ`a(#Ew)tr7u-WdKrpVnB^AvBf!?gZm z4J3JY1j%D#Voi^h!Ac)bNn`8IVK}A#(VZe&5z8i~%uhjHWO12XA%RRw@ zK)r7>rIr0Rzl){#uD?gphNm+;eiM+;_pretJD#x##2-D!I1|grO;;B&K8m-*m)#ha z+oP`g9znTbuGZ(9Yp<446Pf6;;nr7X!5$2}c`!bn`mPG|5R=6LO#&=jN1?31`_SqZ zqaH0(V86kTZit4@3pEc(Vq=@*-E+$uy&dA5^7{4R&rb|pyO8f< z>xJ;u@n$XZJ@NK}@_M18DZiW)mlHzQRw5sv$cp2Es-+GZrY`bl+%*l*Ka45gA%;+K z)pBtKMFw)eLu85AEAt^9lsHul2EEC?8L?f}<-1ZYc8lNOavW~)(Dm4#euQ^nx=Cg4y0*!}%*wiM zd+Fhu29*ar*F($igXene@Jp+<4)FlvNa?<5>TDjnLfJZqwl<}2sMFW}MV+2r$uJJ+ zRq~Mvk&2LVkxHPiC7tdZ9M3~4MM_U%7?+$!*D%bj7;k2zkw~ME?nFvKN<|ujl!P=6 zX(Cb`k`XBjX&~QJk8=Sjvc69wS z?Qxo>ccu2c(6)ErtTAT&!|)g3lD!$j{CWE2E4w0?b`}`$qq_2<+jH3V2(~>hraeO4 zo;R$E4fSS>>B<=E#c5d>vaYN*Jb$~MXY~~kY)!@(v$nl6yq}wD2BxPe(cYsT3+8{d z3RY;zrnXN`oq77mKcBk@Z+5{MdVoA~n>I=QO^p~Gu#szmBa6?g91EtA1@qI!X}%LXd58Nnnoq11reK zR{^k3E3$L}^xmz)lIxffhqt^_aT;3EqeR}9m1=Y#OS z#Kqu~agD2pac0S_hKuKtMBRpiIl%)oS95&hU$swu57VD2}%HB~UF$AO@shR4B5O{0fc zK^zk+m;`RI?{S5U*`16TIynEXuwnjH_?Um?imwn~=$H9I(%W-tEcK>uaz&Bo8)bSW z=mgIWe(^_|*S^Y4V;^K&;$<9HYg6xB=og|_YI*ftWM-4NHv)6J``rTIT!5dLK>c`T zu5v=oHpv=T#9;Do=$#a-p*8;j((VT$4;{`!n@Zvf4yyG!#IXJ zhv*9Mhujjdzp&Uw{>)c%GsErvKyJU`9Q1dr&V~^^+Av)mVcnQ3z7Rm)xR;!^d}~R* z)*Jw^3@Vxm_YGFd#bZ3Dz-xM4z}+nOJ*e5d0nDkm#D?RhfYJ$Y_;kR!p2z}T62*)! zQ0u8$7952t*&t(un8bh1Z1bNyGw<*}D=u)uNwg5f)IEY1!&ZTN0)RsO zWsoJd+-7k~0MLn8xy}#ocHi2YYGxc+8W)_E=`Q> zc1QLKdW~RXcpuY9t&V*6Ljf+%57EAU%ciYtk=M%s9psDexA(CW2Oqm~da=*NNYq$ZJMAiFjP> zJ~dO1s<>sVuKj)uL|&$LB_+3c)bC+;$; zw5{!Tov6^-6{g`c`G`Th9rr1@pDPva>eMUwQOM_byT)(Olz%4q;2~mApFbw~MjHJF z7K={eG0DA7Duo~+%vXAqD)pC{SZz`Eaw_}Na@qeRt->aM$4v1ld2c@-|FxY@65P$s zT2&Qqgb)Q!;|&_?D#_UTFmE8^OxFVp9mg|%yN2gWQ5;jfWQ{CGRwY|qDZywShuN(4 z^c*x9yHC&XH3iUJ#0%F7^J7dj<0F@(@bcUAYYuU;DPXhQv(J> zFln%BqZuGyi~lwGx|;W+{*ejegNkV{J0I=gG~OMjxeE{hD!c|Zv_VFr5R;y3Z$<68 zv(`+h8WILs{*lk%DXx5#?cHm&>%Osik2%YK2g)*yyFel%ho_HK$xG`(jdiBv98c5p zG7V+SkdzEm-T9aMZP9E^v`X$qk?zu&;&f`&aN3%7PL=!0YYg?3;+Zh0MNTNSw^eTM z_IxguY*Z#o>CwxW%*~(S8tc)w3aV5=!=xFVlwj^MP zaErGb_!!W$RscG8=BtQZD`(z9ncNx}l2aCktnD_R-ezTN z@r)%JodtK^f$f5ty7L-XYHe3@YtO&`aT?n;<%B#j8@Fp|GUgF@6ZXcW*X}!x8E`C5 z*uiU32GA$>9YbEMA8>qk-!Z_b;&7a%AVv)h9_rE_?mJ42ClD#h$Lq)9P|>hC&}nbE zqM>StXlWNKY(g?Y7INU5ALIH3mZh+7Ho_2Am)K&G|=k z?n-2gN%Rc9oH6}AU|&beYpR2KPO3wNFx0cW-#BXnmUoYG+PDJuM@MsiGjQ`5)0(_x ztbc?WBlq#J<0IX^`$d7wHF9MZUaZ4hSu>QzY)u~ZV^^NewKwV?qrrn#Ox$ z5y+KlE*7eOvqSt>+&-`#gWbG^TBXj>G($Mfm7ywu;}7X+wJuTc7Qj%&v+uBrX~ z-6`h{=^o9~i^2Xr4pgPTll6~c`_obe zP**fuvz`z~{*>3Ku$`pAH0z(Mp-$q_n|x(pO5=FrGuKNv?n>$Rx_8<;ei_wj?%Vb6P6l|PH&p$EuP@mYO&ZWFz!S>M?Fh}TAo z3Jg}f^B_lUZ2aD9qag#rcMc*nTk%x6Sb|M9Kau&WbBBO~;MKqCrT1Z?U-KL)wB!4@AoMrvT7jOaZd#Wvtamd?aV(7=tcW6f`!bRI`rfKV;x<@v6 zZ9s|GcuXlgmAjZ}_1j_@c-sekNJ@Zs6xjK zH?WNT(W4~}Jj7PO*rN`)w8L!L82iOj*wW9^McD7WPs}1a#p&?l?L2o1vMl$xQ}y|< zyoqp+xKGR=HYT0enA4{)zhg^}t-k3#aWc^-68(24K+i2Sx<5aKezZowC#9DaG1e2O z>|>=IzJF)``638P|&MTJXGpuni zoh#Bn-AWd95_gAxvl;~uv{pVxCFH;=TtN;r0~J$|gIi*L#D0<1r7X3n(q&AbFP*G5 z9kt6dq+%0l%9v||H#Kw`QAUe(E@2JI2mmlL2R7zZ5pwvcDMneZmkrs#U6>E*d-`=Y z&M|XkA--XJRH7wy?r<$`R_?>AYT_~8B#7|=P8A$!WsK!gAWJ0id zt~h3K7y(7@59e}x`;9n6k-KIyZTycr*O#>&=x%Jfx_cLBUQ7@FbFh5}(-&HI=lXE? z?!$Q&nf@YXS~zX|o(YB~d6upm7@B0)MUT1u$&PyW13nK;h7cga_1*pSjLxm#A$r95 zvOQao_Drh;ZG|H-dXIX02n+~sf+$tXq}psj8ICXme&^WRz97rX*I;!^)ydxt;2odL zLCgO~h{$R9ZkYG2`{t1Ig2pg@NTOx$oKZJ8FL>jz<&y?tO*!zr9*0%H2$&T)~TGi05dSR4e?EAKlc?W)$-jB;L|sX6z~5 zf_9jLCGQ7YwEgEpjv*R{BQ!OhfKe42spvIfTuynnq%$*&J+T{VEw46iJG*AJV2kzu zmXg$0(K&if@6{LtTZXJ(Lp zL%F$Q6a|^v^+SDu(c#b+^%SR`Z<6*NmrNsO08QFVE@EJEdqlF)RCF)K8KRZG!vy&| zoTl%f>H7}Vb4LA_??ARfcOo7&`96Tx4(i1Il21CZB9*;#4n|_C)#}FKH9O$u%_0{epp}I zSOW-v1zIjl_Z-6@hE$nh(P-zdAHdvdQ5ie}oQ)p?AfQ2Dsz3kCZFzLX!??U^S$Ngs z3DFB~tM(mO@i2U5>+3UPC zR}Cd+*JszsTANxshYY_r4Zw9^=5Jv#t2@)XX9_#L&>X{4V zN4dB4KmrfZ0iGGmbbMS_`){wY{^o3QYPjfQxWaY8$!TTUEz%lNxfzvd+pDRBO zX6=1sV3u|D2mOzD;)9&g^uj#ZPA~(5h!(YH*oG>`^yF+C=7s+_miAU)K85=x%%vO@6zhF+nv*dy5!L;9&LG!x&#)b!+2l zf@)Z?%#Yr8nbiR=;jY7R>stYr5Op?&snmHhT4BBC*I65XmkD#WSE7eGxqD&5SE=hv z?5(W8c)O(P5!DbrTvWM+GVY|qK|D#ozp80)dGt;E;i}pzjkS%i?>k)@wQ6WY^{+YN zWrC`Vl0Q>8K2ww7Fc$)b@W(|l?yEVSH}@jseF!iZ)U7>YrdivMXYP&Cxu2N3VFMTw-@=YN!o-zxVbir> zx4zNUfrHZ0Qmlknc;)~+p?vp2pl0sTz(wt>#4YY~QY$^^)yKd|t!ZSpcbFzQp4Sg^ zw_i0H$3Ue5j5PioGn~~B=IEt^0@lY2t0!UgJ3^FB$h%e0Ldo|wW|bI+I-UV7^AhL#E&m7Temc8$W-jcSeP2vIe(I+#foz{#Fk)ees!oPn>rmjSDTXo95BzD#8oYA%a5HId+?w4oasJ5a_jSPlBwpZ_1*c@m)Z0z>O$Ep zA91>oWD@WWa%VwR|NH+Tl$!4wPSKXWB{j%;^$NR6_SYd^>Ne!?&)my*d{@j8iLDjEDNU zes0t1A8?6cjkW5Bf!0_yootO2evKU6F}OC(2gh`ypZl^C>h!DF=f4Y?0O@01R(M3q zloGI0UUdxN!QNAHBN$%0nfW)9rD$)6H$n#<8|vF@!`y$rzlm(IV4);K4Mnww-b}AH z3$`eC?;P1PBw6piHU|Yy*6ZNs!njWXhLQwwyY!8Xn|<5D2YB~DCNlI81QX)wy#uJt z`u8vW*lewjd{-QNQ4!o0f6U4K6*Lo-m} zjU!FZWs9v;v{o5Y$@ldQW&5glI7P?%4`l2)%e8ULyM&W_yXNyazVh_uDwx}EGwX=BC|3$rAaHNWML|8W$J2WwmYiQyb z5^oiYxoJUn>Ox|95vt&a+=>)Tir8o4-0=YPsgsft*l8(@iyc>}3$c#+*;fuBVCmEi*k|d50Rz6aP>#sA!$Io&a&eFX7AKNa(l*1@;)(A z!s5{7i`r6j(9Qko-SI14D7$9h7gmu8bG)xjxsha?;}tuU+;64fq4E(7Io&EME4f$E zb4|Tu_w>1Y9+3a9FM6hb{ZdD}-~m26+#ErE!2ptejv&7P9z92-;UrmI&AJaurb{Gj zCyPitzbS7H#2St5{+`WeckZ@!Zxf)P_VFE!oBZICeXZ8+&xNk-Pj`>*Xw3AxKM#C3 z`a>QNYPg6mVy__1SbY4Iw+yzdL0lBJO?;8YpB2`grL$#m8^@ab_xbfV2m5In`eOsu zWxhxcZKOYIFv{Rzt&vd5Z$|JbtT}MX0Syse-u{In);o*s+fwz7r%z@>Fp8XA`lds( z*M2u6%=Z@E@+MVnYv?Uk{5$@Rd5TW-Gvw-mhB{hbg;y#9adG!(qRT_Ab@y>$vJs*q zaSS?>BY`%!jw4z};wYR}#Ez*X#>@4o)|E8Uq1K`Qc{DEdAi!Pvwsas+UTMi$S0sy$ zsAqgHchs+m->brO=}?CW&uI7z1UP}ko@u${$e=0~!OmQ7`MkHjelzqcjK`27%NtfB z(j^z$KY&p|KJ#X(CbN%Z!A_D3JG+YT0H_;uF=*}-<7SMZ{L zh$pdDR=WbW=R@xa8L>`d3%P0kW>kdCB5wj@8_Zk>K|0qSax-|0LAJvH$sP43;X2(H zwoA44^NQHf3e+!zm*62S?bH36bsjasSt_0gJw6SZ%Z6|oB|yv_#OJ8ZYFMJQot?Wg zeQ8D1oz|D9`?pw@K}90fj7Z_`1G9`P(UiDDO_%ct*z#M@ho*&~k@^hVu>DNae)OTN zjhRR*Dk{MzGJePh`sPOLA9$=gk+G&FMSaqk{~t^ax&6^!+z%9C-o8UGDA2RcqW^3k zjL{tk{KhxZZJzCY?GI??0aHL&K+tn*FS?J<;9|)V1BicP&?sJ3E+7ERrzK{lQ0eJX5gXmr?3dvr6n)rRsx2R#PUY03NU z56R7@Q_@0D@-nh7A7IMQe2eSA@U^WiHkioYvLUsmeqF;@qLCx#f^`m3VqvxVvJ?PzN1Y|@U_A5N%mP1wOn zgOJJ&Yj-eGzKhbfYMpmn4NjdRNN{f{w8Mt}{>|I!UKv(vXN7Ci$p=#vy)X2WZWV36 z*S&NZ!kjieoN86$U9<|(+GPq9GD{L4*4F;4=W7@cv? zN}`k&Bqf`KO!i?YrRyIyAaD?`V2%VnitRrxdKU8QC-_bFW0jVPHmmQ(HpujhQ*+wF zR)`6Dka0pmqh=Y=prB;iiq{1@Le&bQpmB%_8Z?(o zYL+?_f`SIkOJ0Y9=GqJG4pBjaJB5>8=yZq*8Z?_HH9uuv_`0j39y%I0_&M)9Tka4_ zm*LZn7#LSV1Fd|xtV)(1l8J;ILzNe+5H^P4hg`kODEsIsP9Y4#1^Y+Fs}q+WUb{Ru zG|`%QeBv@=;u0Ah*hu?_g*cDlKzo4v3swC_@Gkp*pA?=aww1n9Rni$2=}q?Lw?np- zHwzK#4cp2dVq1CiZ9MOM^zD#s<&{ETD^U(VL2M|EZ-Xp}wv|(bK6n@@4*Zt1N4|-6 z%+I;~?Vs3I8s4@)GTFAW{cWC+{J+~)$hik}*uHVh*t|q9wfRdQSGX8^6_dMbYjR9% zvOabY4*SU9Ww*htTW)(Cd?=o62uF~J&=N|r>xziBL`=)G^*bLgFYc}{Mli7WdZn}F8vQ-uXf=);nz zL?_Ohhb=Lz#i6vtB(u|7_{zZC+Io^3b1&#IoU4Rg6u6`)P` zBIKbzem_gn1yeiG!|a)Eyt@!iUpT~?goHyE(8x(lBp>W3_R)u*31=ho;nHh1gO^LW zm=N6;5*~r({1cl&{8*VJB`U(cq7X@Cfd|utT)CsbgDgq(SDat6sEp?&xx^k&UdU5j z?asWR4P1Tq8m+6TzeU~VZq6Hm8m+A*5KC;7s364M4nhRD1XfW8=2kUl4#7{nttDiG zflGGg5Go#w8)&?(u;~mcsEOWg9wKLJcauMcYDvILsP=O3Xw&ceo0{(w50yx9M-)#~ zb86whKTs%!3u{?F;&Z_t%Ne$WN}dW7;7YVB%z~V}k>;-pa0Gmtv& z&!`1F!xG9zrS4gMICgaaaRtJYJd za2_p&3@a$g1f$FkEb@(57P;7)peE-N0Erpq;jbnl;gj}`AxHypA-b~#1CPVP!iA9x zsEYwJ@oYI%fV?t*<)Z>DZzZq{>HcQuVoSNCacB~|$j?im5&H^>%_jC0k}DfN#338Y zy_Lkq@(68|ms%uhf%Ec4Y3cQGM>S&H5qN=Uuq={nT7NZ5ev3SM*(!TuagU@1qIx#u zbeCjdvR+6S7E#b8$H8O#j40RLf6{*7Eb4$-n2@!ld^v)xzrDc7R?+tTXA#s{Vy$-| z=lgu?UQM)dS3w{W+hV|e)s!F;>@EL+ZD?Y;&EB(!2S)Y=cvRRs&xY(R#QB)qibL&6 z#P*8z7CcvyA=q1BsM}iL`!BMmbAgh~F4<);iE^}^LQKn7m-^hn= zZTFiaEt1@nOr*r+=%viR5G+e3UwH*V(x4 zLodPti(v6OMXn#SC>h0{enoEoY3ttjn+6sa1meUz#@}ri2)o+Ye7;gO;{A*Siu>Hn z{+pNmaceuS%YQ`lThE+ThVSBS&-24@8mx zaT(RWPF=gDvij)7E$Z5JFrc}*C>S}2&uv_RZw;aC=ScpZy@D%z#ZjsnwkX#$YLluA zehFabZgYkEm5pWLTr{A>N$-|6&punnkQF3(mDA5ctMA<+fzu7|y(vi50iuHsNRlzQ?pVC&0ZecXKcdWhyvUUG>h2#+TzJtB18yakJrX`Xm z5oB@W(UOYM@xLl#kCte^uC?MG59iqal_mA8)}nnN>%5p7(o+R4&^| zQ4=$Ic~EO@;v*4fVy&)=)S0aQ4ybL3%ADs-IMDYG?AUo<9@UeLqrbM;>ZDKaKLlQb2G2 zG(H+xgpk>o)b^v5#}0e!a0o1Z*Wvf^UXiYC0V1&nu#)z?P~ z7B4^&uApxr5!iN}0rFs=wUN$^)`5BB1|fnxW|)J3I4i0bzaKp)wf`kQi`7de4q-1 zM=$MyyL3o<#>!&BV6%$4SiMqIvPb7gp|R)l7a7xsaO$>Ttt2xnmS}U{rEC1cI(A{L zz%MM;0R|>u@@y-2R<9O7qw4A?}DDk{;TCU>I;VYMBV1)+(VO%i&Z=- z`ivQ@hDoM+U1L7ClduUA%y0hh%X&826leV6gwOhgOQQ8ibi}6o!?#UMbBIxyDFJWw zHLT2YtG&nr-KZtD|r(>ZQa4DyVQA`7Z{TR#LDT%$Kr8HIN98z(}y=G-&+7D+9$NH&Eq zFFnfPj^p7UzMR0r&fHLrId8u2D^h!CtzZu-!*X7ePrh8nJ^Zib6Qc83A=nz5@3lE4 z`7KJf0uhNWz3yN(w-Z7o4zuK$rQP!Xqt=Av?VJ z!rz-hYHOkmTL}AJmUQ6Qk6CL3`(6hL7J&9ddM%H2IAV{!O9fklZiK^cV>Crg!T$um z_6+I18yomxj4zWme>bN4X6(}N45-w(Fu!-~@5=YNppx3PEuf^mPp=6mnfa~Xwtik+ zJKeMQl&6f{^@yjV)>B5Zj8nS7v*<#`P}SX1-N)#TZT<*RvtxL_Iz2L|WSTCk`~Td3 zNl9NEZi2qZyMN96*4=;jpWZgLx3%B9&+F~>dY+NB!7GAo>R#iS0*^X&IGc+tT|#ln z!Lc!qjSH=b@6V#$V@A@+VdsV+-N`Y}v*d%i!LimD3}W1l;r!!bqVtpsQE8!fo&956 z5xlnH>g=&m&fkTeAi-&({r}+DwwHzb;pF~res;fijBC91e#6i1ca3ek@7nwS`Lp|8 zm|d>D|Er(fZyDS0{k8Y+`Pu!ZF)sGn`{_feG0wH(LoPkhcZcSQFyU<3Hs;;g zw6hTf2BF(U(OSrT~RBTykL-(nN1xEl?YfiH1F8u4v+uek<0($Bn! zeyV3`xLCaD47+YEoI1+@DS$KL^GxI+4C#1V{i|-;4nui5jYR9#;ApJ#5^tZ=C^wrV2j|;B{l{4zA^YTvUzU0>l{Zx-#LvYb04DNlv-X%n0*=+sOg)FJ$*m$gwfk zfn&0Zjn9lpG|qPjX+MbmwUH<#x+K_r^{oaFEXXHlfFd>;0$@bE^X$wFKH@j^`5!z?tuGuGDT(vWJ~zSNT>tgYFM0s^AsLwW|6 z?=FNE28wLKmJ$8IpU1evLcLj1kyD=a9HD(+;R{0gn3v4HAp(v!*izst zt8hTOGRar=Cxz~Se5*q`nP)@!_BzbI9sxGwU+6#8_?qz>y9Kb3#4nCXG>_W3MkuJS z!3HsU*Td#c=wvvUuJA=|MDvm?Yhk_IODMwA%$;7?0{5z#&6ZMtJ>p z0q?4)=(S6UZYPsA32&!pw7TEgLlXH4@|K&~_EkxSp*|zLWEpv96{E|-_@gZa#>m1+ z4$N)|lEmnV!TO0)Ifb0-};qbIPd+O(&`0bkhJFfnq0WIE9Zje(9;4GUD|Rm%Ufr zU;3t>>h8KOup<_goS-CaIviel`iADHQ*ABhap;Vt;9dwN$GNZOB)6p!CCH_`aV1F0 z`hg#=Hh%fZ2bU_R2zroi=s~`F_2Um*x*L-J$P~`PyNRV&Rn5#PUqXLd3+4)iU(;j9 z;t%c4VH%Q9IBlr%ctNq-CaW5l38m_Kx@sV8y;|@GON4$kFrW<%B#sP(pC6chX+Td< zeEV2c7iEd0Alt8FBP;)$=R*Q;)L48A@n=$^GeLakHWH`oil%CuL}6mpR#ckvs{74b z#+)xN^PnnDH5~aLx1h9^HQ|k8l*K=*xG1g~f8YieQwW`k!uQTeIALOiyHp3>I*FC) zZEb?0Xm4zEb0E)GO~P#t3njqcX#A4se!l$R#7Rym=u~tEy7LB}zuFZx;(Z%R6-jrW zvhmB-S3miH=v6*wc@?mUYlU*9=oPFtQ6I+6Fn(Q<9wxe*cS(NcZQd%0-Wui*pGB#F zPfPw?sQ^2bmwro@l$&Wv5DR}08#DH9t_r&s$xOKYpLHkch64lBasF=a)DByg$!yI% zlA>Q)=$Tb(AOXi%)RC5D;TAg0lFwVblqH`M9AQWWEb&~PjxKfgA-Q}u6WT0~k;~7cP#_tYh<-+YrDM_cUBGd*ILV$IO{4N{P~+XGK*y) zQ5M45V4QUfDgy~mTyMWQZqcw==X;l_4J-N$bG?QPuVKy__~IH<3&!)OqU5Dz!C)F? z5n&sdV0^5Em!NRH^5zmqN@+uF2p3fIjP?nI!DRBivb~W{|{HL`MG`z9gyJX zTD9n(o-zM%1v!6VksZ(Z8-H1nNBtSXa%B-h|*iFS0|w1mo=N>EZ{i<+92 zN8KmL9I|cSZxqcUtovYmE}V zUH)W!Yb7vrtGrKow`wWZBfr27`-aCp_|4IMyM3p}a$elGg-i1-_)q9Rv3Guax}}m|8JGHzUg_SHeF8FFmYL_Z zmX*^@i*tJv2)2bL>V>fltSN$WZxXc*@sC64fPo|Y*rcF&7?{O${rkr(UBnejXqWJ? zFpKSbCmN+Z?8{=K;08;cq-mZW@8OT*PtqifW9UgCJ(2Jvt80bG6{*e8>UNLIUeL!r zF^0j3LkoR9f->I`{AtTyDu3D%7!+H~iAO%RUsI%@%XL>Q&r;~M1@92$B|Zg- z@xb`S{o@z+jjdJ+V>lLi_E*=2#6_ZK%hUw%j`90f4JgJnmCr=}^F@n%8;Fg=MhX*r z{VIr>bM#ddCLn@m)*=vkDC5l}@6MO6f`5zocub3Ym85+>Y2Wr|w8QBOg$bM!i5Wo$ zkv2gR8p-FcI?W%V7*~&6G%tf8h4S&>Ld?g5i-~+Zia0{ijUb;Rdq>U&y zEnXndhVVr`9nn|D3i`@l082PV26LEdkuQ$4YlQYv8KEQ6MZRd#HdSc5jXWFlt^5VJ zk3|(vJV#di0uGb^%5%gZp7&A9$|gB-r+M8%l$A;(G!Wup@4H(6Q$)UjsH0fG!>N>Y z71N<8!t4AVZ@gF!nYb0dJCSEhhJAZyB4{`MH>4n^7=FV_cA^gHUjgNmm`LXv3w@XH z9qIu27iWq;;8W2fVa|Vyal{1?Hdo^pV^9(uc$d_+hJwz|%y)h^*8Q{x5fUouK=L3_ zi1^H?m5Y!&9Nop2T6nm^L+{?ywHar1Ka!t&??p_t--d8&iJw`}!n>ZzdoRZy5g&+% z^ERGG@Eu`X-R`Gie(>$J!?^t4W8SXt`h%P6>+kg!QLZA!+jXzAIX_TD`-`B&nK)&f z9^;;#R3=r-J?&lS8=N?AdCy=?$a%F>JTo{u$b`w{cP~Vx7c%*PIC&v|ql+c^r}fU? zF2rdIsQ9#aPe|Z+7xcRxMG}myf~D1YcRsWjVw%Qc-S&mPF7i=i&_^Q558+y*`_F~G z4${;nG<^~p2hj~~C!(!mig9&5@gE3zD3nQVQH?vbVi2n()p{AH8iaZXBF6kUHv(~8 zmiaGc-Qi&t#4EV`rmXG6jyvC1Za;9F9SR;i7csr9rPbf!&ui?*;cUnJzdx1rsdFUP zbd*fguO~8q^AS5%$*tIF?e1{#Dnm{NgX8=1 z?M+!w(}rgrQq(v0FIF%OZ{yrW_%HEMAiSQyJ^qKz*M#Imy1a$h-kA686K9W*zM!O+ z>GJtu+S3Gf6Cp>UI@Q)~q$aU6OhzI&ao%&=wYl(u*TP|nw z3@H><4ZN?xuNJ=z_!@elS?-H&*$L|aLF5<_aEfT-U zd~hlLz7;>%sUa2>nJsh)Y>GvjEcEhK_9CY_d~AJX8N2b~C^uO8M8>8qxl2`qiJ{2R z_sy^rA^o1pSov4WR$1MfGJgtD$l6c?=|RHd*v{XbcK&%RZExe_sB&alKD}`>)UeiA z=c@y$&wCV!`bv*A8oqI!<;vy{O1^6*PWJB&WtsiU6=~j0X9$C5_FHrJG+GyIqB~C)&*ypaMJ}x_)j9akhe* z6VAA}Abdb57Dz6h5p%*3wP*a!kShjK5lCoWB2*^yXmwAG30W^Zq*=mCgvx|y7V;Ad zjYvqwl6r$^d=gpYX?#OyZ|5ccP`gm|NNDWjB^{y0$H{2WXp%go^APTcKTR0Z&{gBm zRnIs-)(IK-9B6-JeDpg*EDA?Z@f9$z=H`BI#OqqZD}LH?;h5OcTzUwqTwI5~_{>#- z1%}wAQB05mrH7E3!hs7R1s}Qik1@enjWA36Y2PqrdY1A;5yi0q!9;?Wod>RBkT{y* z2u9MY{CF$!92n+KNF7P`lvfNHYF?2@3Rm8p>${ye=rmr1qgKKz#8HcXrQRU~!B^+{ zN(qrds*|#T8Lv$6(TZH3owRQw?cHb4UXmg3(ObqDANc5!YkU+L#3C;cKFVrK*oqbE z`W54R6c-{N#l-|4MG*^L4G%$k%6NAxP`CcR#1J2C(V&d1w(;%k~$)D3T0RA7nojp*w>X0X>l(>{k{jj=!Nb3?Sza!~E zqjrf0Yeo&L>vw5;U#|CrQS}GSu6!zxPuKT;UGKivl`myR z;dzGACPqSD0gYb-edc14H_b<7J53Bjf8!-Ub4CB+3ngD+KLndZw}|5eMp;O;Gca|yTWh|qUN)|(^?I@_p%n* zG?A|?k~c^3=4jqL4MuB+Il^RCTg)1*LyI(nX*E?cD$V%F2UYo0+CoP@LYS*ve>+c8 zBQzbPnE);E)2xS<^0e#{EnljrqLp>DqGF{Pz9jIYcbF9pT4kccO179`)7n_AtuiYw zu237+nJZRkt7z`xFVzmS3eO7LUR(@o5nJKK#bGT%Et+uAt%Z!G#YL<3+_}vc zF;re%!fP*%sXu9k7uGAAVa@67-Hh~qO--AjtG;+~^UCeYFd|5Nt|(N(k?@1Iu}3O% zNH4t8I+c^(-2Skc<8|D~H7AlOdc3%+qcu+#SfJnn?;A8!;)+M2QGmtn0 z7ZRXMy_?3h^T9Ijp75Okl3iyB-Td6r;1a6oa`?rIU-u8)dua(1Tp|g|sDO+|EW ztnMAw9@uV1`WRdUWYABr=MK}j&dX!-ULY40&y#<_Hw;I#OHAI=kaR|OX7mr4gZXsR z>F_{4)!+Yh@4h1lyqUK(Zf~tH8yez8ZG>&%_8CvQK^|`-lN9e@UWHar|@IDjX^oMXH zl{UPu=49vdDQ}kY9%)%KI@zD$oK=QCMEV1M`};}sr&XXojoL=Z{)dbSWdg0rapPGN zXceA)OpEg_p;d^%ZdHR^fcRuXcA*17g>hOL)R%_C_1yloU!B?$9SBAkBS=$^Eaxy% zFC|?%wP%NUYMCiWf>Q|55XcyaMuyh3lFD-K(U@hpJ6*U7^sqTiR%+MRd@#;Pm5oyj zzCg5bp+3})E792GsyB3PHVFp^gZExT*1aa1#1v%F2~HAC8TEPY&3#e_ZLs81u6#PL z{@y&>y{l+fKGbXy1fx6XIlG>I#1Ca>TQ|4=!bhi~=h1$Q{KJ)KGIZBhyr@ON-oKqP z{?AHF5b5DTL+h+aF<`E<(w5+KG}O=-VGfRvqg7Ta#{{B*1p&O9<8LM7mhzqQH8=9g<&-snLTHYk1xLdEQDwj9=M|A*yo^PDg=Ke7B9T>8LcZhR_3A>1c34{$mmOC6CC}v$=`HtII z;&-(<%w4Ux6xIqdLp3IZS;I2Ix~mlv*xQ%ipvmOo2YnZwr{ch93fJQo^k-d~V_rUk} zq|Cqh#r5d{4g10Qv60i?VEetf@Wv613chApx$&~4dQR*6Q)u#GA8mTtTyxWxI(a2J=XLzF1cnzD<8tsb7 z<`a@-%dDd^wpRUycB6312S3SNU?J%a`)yQeGqD z%Vm1_cMJ|J(=h(bSt-t?^BiwVF1O@qHm%YP93IJ~Gufi>JTF9*AaPoeTU zv{*tcB%bj$&EYOp-f~My>{ebwRq$Rt&m*Ie4}5?K-Xgz`=_9tpLK!v?g6dRc zxc=bqdbE)=y_gFFt#=yf z9wmwew#d1--WTEJVgaB4E*$gFRPGg;@Ha&I6<##fNV$EU!uIA>IW@|zWPDPErao0r z)`{Fo`?dbUPB-0ENW3zXh%7}gpMq*pAEe#NyH)P29%7>0^*5W8E2xT`P2`m2vl}E- zncVL~IwVscdxpii#G--FhgHqyIZ|g5^lH=d*#Mm$=L&$2`-T9oeh#qVNtN!VMeACa z!32sMn)WGKd8}vU;8Jc+#Uby(u#vEi6Hori71p`9Mr~uby9BEh$(tjCe+(sGAHG#S zuokg_WW5nph*LJc&AnM+_1f4vYlm5zvz6^i!4&H>IBZv}^VZ0=ZE?vukv^ubu+ugN zJ=qw1QRvsi&F40tg;O-3a}FMHp02KMhD+h2Gf;+N*Y*w z5DUJ_S)1LZ2&P$jSc~^c9zrQt+_4mPSTuCynrzET+JX>Mxn(6|(MT*SC9uC(R&mhxut40D>f&mLhCW#6SSfdC zgj*{W4vplD+_6&P(6Ek`Y#BqIUi-G1JU`b_*nu>lLKmneFn8liq$Z_vVfKJ*tW43z zI+Dl=peY1Rg(Y!17YA6rrPecDv;f4QhI*xsq?I6G1Pm*0Cg9_fucr;#Io#zZRhwED zaziH~?wnRziErvGOSJ?W0%0B1GfQwrT5vdC|I(9%AP;e_x1f2Oep1~^5Vc0uLRTeQ z0^Tbe07(V)}$ zphHO1&GWa1VDJla7D7z#-?Q?(qk0GsgtibI$^%_ViL}W-T?z(}77n(W%;%?ky70hP zV?8vt%_4!JXYFmL(wvae7RM-XeyO|Epo9*3$wEvE2~$X!5}qfOHaG_AKn`>Xk_5+d zVS_+yCVnO+Z2tR_yj`H8E`|TSA!qJF_|TJ04``C|U{GCfF?lPzWl~pxf7oNvP@ zECe$91zv9N&jO)DLSgq=@FkzSh`SpfE0bbD9ZC7KR6T?Yphg5Y%1IZuskmbn3+1q| zgDn0feVflN$t%DfwXii73ya>NLv+x_xP|1DZc4Zv(7o~EEWm#Vxxldo_Kwi^egtth z_%{5D?L76!#do>5k`+z;1;}jKZ~g@7?wa7_XnwL7 z2P4~ZLDr(|t;Mz#erY;z*N*|yRD2@F?wT~nOSv2ro=7buj#A`v+p>O2-rPvdsW|6%qH2`8Dra0)&C#D|&WCCA+`S{4RO02K=?^4Moix2wj#@ zSzuqL*A!XL^)Y~pz`c0+r^{2`vFqjBbnii+ltm!$*aHl51#x=4(q(Da4dntG+@d$x zOspwr<@Bo}tpsnBV>tMfz)*Um5P|V7(Yy#aud|W)lrcTn+4*@kGged2tR_z8z9~gm z`GL}1x{h41=?UB?YkIQ) zGdMv4?el8P=uHo8DEY>yjeLV@Ap4A=HbP$bZkB4(`)zk4T@;)=%yta$#XaXCjeTrL zd25z#ZZ39`o|%7CAS{dU5(*fT59w~c4zbA%fk|S0buS4p0S--o3Kygwze#}`kJc7UkfSG>dzvU-r^ZV#Nk zW9|1RIVs5PIMy1EEtpJQDJt>X9|&zlP6>gg`!0{69SspmQ8D*KsXPuhNC#7Wy)SgPp zZ`48Xl~Su!zVzaARcg0xJzZN{BYO~Hw;aKLjg(8)&Yf}%U518i$04TS2@1inUV;W* zkPt|_NF7+*N61CZZTNdnod{&DBcFDJuEv=0@^y}7D=S(+#Rb-=!6Cj0=!hf(ELogtRKy>Gc zp1p3piDXA<4fmAJZc%V)p0`z=R88pZJ>@Nmp+XF|r4fe*sGNrN=+&h|*fPl{Mr1rh zLIL=CdB6)_7t8oi!2}B1Z@lO(M7{RuEvVm`F7((^$f?{q|9aYU?2TQGo@4Lt$_Ayj zHEt!Z*QJDBms4)qK3KGKF49R#9r^7hjPkEc!#w1t{Zk3_%cZj$!YK6MF8o)0_+Bh3 zqswzbeHf(+{9eX^9JjB-uu5{ZMt3W+BtwOSt!_tIb%xB1$Q*z#_Yktqlv-tavdjP( zmYJL@ub-lYOmN!TMMqB732!V8znsWJ?O@8_^%Ue!K*P|k6;~7TJL@d zn8R|mh7_uKV1Ad?m5S`+IO3(W+6mU$Ielrd!c9-B33IU>$#88elOZs|jm&f+Zi`P< z7yqqG>9z)Hhj%;Vt$zTBw1p`C;yUw>Hi_ zaFP^q+_6BrH||Ea5??2u=1N}B;@hq$*0p>l7b63o1@+Ey71C~9>04^QjDE3}X~?50 z4~o8+jZRdb(w(==azy2xiG55d`4Ma%(~UnYUJE18Dh~XszuqA4?5#X zO*v@%|?!Ac2HO_&er{ILsB4$S**f76rUL&i5+ zsaJLL!&+Zy)yB2HY8exlKEVx7I^|Dbg}%ekv;XLtxEHwFJ9nMrVu`$wjUktA4ihm$ zmO`2P$MU+pHkB8v%gyhRXGtbwhC*nWgc;a|5}^%vFc~qf? zKEJ4Bxv*|e*msm67rkZK>>DqVMYC#giDVP`9mWUey45xbHxtWdNwjp)WYvhoWv1sH zq;2c~H)gwYq%%io1HUzInoHIxkpi~`7a`|ntj$iFsL+KxB&8iOvw543_fxQ~@@2F2 z*yA85+>cmxk?oRmsq;ab);n6iQ;f$bX5h9(~!+EeBO%V{shf_k#JQKaA4dXTI$I(U>v5< zNvMQ5C0{?M1RJ+QnA4+VP8;tF-?PrR>F0B50KE)IX$&r4T@Z+(9Z^h^k9929a!D}E z1(wh7ET1i}$pfXSPRc2h^?{O*)o&C?$?BXQIZ8D`>7pom0d%Aen(T=a%zBeP`410fPj ztO_B6LD2evX~>|A9WM(>5m*AqGKDYUj{IY$@C6FXm3-e6u5E9uB6&T7vd@F?RmRie zw!t0(o$UsFxV~+FVJ8)gl2rLdPt2QH8NYt_yrdUv`9Ku=f%J!})8D{{X5B(f(K zvfy)1xx^F2a%Vi{tVfFK=n!9$rthKKo)@Col&4_t*)L-8CLF0rNqt$4&qZ%(D|vpP@Z=0oZl{*meQf_8YLVFLy&iuy&LU z*yNnP{slsEMVLXAi$MsQ+_~`RC1UBoU%n670*DL;L-%zsP3M64GU$1tXpHeK>)vdp zaK+eQB@82kwF)#&_RsdyjK%xtiYjl5%={nOer0E7ZFm+!bj0nn;9Z#&?|PKjDN$MM z1f%I;;xFTK4Y`075idaOAYMR6k2eL8UEFL9bD@9$?dXzurqjFU-yWRKytJS+5QTqB zcF(^B?A0?}vitW|hzr23DB3g~xC9&%>^=m$fMcvS;g?uWeW58rsrz8DHo=dw$ixa% zE`udT6#pCIFi1DPEd8<3zXV?91qplqs@kh(#b&z0ZYnL~1e>wokxhx{!b`M591s4`gUzOOb(4 zK?MOxMbuh3PZplLPkq15#?DgtL8NNq{g6ZNk2XeU!?Ge-@UC#Gi^V!}N|}LjhC@>> z$SJUXgrP0Dm?=!7rd26~*Oxi})NEYvuE6mKbH`12wSxCfO^IQu4{EvdDd4D=zyU#? z<0A+slwSXF5x)-+-D)Les2?>h&FE3sBw*oSBMiib;iz&7Bw-SF6K`83p(T*ZYWa@{N+2*G6D0Alq$pX5N{kwM)HTG zE2(xRbP{FKZCgFkPRJ)D5VrsqB=WQn>6E&ZaGM!PBj<8O?~!n#GdM{@oaI#hg7!)8 z2cCUxMB0gznSJ4b@%LMxQ^-;d(c7LjC0K;l(P{0vELl9~kaYGR58tzE!#9YrapZS~ zAei-)uuTRfAX37_FyC?MCCz9W|FWs~O11?TG2_ZQjN)#9#+HWvduve-#d zFLn#`rB*bzAb$b01BBFwyJamisE1vkMFv3=W(HxaK+CM8C=TFl#JG|2*1CTeB43lm5yiM zt7AF`jNg^440l*MxjF!qkPRpyiUcJ@p`0?lmiaST8fs3&%tDWFO(z$W(xTYTO4`9hCSmszQimpG zN0iQE-0b_{tIFWA#K1C?14wY`XLaSDk@d;n zCT7ht>05N!+*f*t%@q^g_ByI~Ir5j4jngxdGl;Zb7;ooluPM5IU>%ZW(=HU*Uo-lm zmkCFVB!nz39DxlAmfd?DqLivh6ud?Bg11P5V75si(gaDcOT<)*WEqT+iCR8?8CeSG z9GrhLV(p;|lz?fhGP^2CHXid^#7PQ_3#z7vpc-4P%G(m&Vm2pb?#aBiGUAy-R!8Vk zkFifeY~F;ndn#F|l3L7u@3}xM9XNe~EJIF8AXYMd9T$ux3wCH2iBPd#CvsH5SoY8n zVYzOGE=-jFOaZSl=+%<({LUz7BPXGkpkb8(EhwmZ8AR2`b`(*m{^&$Ey`xRzkJh`@JKDnh(Ft4Hr2goXmD7LW{MP6wP3ltA zmFl|E1S;bwO(|ntrHO7eb(MTX^& zE!*}QoXAau%V008HNB=XC1`;E(K#}cY}vHGu68an`hMrgQuN^{KED3oEx$C0>mMzw zf3&dv(Zc#ill3P)LuC2U2bLegOyROZocY**GNeF(Tuanw1SgJ&diKg}0WV|%UJ#1F z!fVUtutIUUv)BfCLO6on7yy}mXK!4T@elLJS#}b?D%^;rLBXGUC_kP#9o7x=?B2sn zLoIdSqp{v@_``TrRJ^ogRe0&WvCiMjb67jw&`1l^D!fk`zaLvhFPk7IFOhRIG=>Kc_M@Z2^pzI*%t-Wfc$9&Lj*%7e$hUKz_2F2Uo#P(dr$NC)Av zLG*tZx+jSe)KyAwMmIeKFOKM)yYz~2bvtA}qHZsok55NJv`!0&*2`zRrISVL>2B$e zRS>P?yG3<0+4n?XA&Nza22x6vBn&^k0K`_MShDWWLRps)^@&4D z$MY#q=t68Mq#OSUtg+#&?IC)75i;f_QO>M<&Oqpeh!@%9fCl7f9?lQRFOW0Y&Rkh$ z?F?ucxHs0tPOFRocySu?=E4?Ul^jceE~AFj@(n;C;Spvq9i>`_;PYWfpCZ`f5CPD5 z2ChnRFZhq$*Q!n`8VY!wJ+ed3$8&3KL-Cw{Fg$QN5@S5!H0O|pkqpBtw3WkSwY1CFJsa?Ej1sPD5yoJt6n5F8I;y40X8AoFwSM!Y*^|FDFzDE%sRs7Q<{#Wraat=8% z*%nv{=O>q$;@mDX?bI2NY{eBbrH^*mX>QonKGkJs){YXJA$ala`CJT^5l=h!&lPww zV)F9A%3S(*Zl>t|;S4Zws1IkdgrG|G!7-pw2$}!bhaD&w-y`5FB+9M<+O|rQ|y_Qmz35+F0jx zn3Xf1J0mM8GspRCa(MP%NEmW?n|D6sQBV#A?J;W{=17l%alqNy`^2H=&&Uq@Jmx5e zIXX!GPU}eTC}JW1Xur^4~xU|(9teB>e|is5t8K`zj^w( z?hYVt{LtY8XJr0kn=Zr+8JjO#o*BzoVTwWm{yZw+!@ff31v)dWz`}3)Z%C*Ee?&3J zaLA{|*Kg+TggBcANA`rG5I`j%fcDXyZ;r#$_=yEG7S@o=Z#!qTm?;ZpsGuxnl|>=( zn3WbYhpBQ8k(oYshK<8a!!AS&X3Tz0(+`f$IZGZ2#^B#`QCmd)+5wJ3uz@Bx9vf|xMJaqz;4@ozZ0$=vZS+$|6U z38gr!C%{wrdIWQ?PdU$WBbk8+oTUK~Gh;H-eRO<0ak&y2XfDEX6v6s=p6zga9$s%c z`lG?K9o9``0RonB@2wpmA0oJ}z(iaUnrtaE?b4th>?)Ur;W+Fnmqy~UOI)aDrjfer ztjR9D(1#ZZUVca3)5yttkFpH%x8(b&WA-oF9KVOLJt$P;KI}6&w>_Q zBLk;?9M94c^ie?giEPx(1`9W{sSTtPWFV;Q>^-6l6m=euTR7!-_0R)S3wQg(AB<(< z@;&p!p*=pGjCeO1Nn4iKwg7EwezR}M(6B`r?kXP zG2bQVp}ZUKGe_eVo!cyaD?-? zn>KsnFWJ&><(JI~eAm!NTvYwa$BsyW+j=EBG%=l=OPdgGJdv@7xlVUF zOAZ7GS&njmMZ#VKZLQxNzlvjaWGi%6u4vu8yh3{8#fwCqM_sFe*$1wm1Qb`x^T1}} z^@s2esLTB7yl(JmOMQ1j!24@HNRF!2o)3L1%~+@OU7aUS0I%@=+}SY6aW#0pzFX^- z;Bm3)mdpF=9n+^e|Byk{nMCxpp#wOxdJr%2HSvL{gxj{wa#UZx5-tzo2Ff#^LuTiP zv5VY_B6?4jy=(Ts*NBRR@oX)=I^w+-2x6aSt}Qso+NaGfeV2lK?)M(_q|OB4-^ZE_ zW^P06LpI_(e{8|pKb>g)&kSPkRt3@`{m1TT)j=9;(fN<9L0~EIg^9#l9?9`cU` zZ1W$BOgeI+`T4wqFiEcPTXVXk!C1W~t%w><@cX3XSxxSXsWL8>Y-K2=J=W}Ot0{sB zMo^~ZX(qS|=-@b5)IZ#WP2C?fV+GP?My4jF&cUtHZOL_h=G4%ac5s6wmVH_?JD)6FtilJU*LeIU4la zK0%l{mj?dou`WxMrADVFr_SRw7I@CftETFuM5Z;t`|eDbfD*j5i?_Z==nMSn4$cDY zGbK~pog$imOaVu{-cgLj{^z`N7IpF5gOc~cj9Ie>9)@Q%q*GKIlHqRg!&!fR`cDPLLYIDo{r{LHym!L;Rb^hP7WW@zY`P0SXab!ngjZ=U^1gUZ64LQ~j`}poz zVB#olcOIo74Sj6TDoTpvwNhEZ=|KTAHbDfQ|OLd!;#7 z;DsirBMlo*Xh*z}cpteGaRMu*VT4<)Dm8^|#lfiVP36|zCNGW6?>}|LoA4N4z?vc@ zcO^x?mRQ&Q-u)Sy-WuDO;Wy0LZ1`o9A=A6*b^PhA(@@iJT;565vFcrm@mJ=$X~?iw zAPqzUu7T4Ly3}H@!L-8-50f|uZaaul=3gU>Z_h$@3?ybr5(-L`WBw#NDWdo;JbFU5 zh2kSAeua#Wr1=$cK9b>AD0nG59MJ%whYjZoA_i-z1xGU@n86y#Rm}42)JLA@i=}nt zvbu74UAdyJoaQ#%)qP>(iG~WmL!3RwrB5Mq-&;3n?sXCWWbUTzrUKRzDRCW-IDKz) zV;BmNn7ZG~$@YrVZ*MZ>cu`Ejo8g78;I!H$JmzlUG54xzo|6%}zZW(2jw0!+_HaEW z)LC<)ki*`jKowKNGtWos+GhE7kjxZ+6Qa(a5e{8$x(8$dI~N&&7;Z!7gC_zSWUOb8 zEJ43p&TDj!&hkA#UV0nOZqlId2+$rN){PVePR|B_H|`z(T;&Ow9NoyFDuMH9j~vB7 z>CUYu+}N}D#D)u7P5@kYb@Bz$N1i9cyW@laY)%076am;%39wBv8e~KO_f0ZHRGGXB zGCgyVqVgKNA!EWq3-c^&vjpP)Q?kxgC*Tmg!GAnr?WPl_JIOUx0Zy)=Gd-dCCUz=3 z01O6}pvf@>2C=sEM1yOL?34|uE9!K}#e zk*Q%kR7JYC7ilxRdI=wq234X?Z_1%7cz@mH>q$&aJ(e{suwa!Ac=K~`M4iOunzcy088O%k1RYwN4jCDp(YlB5+*8utA3BMF--7IjH+Dt62JWE0-= z6Tb6qd5aVd^>wL;24eeUAY%8K`D3kggC~_nbWY|S$Gu-De zpf;n049El|7j#e|{Bb6P=5Y_12Mo~h3q*R3cgU8Ybi1H<+>952ljAP}R+x+3w1{w= zwKXzg-u{@`QZv)@>>|;^UHP9zF3l~QP@3)fp$5rzNc2Sm^l(S@P&x6M+~R^4c?3{$ z8juJ4hr&DAWLSjP8RHh=6T-O}stcC}!8K{FWoi9GzjS^xlUwgrh}sMU??Yz|GC{<7 z*labk(}fsL;!s9W3&Cqfpo92t{N5nC2>6MW8I3IIx{MV%7g$ZW<>;Com`bF8)oRsy zY0jE--(+?Nv99|Vq#qF#C85(%!tCtYJ5&{5zb392lB4H8~y)fPB&aP zCuiwQfez&faVhA>+jJ)pyJHRHnDX6@>3YO_nD1K1J(5=p|1eAB?8SG=^K9&bkMj<0 zHy<>hiTHVw#J8eCm*BgZ^of9SA!q_TkgWHm)vA;h33&!FBcGP0yt51s;GoL$ON2Pw zS*lXiRky_BrC~Y7nSof22@SF@U5F8sl*3pEMo`dh|Gh!*L3AX|2Zp26&KDOUFQX&$ zLgX`iU#BDAHwiH;Ks$nP2txYmZdGPftvzdDUY5CJnb$4t!rAoa(LF6vHxrCahjx*i zqsa)|4DbviLc}1v1QCTG1)dR)UlMn*%trX%NX!gn0TL*$;5BVy@xlug7+~lcs$fDX&?V#iXY}KF?~0R64w#lx`Yt zd9IH|aJHKS%?N>w90}YK|3rWRuB&s9B|9MLjF%V=hm+j?ie2w!eTDT6czJ+=1hK(y zpodK-QokPkh;B3KGckeCka4cEAD9mq8b8lPcv_V-9P|b8;8~KD(Fyja=c9;dwVEgv z*ZHvX-O_E}RtUu+E7oc8chy?T-k;XP)<_>j0!LIL5>C9|tZQRr@FdJ(8ynK$Ks5dXUK3M6!fSHu36614{tT=;2+3$PqCXnK%QJn#F*`@Da>&qL_iYhTuVt?%{o1(%Kq4cF}a z?UJpVQH0(scd2xt1=`#o^#Aaqn5&^jHd3W#q7q925z@dW8G9B00u_g}cxOWeUA2L- z;%$hnt@}c;^+K#qzP}QB#&I|+~W<*zT` zC42ZPHJ?(;*Cp~Pb$lJer!42|Ch;i_zHTy~vVyOh!l$g{>yrB9_4~B^yYgsZ3Hbm+ zd6yJ284iWd40|rP7WUbQIU8z}d%CGow^~hycEuvWt;vD=cg@L#~y& zbRUsx#mfeZw;g5~*jUtr*DFPn$;X!sNRP`t5dEEq!a9^Mvn=@_TQdXpkRriJt(YNr z1UgNj&kVO9!J@se-$iX+u$0ypckrBA#Htb8SH~{P^)}9iphypWa@->+10}HH zWdv4$zX}VjjNosHahk9dGPi??hqsIE?%4yfQmN1-#4fi~K0NTx@9ltbn&VUfnYUuB zd)UyC?*@OK-%D@Jr?8-*bckylyxT4Wp2ykl=Tfm*!@>a+4^}W@OxocJlUqT?_1n%b z=R-5QJVVjG!XeGN!rvaUmCbH%>yviFyiPHi5b|w4j(&h53M*0!;srMA#MM52CHO%J z+bC{{iBlB0D8&VOPI!(;Dh1=nQnFQ(z9aoRSWq5>`5zT@n9%@BQ1G1(mgq8PFYcWJ z|1UB0rd4PcvBRRw(fQ@K2YnL3g{8_z?sEDnQVuXkzPl41Ed6FcDwust?1R$z@1s=g zgT(QcWr_)CuO|l2WvoBq8pU?+v%;JQ=Pt97>QE2F9}-_1bbo#_U=s}R?|zV z=2`PknN<4|%DVaz!tW)7XB72SkIVj^Umx0DuwUAzME+;%`w{}=-f5_w6R6=+vCmY8 zl%qlT!vW%5{wZDcN2+Ws_=VoE?AgE@7oh#=IzY=xsL?*T^A?Dw{hXIr9a?tXajNajSkuF@LhicHv3W-VX`ITD7ZG zx<60Y7iJI8Bac#9G@R_J_ENBKi#(t*v_v}pd>atT7;$eGhR+0K$5D7E-MBb$+l}O& zo5|fble=!~Z6Pl%r?Rqz3JPTzQN68?!EfS61w_O)3@TyOXzeD2kjpfZE zaRQs)y$u~&wyjUmCK^@lY1$8)Exsd|`dOyCP8 zuD23gc}1Wfo?qz`bxWPM7W5JGL{}aKhrzyTSDuV?`J*w?;UA;JW#}W=iOAgIT>~^| z5m&`7S5W4v*a@+!P*-BB*Vzl_cOq~y71H)#g1vfY`0ylbi2Tv!&s9CT$Qsp|#UpO9 zW@%l-B~JCUsG1(qIz5-5j9tG5t#?D$FHWCPVG^eiZGW-Wx%pDJZhbB37^qf-*@Qs@ zM=wk#bV&l@ErF8TE?j@6ia!F=&5T2ntL9*7C-hYdddDI(=K0N?*Ys#>0;U(lyx*I6 z!%Je_Iy5zufTqGyS<2u&;*5!ljw@t#{`4|bz>&YW9~yG z0E{AUP2hP{9{bL2s#EkKK03@Yvtu zq&s|g;h}X%Kb!)!qr6CkgV_ZYGHbpFi$_2&3%8FBnA^3MBleijV6^L!bR zd(=6kCLHUPGa0cDa@aU$F+gV)VK>Z%D#Sg8XXO2PuA)z^1Bx&SAvSg?1Am+gJ444?9F5Z@mXGxzXEf3hZNWW4>I zex<@p9QH6boF)1sKDNfP&vdoa-q$fx`0=g1k`hM(K1gDCm<7?YE$v* zB7iG`H~z13P+%m$yre>s^DsB&t_Ak0*HBA&LO#}@=O zHg|umchhZ5rsomf(`FvO*%S2R-{A;kML^zudOHB7?GoLei#V3J>yDq{w5cXR;QjdQ z^ixVIFN2A5dI>C>8?O}Fj)pVa^IuFcewaV}GMad8HD~#}eaR z`Aj1wu%Mm;xf@r~2=W2rOGVpywLXa@eOA}%^uR#O4-ZJkEGuA5Lvg{t0F90$-xkzO z)A41{PfnriC(!x%zezR!K7V)zdY(v3WN>*L4K2VcLx%hbrMM%JkWV0-z{BF01+38G zvQsYAe%1OT_bS(kf+tq8xnUvL(7V(zQk~0Mbs(6_?B_UY8fCm+7M^r=LN~yFpt9kj(hJIPYs=H<2mznoo>b39Q{^L>^ zC?4<~Ti(NF2rE%+XtFI&BLf%Ml(A`uO^bILAIrCj`*P6j4v{$v9_A}oTV?jW@3|zq zi1}^hF2T&I3i5yXnyGgAvkkkFncptoKDiX;gEBam3K&^p3cB`P!~i3{w#is^lm6PD z>U|)8cqt@$pxNLfL;9-;E741rVKw;_JNkBHd+kN!rrB77Zq&+I2NdxaY8$?jnpSxAd#dEWy%f(4I4!^kR z^|Z5AsE=lCbJ1J%)N+oNF!f!RLec#ek_>gS`hH&<@%CSGd$!fe?@|ll=W! zzIGN`u)J{!zxR*8FNYX2P&*4}2;~jsMNu zdnk`dgrVnAPEQ0m1sQs&sT$!+5)LW#Z0KT4Sgcqt&I@@D(|Q@t3busn@*Y>}rPzb? z7C|wkm%;JCbeD2~fROEY)Fn~qQ(TKFmjuVOs{;I$9q~`3sQ*j>AM$9NFX7qb0ILQ< zY;XI;b%@6E=3tu&+oivo>@fXp%wM+6gB=d`*16BxK1GGB}XzyCi;zq+lrBM%p;vUe1s>=d=6T-Up@S&G2{vI>b#4yI<)FmFDKhmf2 zv`0dJ1!RUFq!TRg0xmFC@wx8hXYlGp0X4L;&~l1`dxmi!h3R%qpF_4DoPugA@0vzF zGj7%w=S>Ayp<*LbiO(G7nT15IHU_(?w=w?P1)%24-L=oXw5*v zAflQf>S268ekSq`AFylQ?LW!QJJFxChuy=!bw9rN3E4jkKC*vj`b=!5DOpkmRNeFY zN~MSmD-%&nG2-EH>I7nqSgP_AN1)Qi?vI(Iu^0D_U6 z-<_)aG&gi_-0L5q1SpJtl?XJKxbB3Wbw6p4{nL+S(m zZX}oKCpO?jZf3kIZyb=@A$GnQv*(K0JVBG43P`3t^^VQ988gDP!Xb^)34+-&5f9y~ zghx}WIP_(#b@@<1EE@b2TA@}kpHII`5MjC{k1M-Zgg%KKqFad(oRcD?su)D_Jj`}j zRO8$L4B<>U=0z1;qbR)7D%R7jbMcuv?vh>{Uo)u5y~<;p9{!0e`yZ&RUOXTjCrHpA zw&{7;U5UuDFAv%*e1xN)-k`MoBKIpRmgfvCPd-TOq6;$O>yt#Nds+`%L@d)oWSK%% zBon@;my#mxC0SCYpJiF3rkx$ZT-<$R?FXH4x&wO`;l?d0@0FM~C*raAxfDtld5O$H ze~lJ#f_*wqakeL$^PYQ$@T9l2EWNU=|tUNxBOt#5P8<*uWo2}v* zLzbK$9~VJviQT`W+7i5Cu~Bvvl~u)TT)xkk^(nJ@`M$#Wc}&gnec5;JV=9;LL#UtC zOv&1c6H#pa)MR%i|1n3odd$?!XY^y`?P)yT)%whi8D3C3JfIO1+x45;*hTbXU&6Z}iQFZf?4vCv)n zYUr)M5;;GK)mK7a6vTmSY?@p8qD4Hd?l&8%UJwO~BlWA2nB@AB?IXP+i@MsxPII$a z&fk}omDI20&8E`&bplMhYuY?^eKD+-&7(1sYx+D>soG*!97`VQ5Sg%*7yBa>Dnm)c zd@NR8>^CJ-7eA(DTSdm#V-_Gi9U+0IkO?e(c#O{DjjzTmd=oMZh9~fn$*z(8Oyp9} zcdHjBRxM7WxBdrZq1!Z%rsbt58gl57I!e|+bq>tMNn=&}8-uMfUR~`={^pH_s^3i-4dyE7BRX|wpCC-`eEzkC+H%)jDr*DQ3a=ZB+6%y-ir zS$DcCJ0SmX(vTOeF~7>cVhBeKS$FO#N3t>;t<1Xf%%WG_bgxh3uIzQwZCs7jUD@VV zTR1k;U1M>pD?(q)b=Oq5)l0b5$XU{w!(`RBM1n0zo7no6({6{@<)EAIFLk9PG(E=$ z_m~F{sDcM0!Gl2n6c6r;K)uY!21g$0e;%QEIl3nbd*RBS&s6W|1|}bxlw0~LIa}2U zI9r=G^W&#NT~z?aZ1hcz{%7{rEJFrbD+ zF|MD=JtV6iA+lhrT;K6j@#lvlX)jmPWUc zvy3F}V3;)GS5?;MZRlho7UKj&}M0J%Vg}S&}#-to8mQAAW5^ruWX)s65dmhL( zIL&XRi44X!2Un>K4H3f}A$(o^d6QaWI;<;eaM?ACMrNcoH!y!AT~bFmAJ4%&$tSC` zHF~Ve&8m(qcC(tMibqOi0?jY~gfY>*%oB4Tm6+(qI$*b+}S0Ae|g`$SaRVKP^$1==TG$-+)mS+dzh4`xMK2z=$t^#bZ~mf=@3Dq|fNeNCZ0{2zrR=y<-+W+s$*!7W$_3 zJll2)f7pSQl6B`_beBcDro74@jxUZglV9cN4*qZ@SJ4q)B9kyn%>nG*%gh|@BU8A- z$DxwT=5ur}SJBI1;Z(G7>P6hLMI7kHigpewXqkmmS8&TJIQ5diD!jV{R2PRR=CqI7 zdD_#?@#3l6sw}LD;F$b6cVmnc3jjlX+5rmG+{ZSx`nlw4X1b^U zG`~X3t)N4{n9C(6yrT>D@s~ihet+%lCu{F<>EJK6_xJHDB!_^O_qi%p^lIm)`VW+S z33mIU6>8{H&K2gaNVc!agcUEs@%%*xLuGgec8kb#Pr#4}^F0~!{T3@_*QI;bJJ6dA7zIg9RvS6 zbPVpy(&(J>{3L1fbA+#FlFiqO?GhPIw8g2nn6DJ$EUQ&vG#e#UYB{w$wB_Q`<%W8} z(|d)4kt|LYDxfZ}lxQmrgm2n)XUxP-cec+lY>s%_=ImkTnd)1TTK2;;bZqP2Vn%Vc zYcJ_dKAXhO61F1C@khw3Y}sD@=3RrMBP zXyDw(acg$!2^b00aTp=QvOeE7Ps$w;aTbk0?Gl!LMmR_m-p7@YjSCboL1fCy_=EZW z>{3Y|aYbLC9H7sn#y|x??k1Cv0n9v;9@D+cGQE0wf-EJr{wNPb+C1G7k@KGH_tmAc zVe7ThRTxcZ@kXDkM(35v;zWn-C~N%dHLG-w$_l@J@WinC5Z@)8n~{!LktHd&YAu%D zoAmEiBbhh5N@AeA-J0IS(u}Rx{W~g{WZ4XgT0r|mFPCDOF+JPnP3x8*9u2@Z_Cw=o z;&}wZ$!4~IzOTYr01cG{S)ASk7rrfMX!BJ4fVdmDf%6D6APN2MTK5V_LI?*$Pz^hd zbj$g}ad)1n$l`a?`F z>r=&PDZ*BL)-1>lK}UyruW7lURzJuqSA&vAPkOfdJ?$i*Fc`}AHV?~bwFq9J!n2^l z4jM>*+rG#zmGar87$g_nb(hjaPtB{MM=EhfEojitTP>9H3OjL)c9teiCWC3<8Q)yjuH zxV3z4gk&6$H*Jh;lTV#?b_b}41^(huEULs7sE6G4MKTPJu<92vVw?mx2D*mbYO}w^ zj|DD^Vf%qxM}9^b^Rb;rZuLAG0YlMwG`4MC5;ogRA7@|0sjJ&tM!tz*{x38P)*C7# z7W+c06zg9&{_`-bm^7s_VTzVY(fDiwdD}qMxejtV2a`ISo|;n zUxC6_Rrgw=vFq0A+tF`^%A`KFx5iMLv~*=8gpiuGNy`t=BYBjA2Mjc>{I$`5n!rfi zN>}Ni>FQmV#$%iNqUke^s>9F^uB@eYMo#$09m&ZVZNRB)Zy~i(}}w zpU2Q|21MMOH|4vXR$GN&?VuUe)}~^d$O}tlO@sCE-IDZ~&_Qt-YLS5XLHeZzbUGD@ z#V&zn{}IymINjbHHJK1pQZAdDl4FdRm{bInBu;g=hsbs(w(kY5HQDLPZx=QmgnGB9 znpm3D_41f2sy7%)Y$tRbn=QGNC5PZ#b99$^L4IAUz&sJGA7XIk-CV-y6FJ2+&1cDY zpdtO?06X2s5;x0t3C)4BIOrJPiFGM5I;&VHJOc&Pknw7uKpK5^ZJdwibX4c93;jNA z=ZTxI_|z|_2hywiSf8HAh-TeN#CyKe_%ObDp;79G`~*GjH7EKy58r&vd+v?)V#I`E z6r|*3q|)4x>wssypr4F2j*b;L!5mZ_J0{FI!4{_B!j(*Md;bUu3W2BbrfV6=*`kPN zFnUh|=_Hb?UgD4nNs;lHtB%}5G$1V?zhLRE3v4PYUej@o1r`F~X>S3~1+(jlH72=? zC4uVa>3(9G2+91zK*1PDAB(Po;2$y|Cf(n*y|bN&TF`s4J%RujX95{+>dE(oeaH50 zo)-3X#BF6Gf?8nxqP&?(*HQiZ8Q!mSapB|JSA34>?(3wrQqo$S8HIvA$7Ek%v0Its z@=CwS(iJIDl~+U%s>o33FO^#CO9U&NLOAW;hB@buTK=ps<;fL8^LZO+ zt6Z<1S(dY6)rSaCVt%#r~a#CTzd@f2+upBw}eQE8-yK?9*3@}+=d*O!v^ zVvT

t;Q*L0GQXH5!j^qy5#SrH(<4pWI&SExNVwIZrLWU$k_Ed3~+(nG$SE{@zG^ zPZE*!9rg5_o^cQhz`rB1@*pzn4<@}dkCut3_8wgIunsmrPYv#h)b}Uto;Pi!&mpgG zOcDfEc?05gEY_bC`%av-aH*>utZ~Y%^|hyACE`*iz)-|6hj)QRoo6=HNL)2iMhv#Y zR3nSbQPr;!`nthi3P@iVz}z+i3YO%>!n*y>aiw(}aDUeV> zJY@;)D`)+zEfGR95uCj6lJLg+M*+YL3C!|py%>4I}ulW=n@zyOHc2Hr_f^yV^| z41-!@UC4bW8;9BS1(x(`lme4u9F3;*g$}*8k}EUmOeHHTnN*Ciwlc|HB?%ReRne3y zt$Jmhwl--+z9YYUO+?#}w6^RElVd)vZjWellB~m8cpB8eg$jn=?nV)7Z6khcRCmh)AJyqp3=@K(5(U&<6`V((`>^2b{_1 z`#yLn5*w+)T#zP29|ik64dwd?GIzeVn%9W9T5D!MU%P;*=5Oy}%J|xH_V#v*WGcUV zndSDW0bMd*n{alIYIljwr2z}Qz6Yl$b_q*P-hcu{U?zeBOR>~0#G}n`=2~<~hv*rr zt@8SHe&M{$!Stwqj;NqHT@t(Vv{ujYYo@W$5Bt7m*JLq?yM8{#>Qt6z`?Qr2%%_=h zFola>Qgg@)&Gl49d?%5MgWWmFQme6~TBDcosr;b1~ z(Hn`p?uTh{TA-lZZA*yS67dl-Ljmu2K-n#}m?z_oFw>D$*PigvRITr$?#Z70pf>@< z2uRV>PBjsXY?*+7g!55Y#dzKJ!Dchul-w)nahIi3#FtkmwzyY{xs?)2>cUd7Wu+2- zv1|!YV(P+Rua>|iX0y>;npY)}X&{CME%~%gz2zIz3dXczl4-?c(~2pk6-lL&5f9mv zZRA%Z`u7MnkEzwIxz=Gr%V|>$4aGo>#FT3F4ZCaL0Vr*1l0fL?woca5#GGet#2wtn zq_FI5O~rnTLpGo=If(X0KMbkgn#@D8HBDozw71-%wcOqd@*m>qxTPIxKF7 z0L4{P?NW=wmF<}gu9^i*m8-JLm0a$Sx@yW9O}$UcRrYSV#MLBlG#FSBw$S!|u*~+{ z98bTW=yIeKzj_*O+IOB_>fr3JerR8vwItc1mbxn1EX%<3i7d;^EG=Rye5|;)-lcU_ z^iDfF0M_U^fFq;s&1t#XdJ;b>eimZ3qG>o>W-3iM4hy|{ZOAkRU0m{INW+KE#e{PN zbiQyNG6bL9Vy`y;J?64ou}NF(332fd+3*_t(EnMwOqQnv$Am(ceF;dUa4?Omxg3jS zD!H9z!U_1M!j(OHo!gadgyqk=z&y_Q*g>3z$DXv)y+vZgYXz^&=MdV}Sa*y0vg!M$ zBiiAm%o}fEdI|l&5=Ba82)GO7V>6Y;4|A&K!=GIQvaDf#hC>W8MmUJnAU+93op6x~ zwyNRIr12{ap25A5X;ed23Tm);%}*T=UJFm=9%5u^R724{w$rz?N(B)+$7&u{?y&mA z-LU9c(!GR_I@-)wC_XdktLP5LckUQCC$SU~ZaIic?X5y3n8f(U2k5~!2uXzEWP&M- z8W(nvD6tkJav@jy{=29en@#2QGQz1q=p^j!Aex{sA;zzy-ML1zyN*AL*{Os~n!#@} ze)keAFpBbE%sI8yd?iN61}MxPi5M>s42iPRYAZHl$n&rt!_*#Xa%AMcH04+H(`_(rI~22CmVLnccS~7F*twS|mqM*ViG%PI~JRDzSLW zqmWo&9)rW7r1LLYK6g>fjVp6l~^Gx5Ke|7XrhIvAB$I)8mn@c%o{cuxyKU) z+QTYAQ!w=hUyN9CGGQgfNA-9mOn2qYptrsn+xk8sPB9)3J>nLT$V1Uu8u7Zn^c4HO z#vD|e7$M9r5oqm9)C4n%Bi+#c2xobUNjxq-Gi6NoTeRV(Kmy+buW20X=r!)0PMSt| za1*WJg45^1?D?<=VaAOaXqykhUtt*&z4>wFj*J@(xXB<9na8e#G2JuYD}vP7*gZY; z>q{_S(!!vFm~NP*IV4sSr=N$LnmMhRn7-V)Ial62K(MAU`u?GrH&*nc*;{t7^4*un{GPy0%b`RZaFO^evJ z;Q>>&y(sZGnIO-X8K0aUdI}a_)KG_D_Z55r*)r&yLD>P2CK}Y{?mTP~Wm`lnLZd=9 zX%Xo-k=6t58)_)4w!A`X+(xRqL~Ie|nnXFcL-HPp=NT6mEIjEcpBN7dj~O41F&pEl zEiuc^C*sM?NWL#5&6{Gz)|kNYE)g4BVwPPw@kbtvF(pFEBBhL{ju7T~TYd6_GvX0-nKXy;ecyfKr{3D^u@l+#ul|y3fL}JZEV)aB~ z6-khy{y5trE;7~&mw4qrh;FXD{5QbG#6dm&@w;R8y+4nOLzh;PAtZHq`_gzRZ%rir zJds!$GutK#`q4yU(|GlSw?uaoFW&wSV^TK!3K0?p?r8-WUvFg$m`E&m%M4KWWXJjXSy=MAl9;h!7v8lZlnnXCJX-h1*)Uid&msdi4@MFatSc&k zQlyjh1wVmnF@(>-y>7+sscHBd)>B^5^x@0U(i4k2m~xTD^78D!3*;$bvEXlyBBY6V zEoHFu6Rc!}|3!EBc6a~7`_C~Uw@2aqTWrf^;bCk#rPynJ3;L)9fA`_<5dQAR-+HX| zS=eJ5@HgKRi_OR1AgP;|nrAc7={TXC{}XCR{y!#qTHPaZqtxh@8BKPjNoH{VV$jf{ zS}RX>{&`yHvsj~S=otJirNf`bKofe~2R*A)+hl6*@oAxt$ufS0gp&V=EaUqX+r(<` zYtup>lKlT6`5%yc*k&8%Xua=`fz3m`O%B8xbniSZBXPUjve_otEN64P$Q0-PX`we_ zt~_dJuTbXeLYW&T${d^qgaUkfH~ID}H_Pmw7K)Pm5Xp~xr_A4fr_5>YUGF=$v0-&W zsVu4{5!6iCbD@AIE()6UIowfwo7p=&n^SD{cqGp#G@nTVbS9%nTUXdE3)5MG^>z9i ze48_ASWBoP=ME(&qCDMx7-s}_<@f~~&M;m{7)VIFPZg%qnW2zMH3=T?yCndos94H#5%g@o%n4g?|;gOHl{R%Oy zPaV`YeSiSjsuKsbcoS;pp^h;S)#y?FZXDB@Q96xL?wcWj0qL)|Gt*!ib!a;t$4MUP z(NfdOsW(DMoa$E%&$&jhxLS!@2Y(O6Po<)J2^2@9pG4**eelhtdFuSV9?pYB}cD{BcF5H7y@eWdy9f|5OR5uv>&0xQF zyzR(b65DShCqSQH^dI26aNU$jd*)x`iC*UbxS(HUNwy4{t< z5CO0qn*Kf4#}h9I^H9ifYbXf)JuPI-5Nm)uvOdVexf6+;iNvoaUVmmH@gG6AEZ;86 za~AI%-)lE#g&rTnUfT>$b?NY9V`Q(Lz1On_du_7UofYyCwsswH>L1=Z7T;{8YVZA7 zp-0G#RoAicaU>s`E!^+D-s_NmkqSAe9nZ#rfdNdf0T%!-YDwR)Ab2FgiW?xjaWdM@ zW|`laUCNf<&YN7*5EBB-%97b&R$!Ae?d*+*bD@s}T1VV(0@GbY=DXqlcD_@yyx)># z_x<@UWuftV{PLo9{8D6B7rAg&t;TO3Xx5kU`yc$?!S7xC=7>Z#jSl35OOS`V^5$5a zN$9IaX|NqW9z@>9Ia85wmy(fzW6-4z$Qb#$lP+6U`F-25G1f;mx^3wIEpu+q)G#fY z>Q<&Oy7M$|o$9uxxvl9@M*?3t)m@q9u1x3Elv^>iX>$a^4EJke!Ilb)_~33;Q-7ps zbFir;=x)qvmGVdQ?za{0{6Z8QcBY&HP?s(>tV>~bhpk<1ht;hHfQ;Kw?cQ1Db}VU? zhJz`PnZ=*S!>v+0jt}tpvpYAvw5OHNH@fo;d%8n!{VL!O;F< z2sl+?r+Rnd)X?8Eht6E1SH>1ey3N37SWKDJdKBeO>C%;o0c2+gkc}4{lD{q<5?310r~#5!s(w5gs-OX^~r< z2q~bNA%Z|Tb||t>M%bWb? z5gJ60{Ta|Huuezu4H+;}5jnFm`8pb^oP6rV?)bq>!w`IA^w*5I~HK6-qVp`xvDmnFc?P+s*NXR2ij3{#z*$psBBGeXUV(&I6axlJQn$f>J;qN&6)gh(aCB{v}*N@So_9 z@KtM?>K}BOr$cYR59?hvwM(sZ*^)7rU2iE}FrJlBO~Dehp?M#yzjWa9L$ba*~q z87)l5*YD%wb8CmvC7NIVoWFj3kl&RPYzSf#X0l+3i+34WWLUBlyTJygPr4*ss2_Hm z0Y%iALI!pcEYne_u=QjQklBC@#8`Xn{zM+Zmvt#P&;$Efh&3$6^1=f#X6 zD4{Y5hUn0v7Th%qNtzC-3?>QEg!L-ZhL&6#CoVCTs7WT2Ft=?F(~@9F;sNc{uOhD* zHb#zWVJa2+_A)%N;v;X2d>bmg9v038Qe^QpR3=`NcqKxE-!g=xFoEKE;oI@Vz(hiS zZ9FG`JYm#bud9-{XgN>Ih|A!5QjQDyL^{DlD@e{Nt?@PCQjuS$1bxQcu6%kM~d$&ko!UyTn!D*<_K8DH7uR%JoZi%~_-!@>{}-}<$YRy~&F z=7#2xnSmNB_JyW~Bvzfc4(M=8Tsu#9j1Ia~+J=ZWFQ{dM+WPaM-M?&=vdThNO#)k~ zVc%A`*x5khUANK28iAs*?umj&b!}rzUST$AqMdT8&NH-7VHW4-Uq5xftz5qfnv`wC54qmp%ouZ0a0jPo!^Y`QKCzAj644q2GsI^_ctu8-pdDr78Q2t%hh_gbGa``Hu!<&6F^ZWA!ROwY zbqm&Xt8D3sjl%g_j8Hieh~#lVSY_c5EKGnOG&35^1i1@_|7M;Zaa0qLW2o>)YE)1e z+Fm_>woz2416M^PM9^>ve3FQY#pZlOJuJagD>%uf$pdMLP!h8? zicM40mv0o(A~sFRXbMzpnhg4An}n6Cai)=5W~J_*u@%FGJq+#7+YWWN?!Tuu()ZF} zTgcv)mguaR4b`4Ldu@h(G!3M{!bWN2cw{uW8s6q7j&ab;y7F{bp@qlD^EQ~2Q`8`P zngws8lKDM@-s1chBnPxh)=mSLU4lXTtOK`>`8kW-3BwMARS8wRyR;r7RL27>HC&F1R zsPtbUDt$gpj5gfdqS373>9fN%)vxuY_eqar3kNL=^&?K$VCXy=i9&xFC&Bhb8hg|`Oxh}SH^;|q{}(XEu+ikpQ~u|o#ayzmLwaG7PU7R z%J|50IP@Z+Prt#25Nz<1xm-sX-{Dsap24; z5spBtalw6_xETd-jBc1wWSy&Pm!L2%C2^2gG052(g|2@VU#ZUT&eBUUjDoCzjb;;1 z5**xoO(L7TkgZWdqg=z7Y9^U#CYx%em}-*PVBBVe^acEP&QJ6OJ>C;3(z;wkrzuBo zq+sQsO8{hLR+8qwIt`Q3CmrtqaThZc0Hcf|*tQ+5>CWa<3~5grX&{<}hW)En#pgAd z>;S&R8!A~xMpz|sNC&-UCuy}!eF+JXzN;Mj^<(nBS8uf!FkxhZ{ zlFv;0j_f2iE;|{&hlVx;l)ASHSvC`dCtN@m&G4{6J>7xU0P~aX!h?)m@H48hC zU8{Qx2r1_a^Dv{~k#7-CV#N#*>07kAx@)$fPlP-8rbRr36;B?&W4pGp?&b}clO&Db zXfB+{*8OLpMXbJYb-lns7wM`#oXB8PDf2~(R{NWBR*R;ibhZ|e{;2!OmI;~DiSkNq z4k0p;t^4LnOY-E2H+5g*YRbfw**Z-RlK`k*lZ1FB@Jhk3xy4!>_PW1)8EnxO=8ZFT zXn88-eu1o*rnul-DA6s5$#3N7p1K6Wr7#cttxtqE{VhqIpPxfT+;*z>DMn6GkjR}m z_l~ajsqu^V&mB?SxOnu^A@Pk1?$Ur_;-VV?e-RV?Rw5~s;G`EMNHeouUZBKky_o}} z;P}MwUb@=8m6QPa;l-QDCkt=nZoirAyqUc3W^&!lEYWf(0P!IM}wjd1SscRdv%xX>r2i%h}xx93KzxtwMosF3c*l8vWC2MQs)=3 z8`84RVp*>tlgPq8MSS4#X9hgY`45KQD<9-|;)fDGb zX`wxrAu1Sp{1TDJ?Y>OL^^W+sCVPL87TS3kBLAE@KR)U<`%}FJlb6f7mllVyn_Z`DADnWN358haCE@#I#U0$)`!aj^xMb zYp?dw_+Wu+$f4?=iw~9-1CH^EkNGuCNJqx}n~OKb{F$%gW6mi5_m~?W(wF`VneF(w z=-s35{ICFxB-%tWN>CN9*E1PDLF`Un8do0*`-SeW8Xw)Khs;Y)d)J(0rs_=r>l%za z`Bvj~0SCwUXUztvAjZKhY*%6rE3HyA!;&KbbLA7?rSz2o;u;Oslt{P~nt5&8OL~Vm zlLbl+aVAz$&A-mPSBVG)5-xuU9<#y)+ggHmtGRi*7JetO{ZRhIAG2 zE%Cl&`v3b1J@WskukQbUsjuz>A%=kw|BHbU@HWV}*#18%tNxLzi=IDvc~O+;44u^b zDYmP`@&J3v)fo1a&`GSV$LVK)V9Pu;GJ~SrubpTLZagmCJ%`P#Y>J%U3IaNEEZB6+ zA3b&=vl4tf;*{{Ooq&R5_r5ck8!Zy*&i36YMRy+EonpSTaQ73=%q3VfnePOw)V`t> zi93!bz$;PGBU{>T0>@6Y6 z_WIa>h~UFzQ`m$}>XLb06QSA-NV_$TOI`(u+LyP~}-G+GYq_+m--Na?EPIi%u|1qqQuke$f##(_*pb-Pl z=a7DOMDJ2|eCrScfybUJ9hw=7^50XNYHQI-!$L=9<5_Oji-YW)e-k=NGKM9UEKA*j#Dk z#fh6Ag5x)sIQTw6L5>o*<$zIEZaHeZJhoe*>5~p!7BqxsVw_VH4ZbNTazuO@wdIYt zINj4e{#Nsd0kXTz55>RHTx8_;!rz_KP;kJ4R~BGa#|x;Vp3iY5)81i2Q^TM@et!bW zdz^a&WFo!VH6n6ZRyRudytse-2Bl`LgiEH~!TprwJI$ zAIF6H)nb4-ov69b(AjTjVh6!q#+ggcHldne+TXd}C&GLbgR8+@#5B2ydqL>h6W6np zH!+$R#RBEFj4Dn|*>25W>Igcdjkh~kZl!odnO#l0MhtcYZJ=qkTB#ctbHro23t)aZ z0|aghx!&Mm2T^f!KRhp+ zT1orCT9OR20CEx$|dTs}7J80${J zYFu|nJ{k&ONp`*!YijZPTY^W@G|x{SkiroBiCCR-av+&*MmS;-)wF34Q?&W#0H!~G zNV>Uy&7|R0xRJ&;1fSCu&1-+KRgTKa*UH@@>W&ta+3YbmYylCq`9ZQGddP}^vB>y} zz}g+qM7ZCrlmN^*qLW2 zfkf0K-UU@={VGE#t9e$gc}UK5KjvyFts$~H%KKjW0PRrVBLc^mPHfMJHM&MA^=hsk z62lah>0U7)YiIF>zKPhF8h0I$Dc=_ZcVt}XD$`j6F_a^ zg=UmuE|rP}1ewyPW|iD|bhbU2u77Y45E2*vHpLX&Uv?{e8NtdN+YVQIU`>5|9j7s7 z7IQl`G`q!JUgOvKpNp(fv2+4pRGoo~-j|=Ouk~x|CG`y|PlHzLl|b{-kp_<|02Yz*-j;=9&iAeX@}^aGNZh&{h9|HQ5Kndo zV~*^WskCfOOy-LF(i>mC?v7?z#T(*?eD^Ai$FGe*UnB;jVyzr!Tj2GLxXO?u3D&>F z7u@Qu+j$*Y5UJpjjPpC!5L=*pjNdgoR@NUJ+}Lr|xCz!EB^WGXHK;I397~G#2PTZAt zpYFoS)S;T|!?oA(rM)ZWeV~u}||?2`7<+ZkY|S47@>tzToL}3Xy(8gFq3ZiYE1_PBop!QWFAcaVg?% z)zE*==2nUV)shX$125g(e>@@g^@vxNPUKk{_4%s6H3* zA!XKad}sqA5KD%{vxEJ9!1ALXhwh$@emrm>oJeKe6Rx6XZ0%NkCVJ^*X;u%xEf@}s z0cvw23j|uMRZ-_BX<-?KD20GIhPV^) zp+beSu!3OS6%RVj7KuZ70GYLp$4H0B|X2+_^MX<*JJ zmYga~uS_`biE~x1Jy}w}HrObeCvwSld2Y>?e=2#p zwu++O!+YmXJg9oC#igEwL%U^PIv_LbBZJJ;`n3^8UcYJk(q$W)nl{Qrl%4(wBX_B1 zFW;A3|3Fgx(v5+jXyPF}v2@jF{aO#8E9*um@F3L<%+9qtr=pje-?tMmt@N)<+VwS>@FFTHZm20o2z|_{neo-XF-E@NV#LTPsHT76iQU3J|(fC z{)z34r526Y1po#SwGtHad1mT>bZ#zf2yP7Aq3nD(ZRsPC?gajhM1nzmx7c#G#8aA$ z0Dy2Z$$BoC#*{e|^)rJ`KAX zqW^RQz0w@8h&t(P&O+f580VZt?Dv1`-SSPqLJLpfq~a_RkI&3m1bx?+pgHnC7WNyC z76)kB1H!XS8=yrzO^!Os2hT_?i6p%K8)D}|q(1>#>TUdnr6stJ42XqTZKpMjxL2^` zh$>Kcf7?T4s|b$VPp^&R$PqL-Y4o|BWcyn2P3J&Q{LP#1APyvCh-k03d{*c6Sdo&M zvE^k1kUG8h_veD;ELbJiZTLUPCM|cRAc2lJ#U`D-vDXVW_=9Xx+Qi)mbQs^c%N;q^ z)%}t%-^_Ssg^E*O~!VS`hjk#W$y`TT|_x5r)H zh`+wiZ&Fvg)d>jHYi!De6|P|}&q$zSjl*3UV115%EfFlcrZwBk<~To(&1)`|S!_wB z>~i80EBJRqR|lmXj;}gpLbL2@7$`$>Ku;f3c}O&9gWwfA8f5tpLCvrWZm|oLl(c-% z(}|sw!~U{T&aG6~f#w6p*joEav2AC?5f&sg06>UuEcsuG|Jl7UIL2D?U|*CZ7;3QC zS6IZ3Up9$dHkn;EgG{P>s~PhH`%iEta}jhKZU{S#PyTQ85x z2r+gvR3Om#>$k_p8L%E0OSl_iJQ96z=wxi$o}OT&T@~z$cwhejs_gdmXgbEc3$p^a zrr1dvN+)~o&c;~y6rM**Mrh~~fBQvyJC{yKZqGZ}9?zSeA@ktxB5w^)uwfV-`0o?@ zx!!|;(3Y;R=s@V6-tGR!qJAIeH<|%CYEXCno8Zy_00i)-K9&VSL0<$? z874jdfQV6ew1TLKdIdBH@g>9jGaddrLerY9PhMy=c3wf;^B~S~tm2Mr-+thBTx%Uk z#KgBq@?;GDFWd^yB1w@f0srf_$|>)LtD%1oABs;w*+xS<(DPLy+%v$Iz#^Gtv1lxo z9$}uF#{aT(NBr7uvDhm}rQxea*1=eenTMA2DX=oJDb?8lM|lmq4)S`yK9RMjTYCk@ ziY!aS`Yc<4!DrskEr{i1O!mR}UeNd5h8h5FQ;5_7kc|@Z3>427`bY1Bl=Pq=yoLa3t-||3P^ds+G(e7Yc95%V2QGF>GG- zf+|c$sGzAGqaz~nH&304PC5?wbc(ft!n594|Bg>tukJMOEgoAfXG`Qx#? z!khiP=->7;sps{}7$-gb-C_C@UY`^nCLk4!zl{(-->VaO_aB$P-=}$nDHqD5c^O$C zOY+Jzq>=MwXe4RlX-qbujT*G^;QwwTrTgu8Bb9pfciO1JTu|eegrBeupvOEx>TJm& zCyynk0#(P>V}5R|0kMT&XTw28z_CfI`%KOsg#*pT3x$)shgs$gPOsz?in>-Autv72 zXL`TD|3)ac<^~oK#W^~hgdBmsObIQz{`4W`aS=1^?@Ht$mZ+dw*ITxV##45LiOGCc zsAv@gmQP&?y+iyqR>w%BQ2r&{U=pF^MHHIv3?#;z^jq);{ni2h>AdP$BLrfD(mima zA6&xcu|CP-`RUC*Bd)4ssgQ3y&Z7M;`fhW>81shag1Aw_+%4D|Ct=HlO7s8X?0?{* zs?tAj{LY=f3|C_Y1cX87UKkh$`m7MeO^hnTG=i$Za5O| z!dMBe?Pq3;BsMk~TQiLWEF#7I6x)`W7Lv5us-YtOL+1NFcfdc@{(j%rw^xHR_ndqF zJm-0y^PJ~Ae_puq1QwBb7{1_)vcvZ%mXlFLI^F!kki9bJYo;ul9odQ)qlL`k(g|%p zKju5MVSZJ91@wq;NgKeqv!Ivt5kdp~nffMxjA^-)e z7`B0d6k^+LyGU3-L4Fj`M)S0Jn>M>Ds-of|BrlWL*Z6dRN1(7}M(_}XoZ=}%!bm}J zRCaz;fR`2&nX|JmqK-*y=Vd%E5AZkyE^a1qtO%TwN9SQ2oyYuJ=HZ%(DIiO_J3iSf zY@p$Z(6>$m>(miVX&MWBgPJKH?Vjw?a^Coqk7mbuqeVvlyv;ku8RK=Er^`DKsHP~H zi8Nfe4xWOe=nalSQPW1ppc);6esm1YfR&38#*peQ7JCu5vsi-Gk)-|B@qCRl-wnXt ziMI6kq~Vi}&s2Ph!+f&j%4IEL5n)>=+*_b6=sE{OX)n>8bEwD+aQq=7Il(cUGoQ9t zDA(B#`_c9FFVU7PYMzNH`A=vWs%B7@8Q5!2g-}qLLcybPeGFYW4Qfm9%UyaJ>UZ4?cT$#BDg{}J7t*}^>B+fB~zqx^ERK#7%cFjGZ91}-1P$W3w;v?@@h(Q+vyR8{KT zGLqYjkiNGPOpC3(9{v>+WS3TDrHo>?UTJ?Ev4D}C*3l~MdA*ag^>1J(=(F~qa0K1gmo)r_<(h`u#LaI+rW!!hTT&db;zkR5JJ z1c1v9_}qe$yRWAf%b0`184ycMGTUOrN{$HV5|PFb>t@1rGEy)w_u+feK-e2Ef#dwXBz|2KWj{{P(k-#xumD6L zJyE!k$MqE?4l)tKtsyBe9Z*P(f=U}C_v+o}5z}&83Up4UN0^L5WBdm53GN?ccK-7karBejJ?yFBuu!1Xmy;fFMxBgxCb*^mERZcEIR_xTA2COU zoyBP;v5O{ihaI4vK-z0vDG*8aYhb8+&?i9~kQG4zeicED_A?>KJogJ@C;4_eIHc$m zBX^qc1lj-4S7x|B^YsvR;({H6^VG~dIs{oN)12!cKw!dS3hFeLRA zTpqDq7?GiweRmiH#w~^d#QfDI|KKF6i;CfEC~8S2n5LGI2*R?Lm~mWuy6*=c`m28 z{Ele0BHTHZcAe3^?GNsS*-+~jNti8m9od7V*a|Dx{tKZu>^YSh zsePfD(cv}#xi)v>s_9qdkKDbW7H-t>F-aXC+7z!2OY z+J?(xjMu+FK5fr=hRb=bpy+A#=vjNtS`_MO zkSv$;yjE}Ka(+jw5rqi+dPy}lNs{NtauwSe4ooB{BD_XYDF2_Z^)Nd8XsHb`-H6{@ zTE0&hGNZ<9_S_Q&ylwl%t3+hPJqineHjE-hO~@hZma7rqxziMbWIZloW9FA)EM2%cHl zW_I2-x^g~ca9s*=5-6JrI4#j-*#7b#>@aFdn=0YV zS$Z)uPB^#(MOkREea0CQx3BO(gdVIZ3nhe;s1gJ(1w>>jmfKa4ye-CVQ`uDvucGWW zwOuuiw@t9yqIs3bE@F9GY{3g=UWJ`5*KRfxiFsR`dF5o_bx}h{N@9;H!EH8TQ3LH9 zL2hv?5~e9|zaDrrG5m;oG*K@Os1gLbg2Z6E1_NT34l%{RBtmTXN%%@TWY42S{`3p$ zQ}&I%gm`r0{m;LGlnXA&^&Dj;vh_wSNJ_A zA0|0Ds<*ghk~;I|I@;2Ji-*G05zGG~lyR%fn?8j(06oPM$`vil;}19W|6-rV?B6@$ zwn#iE_K;+DvM)kwwwKElLuo{$E{~>G&vFRw{Jxt#> zC)e=zuj^K32A7@d@5c-S4dNPk=F}LjPpSsT&O<8SOcS-OD0_&nSZUSag^d}<2< zE|UpQCKKj3xx0kK)eFqaz@$Ac%sG{lraFi!2V%)Qx)OSZc{C@dooYFRm3c~N)7&_{ zokvVkch^;1Ij=X$-1C&3m;_2O5B4AW6?-w24!LsgcJ1DZe(k>dwpV}VWo2Z!Hbij& zDy=S&RQy1XY8iV0&q@2xJLtAjg=Q$WRUZa7DFYX1(Co{|Wgq(5_*R=X4DXbhY~IHf zeyz>*aWRy2rB*9JxSG^|ilJ74HE$NDwUu7w=83Vv$-^>H(f|T!vm2ZoVShRMH8|Y;k=&9n{|A0q8()UfW(}7H7H6cl5|ARu>VVG*TrFIU`b1qr?_)cm%vE76^eD{p_5Jgf&6CaFaKYJ!Qs4{{m!V zVIraS(6$XSNoWCgFvfh!pty>2dNL94M)#lei~c>CKVSFym0RkDLf5dtN~ojI@AiTB zafpkMfX}@rzz0ico~AON)+EpSJKgD_cv=+u8Ozi3u0PPS7bx4cizaC!i3wja?&9-G zlg$6Gv~bWf5`fz@9X47dy!6U{q?vMr?m)AOCeTRj zGafv(#8Q#q$*am~(a;*L|6QaL3+uRpz5$Djg6!1^-RU*hG%kJ^+EXS{CITh}eNBfD zg`h#SFAyU(|0k_gl#d6cC*L=>o_77<6?#Dz_;-T@77|ve|21qBEswyOhiuE{_mbAU zUAP_Bs;zQI>Xb|+)Ml;nOy&vY8*i5mzYiNVOI*1nzU1vmAZJIh(or12{ML~li-;tS z{G<}EVAl?3gPM^0buuM*KDcR-gQnLi0bX3=ZI>k$N&QvC$jky0D6_XDyTdOBdV1Mx zH*2;XOhdSng8Ch{r?233$3qCyY>cK$ew~Jm7E${1Aiqz;~<1Hmgxe1W89hx)y0tD$jHO~E|-D(YT&#G^4S`K z_ZYt#fw@KVc1bkJovUC}Gj3?zpphOwlylZjOH%XbA)Qil+33rfXQDeFr;xe2fJCBH z+I{~!S3GYf-MI`9kj@qF%7xJguApVRbabbKvURUt_IJ8+DP=Gx*~OLeetIb7RX#bg z@B@kMo_Q9DSe9i{ta+&38@W7b$tbW)%82Ac;c&rZ~_#-olk$w5n=<89QHU4?Y#4663SP>mBe>OSFy-Wp%h5ps2enn&@) z0T)tQCa7)i0QMCsr4CvKub3JqqQk_vLWBO@LJqKZNO+hIe>$PZU?}j`??JN|J?ugd zXs5gC6g&#$jc@vK7Q)Mt65J#?nvpY;o3 zJOHsS0e#?@Ca8ggU{c}hfP2slIfZ+b35<0`J(7qMTefmFCi^(=35%moJU*O zrwTK!5ouX3b)CU*v3dQXWk;w-kqL7ta0gO;1qwCWBbTw!6-fnA{9Yh5EG3I?D%3Pw z(m)DmF3c-57ll1W243-;28?3A#P-aERx!u{jN%482)v@ZPtw3NE30wSwRd^5bmQO zdljTdfWe5o$fK-+()`?*e>pnl1^;EtrM|H-=lyid$+wJ|{ppw!emv#}!ej1tlQB=g zm=pg0jd}Q9K_6#S!JkAi~{lp8lk}YZ&K^_0yNR zY59<~#1N-}9zlLeF{EGQre$#_e`Vcv^ih}kLaPL_#b|QTRteMn#x|Yzea|){EoUS~ ztHP)j8H;FiXe<&N0emZBlE{qKNRXFP9mzI~7Q?J8*RS65M^`g{F0o{p41D(C444e~es1{NOHZCtLBedkg@5?MwI z3{V9I*tjjIjHtdZHE}{GZ2J)4Ho{6=l7QpgS2eKwu+lB(M}(&^8PJC{`Glx2AVO5>GoAANFq>`4lF!Y!oOCd8yM@*bp6B2HY&F?4J{n1PQ6lZoXR{eiz==BtZuwyvyv~Zc1o5 z7;;8S8$KGrzTdxp#IP~ZE#Bbn3L!(5&~FJ5O?M@eYZr6LCD@iqK+peD7X6FxBq?=9 zS-3@R`+Xv_%PaLTYc}8YKOTe-CgVGa@EhZyqg7DL62_I`A(o>o6&=fv``jV*fSo5g z`ILA^o`(SN5DBvSW)&x*%w-$3#u{z1&v55gS)4Cy?0|@3=8oy0V;mX67{@3q5LEQU zz#423dOl&CV#1KjcVVD74Z|=%={by+;c`|y;ucX`%RCY!2_>T=ed0QnK^f#f9KFM% zHVKfi;+L@9#N#FedRwyR(40tQHjfQWe%sK(BVvC6uzMl_c8`E8pM~|0=IBfJ0Br1V zNZ_GyQ0WSAn-gOfOHwCHERqDpV6V!e{zLSNZO6u=bgFV|Rb@WKrYG9z4c-5;(;j9& z6D&wxXUW4{-O(a%G`0R+nTE5N@!K9P=b{x48h;>EzjV+wG_uU}Ei5Flk8d^|aYRSD zqnTxw45)I8^Er_ zvT6D)tm3@?sVhZv%gQT7{aOc+_uOKpI$vH!%f1QOM2VcVQr;KE`P6Y`v;{^>Vkwip zx$2p?lS(hX>QS(M!wO6>Zp9S6WW_dNXN+#_%kii*=B20XEA zhnD^DxsopuOf>A4b9i3}6>Or3_bA;`*}V8-%KCWB8&1{QQr?@R%}gVB;5*{f0?oo1yGqthg~P%a*K&NyOtff{ zZB1s~LkG7J#uUDsAqWeVs|G5#-vByB%acZ_j3b$3CbQk~nNrwaW8hYriq58H`qy5} znwbUq!6OoRmZCmDT-Ppqy7Bo0pH~2<&+u;>K7f~z7Q10D2pevb7AFtvFOX0Wq8Q+) zSf@1%g#3dv--B51V%xeAAZ1RO242-3}Ta=BGV*W9tPyilZO)R zVH+Lfr;6`rC-=k8D+|BB&WlvcQ_dN5r42_u4bvndpu3 z=N!Iuo5+)9Sw;4$(&1K@a>zGpUAZ}GjRGA(9ku3*j`pZ#DO68xk?MJ6MPp4xlP}mX z7iPsSOA2J2swSeH*M(Za^y+H2eqa}=+zmV|ybGFqsA{{1R4Q(2jnFXt!>wEQ3+1Ud z%3U)@8YO4bpc~O+>t12z0Le2HG$~AP(zmMFQ{|$kF7B2uWU34{EqSwpSt{=|f zB#ol&DC+PnLKzIaUsCP(gQ_=21(o%7S%Uw&b1naSwNbga`*5-Uti_ z%O--yg#Xn|bkmjcvMF&V^{$r(I@H;)HtqJof(L&CzKEbtN=zJZ)kIgieI&B1o39*w zS7-!nxYkdE64d&z@SE68l@YoyQ#RK`PItGHTVO7}$W#eNO&k{uo)lZfu+I+om3lp$ zIhB|wM9w{p$IL4Z=#6E_MwKrjMh4oz0lL4ZRfrQRsJ&!_zdF@x%$AD?ERSgm+XZQ{ z#5oYVM+{RE|HU*kxM1p7lO8B#vCK-C3=uWNl%|G5t-<};KnIt}=nmb|wqDjg^(4pH z1HOt(VlVM#K0EiEzZ()?3;rNMy024Av9r$kyU3%Dgh#KFLDO96-2e!IW!?a;(s6s9 zGtq;vVE`H@T%IRf{PE>Era|B~d*a$2qoNX*ql+bmPN))kT9ekuSCT~`W1BPp z{Tes=sxvLN0I+bYEfho4R4aM!mY*BLm z>SDXx6RtZQb!CHs!WjJseoEk5u_^FFp=<{S8O9^MAu}FhqK=abW@h*LEwbtvaL&l3 zcoB8<4_4F>WHJW5p>Za--H1Cs+~9E{;o3)l_pu*Z=3NrJYEEi6(u~5VUl(3GH%)nc zh_SG0{RRaboE48p!Vb?FeW7z4z)z*-%X?t`se}>?@dDmap0i-XR%Ui@0p1{-1W*}s+x8hqx1@Y$|b=vXc8j? zAHsv7@Fnpi!DeTa&iv;>FySD;_P5rM;e^|%eIs7G&RkXRjaUpBrGjgt=5xJ;foiK*)$ORZ8t09( zs3?EM5BI&(s671r22s80V-_?q4z4P7sxJ1;s-T>y@kzG-SzDcph-`>f$k2sFlv5|= zd?Ie%xUDiyK8}OW3oha1g{!YlMNTdzh`wD^$%-GC$RhYJL1};$gUq?oJeXA>sgo~J zh6AfZe#bVj!Hg+@VIGscS>+H>{)`PvU#VI8n6Gy7Vd%%au~0!1U6#MseNz!#NHNdE zJ}tekw3TKaZlgSmmwA3ZS%p!0aSgrao-jzEcDikT*_0&fj-Q z&jGcuUrNU@5u4R2y?nQsh-JoRS-lO<>uggagtaN540GZ^D5m`us8uOGTACK)fOlF> zh~ZEHTTN}qQ&Ch?@q*7b_(g%oXOAbAO*P?|B}J4i;|KpompoD&VxXhLSxW)2dtCKl zD^3dx8D9!O4PR3!!i$IFAY#?fk@?bv`;y6#f)Q>m;0*{-TZ((z%aw?tLC#6c%#ts@ z0OjF+&F({vJ?c`K9``ey@enAUZN+aW*4J;ETra|93|YTxXL0o*3!7@Qm*Z?b7n}+C)?m3L-WkUm zB}s+*#RuPJ9)Ho_U*5_~G;wQwc4}{$;;;ZS>?szkJsJB_E#`eJ6byD>KvLlb88-mw2 zimRK5XmVgMY~|6IT)jmvx%o5twx1|@4M&!If$=es9sc*4#kv)(?2(Y|;52SwB+Iz% z3zghLxrRd~9e94sHQH9hb2(}Lo)Guei(HPLSj)Wi7v@baC*8h~DP7j;KNP|<=FNU* zEB8;4+xL4n-?G-tnXl+2LEjY^d@vb%T7v#-flV~(U?CGkjT7n_uU#u>j*UI^_M(h3U zM!lGu^_oy`F4Ldenn?=-GHfTc1k;rY)FM_vTbuMGa2J;V`4B$=AV`rMNhw207lhvn zztmnA3iw=mTJXI3NcgRZ!Pg=MWv$`rdDa_(H6V_UshAk-#Ta99a?2kv0ztn6U zf}EkPSQS|ZB{M@0Jrh^EJQRp{di{~{VCkf$+wW`C2IiyY*d7+?#?CpkCffCz(Ara! zI=d#_ME@;CA+2wfi)hn=2cOe=wH*p-*IadnLgduQ6NyS&CZdQi zvFgvBcj}HK?**gSpt9rgJ17XkZc|yT;WH~2JbnQHk6Zm0e zK%WEwI>2M7R9eEgKn|6k$ME@1&N7!+J5p5dcY-{G_RKRvpV(CyPlLcqww-@=RqO?+ zQGQSPM_ES~x?#&KA1@p~CIi&QdE+aIn~d=@QBWK_eK+zH<^&CALcsJ6@p!|#XQ=LE zL4XU(aA8~GjG1$0c*XZHauOS4U3tzul}MN%wC{{p{j`IOMa8+`Qn_=(aaWN(kQf;z z4Vi|!&5`;W{DiKENnNH$gAR%_OZ8H>4I;hV9X-wn zRUIdC+eAjQ1i~Xwu{!~8q7#CTpN$ZFWEncLzJ>^J81n&xwz)Vk!*Z3txIkV>LxLYfbSAcZKrWyt9sZg zrK;@SJSx%iQM__a(SsRMKyb6JUl@n08SQ7GP3@lq_`BX10pTeOEzKjbdaC7WXfD$r zZAE$SXt{s1eA{Tbrn*5)%6$TlrCjx+<-XDK1x$lTcz?9KcC>u+Xn7{n5PENPPQ&NS zn?^jaTn$rxk(6QVy5yEWjhtbcC9o_&R5;g&25NUv@I%ufs5Seqf$Ii8v>uX_UPB{@ zrOW#$-kfbdbq=dQ6!eg}?!?!%&>B6#{favl!4E{qULSB!VIrm?|8ckupQ+K6fRkE6Fj{U0;Y@RZ z+8@IuLqO~>3{dEb8zJQ$uVOCH)ZLZE(9YSBUd1@fEepw?g=37+);KZ-PVx3w+Y!QV z>)3Br3Yy@0pt$?{4YCm43tji(z4?DPfg;VMX1Y>?Y0Tl& z4vtylbWZ@UqcXcv&&PNJ)ZD|H)y&*AseN*2N&t!QQ3|x)J)IGEM&Z`d$rU&sz5jLV z^wj9-2J<;)j)y4q-Fk9F+?5ealCZ(<8frLgpp=AYDl8tZ98WPhIGjNNtd}#%v!w{M zOd%i5`sk*xW;snikS>LHMxq@`mWBzaI>)HtW~CrJGg6jFV;7Fdu8sP`Wp=Gs$EBH+ zTnAEbrww=ua+=4wonX@;%L<@Qv`hanD|+{Wk~}l-6WZEb5EM?W*_-e)*sAT zPoUxjbA_HL*L_|@8X3%*-G+m+z}rfwSLtIC4adkj0#u)$(#SIFDU5ONxzBQ;`IfGj5 zp=HylN+j9yRqR0HcX;w{eKilhDsvBRzuUMVa);3H%v(!mT6#m8AGY5cGpkJHk=|M& zwIoq(yQ8WTWuJw58>6-+{CGqYAmc{svr*+g9$cGeQ^~?)be#u7s}*xS6K+150IyW) zNpzm*nQ&_t6J+fn%qGgCyY;DVYGk5Q6Tcol{M(7n!%S&TzN(n@h>TIBy(`)nG4BzW zyst@{O}l;6gXH_$;qS}H_qpNks~?dsek1&KJs$hZ!rwPPqA&(DY17H8L>*v7oHevx z@)GnpqViOt)GbdVq3FwG&ntzCNiA&6v0ExiE`|;%j-i9l(%p!CaYnZFxwQBR=OYsb z>K{2DnHr4LTs^j@o8%N}TLrPqbQnQ)mOj?DboM4Df{EQ2;j7$q;Lwwgt*h{@%I}5~ zUN7hKNUIi9FR!-DdQA(enwOkF5Zg+Z`>ykn_{dxwSmwPGQ7^Sz#DTD|XoOJ3bObQF z1A0!3+4aN{ZLPT?5LHnh)l~1g62ci8`IIZtqbi!BGMb=RuDuxY{lQ$55rrs28N}$d zLT}E{gOLa@^++`tufz+tqK6~}|I+IAhqh+8-x5`=>)yQqasdg;e@xoYF2pr~{owMy zm%JV7^{TcM7D?SwMUNE0fmbn7XZ$2v?m+W6VtOF8>n7J9f498{xx=N@;ZJwB*BxJ? zWRy^8*_bz025eEzICe{=2ic{@2NVi&NKJ^#YUuNM+CZmsJg+o{2t#n2$GdZ>_Gtqo z3^%+ilpf|?6)e(%HYBiupL_lBk4YCs8)Zb!a|Jr8JMQ*XByv?7E8vpm)CB8}ceNK@l{Q9js;IyL6Yj8)3mrGw z`js5wN2zeBE#*`ZT(OK3#c=uKIaMTAtkA<*(7Xrk_TYMfRdfsUMNHJZp;)R(a+ zYi6Gjr*OjB@QBN$rh?-LYsM(r9|^T8DiBKO4PT>j>zuTSsvf1rtxOCkQ+>@9&{+BQ zK9yMSoc%RJze;D`&rH&2kU8AfOq5yg%!%7>lKL8nQoEw5uds@uCT3HA^CPE2V*N+; zpQDpdNK9FP)6Fk_Rd!d22)A9`fp(3tM8lP+%1e^?lF9axiH?#4-5=kB;WJ7bHogZx zKO;1c=R&E`@&K!9xQG?EvnuoKQ1(n8d?Ta9jnnP6N!>>rtSZ~$Lz=0at;MkM3yN{4 zGPkE)Q~I~iMqI1p$S#FUE8VP0J3R_93S1@WA@a>-s_k7PJgYVNpLLQ)ev`=C9#6iB zOe*GO@fDt(O%@W|}SFG3DBIx}Y=72|0e zV>u2sjw_jJ0$LDH$8Ox31w*) zUR$EXTd&fETUfvwbS6V#!#gM-kEIqjMMb6h^mKrokXA*kDLFQ=S-gh68ymD(_i||W zy!+u0)$kI|f6*h0d0DP-IlSheuj{P3vicN{WoyT{2$RdgJ}0bHYQWQBwM52m?kx8-SdNC9^70x$u|%3opZS^#m@RvFAt0_-Hl*~9^umE?ka_dI~pL%_L2+2BVPQ`W!h4u*?t9O4c zy9h40Bmyk){_z|eod|$M$LaAH@-*2_6cKJ#qd#u6Qbu-a^LQ?YBB=8l z3k12yt>ySKTllvm5^FB(q1%M&@G4?gE zJu5?RHrZVN7;!78)ObsK?8rtMXxtVcJTqgKI_d_`Y-%25nVi%34MV>(J8`o~hL|p$ z7!uMPFcabXmmWTf2>U(SKi%U@j!Y}1Eh&_ygYf0l=%K>t5%SUj)_azjBV6Be969I? zWgH{^jLxSRP2a52mGg}MV~In%&TUFf-@MWiqi;>6nqqp=HsSY!r8cAQZOF8lj~1YHiD zwn?J-Hk;^aG2Vh#v>RznpZrw*@b070O#D*Qrs4hEha+0krm5oLrf?q) zYu9a>syGcOPE|OQHA97Q_7ATzF$LCjOC;T|B@JY2(W;iTs_7H?B^(WgEMRxJ_k$}n?oA*BW<$-(Q4Fm)iNjU^B0a9m zd>ht5ebv1t@WCLy#;&0XUXqNKU%0*e!f5%+W93I~FF!I`{>oVS$G4Y%JX*eato*av z%Rd_}uM3wO_wOg=S>f@O@gMBZ-mtE^tl%N6#ppD%q3^{yuT+n~Y=@Im{yRoe)g&T! z|Jo2+biMX+NSo^O(0c1;wS2dU^Qkuf`3WvwoaWG7TF$ZkXKu&Y{8?yXh&Mn)$)gyD z1u+~QdW|}*csBdh?Nyx#47o3%P&0=}D})*}(6BM%5#*v-c1XfZy*|ElsUZJlLx+_E zxgr-I9-nM{7UNkS{)KEfzeSt9iW5~lQ~QwrG1sngTDDJYyAX2eufvN?Pxn5m^3l}t zGQG^c?J}npr@f%x?dq!SVJ9|AN(X=*g$eQYFn2-Zd@zvtaJ-}fc~s{l@Dp&1q|xeq zY{Gdqkz8ScFPG!R)8E5^G6zOTU_N#p?@mPMwSbh`@M*)OP=KEiP>W0N53!%(JLUPb z5?6?N83v%$ro0*0?do77Fox{cw7QdI5C`t?3fzi|pa2$(0P=^I;ySt;{<~f_9s?)W7L3u3?|D>jt}4G!FZHsMINFFZG_RMI zBe)xzP|i=mmvTN6(F~l)OT28NaUz~;jP^L;OOnwZZ;U|5iVP#II4w3jeufy;D+9?% z8$K1(qwx9he9F<{ZndRUEW;fq?oz~T_pr&I&*^D9I~iqIS7C+gYV$3637WIIjJ)0` z0i5EEe7aFen1IIxV4qh|&xq1h_6hVuY{MP`$>njF)^IeIgY#WSH<~WUbJc3u6tSV`I@5?k zVyc)XHUYp6Hp!j?4>U@q13T^S?x__3Lhdl#zC|GdHxK{;{|s@Sl8_{r5ihl0XigyrK=sCdS-gT zB2s|AzD25~i+XTTW`9HyMu9+tuwh*t3FOQ$tRBY0-Un30Pq`zgGC9`DZJB~W5!e*Q z;TcBiwq)XoyD%R69~w=Ig=Y=GD18E+aqe|3T8Nl4lh^T1>2@ zh9hhE33#LI6Ixh9)YQvno9#4=bEb6AnLTPmBPiWYRw++fcx1Rbx$?LO_jHOkx3P1F zv0{+2O*F{KD4tU1GUibTDIm@?S|}htoem`Kd>$Z1W9erU*A>l@jt)IDb;GCqNg>at zv3ssnR=|%Tvd9Go0YZh%vVJ!yXi|FV^m2NJT^;%CGhRAl%jz93s|xDd3Lf&+{%iP? zMXH*Yg9X1a)YP#B54EkHxtgQnaSV>M<68T{S#<19-~$mp0tyO{>hB$CrHRlSwM1DO z4gOS^|G3H3jLTGtC_SV4Y0Qqv8Qx-035#gZoF$6#{nxQAmR!Epo1!{t9!i@EU}iY`=2KlVJFD64>R~5_ znbAW6GeV=nqQxGNS^fg~%9)&kp6gtFRw~2UCBvXcJMQgW#oVEb!~lu=Ixr{69zp&4 zpVOo_51QNY@b{MI%en`6XEy` zG;}PA!&jiIV^KUv03dVZO~IEsmm@Ee{9EhDOSen)4lug;q&NWostC#sbCi;Cr3Xha zoaJ!-u3}LL|f~ zIRM;I!sz}^U<}nn1WXY#oI5gAZCqPhhmVaO{-j%_%?!5vpFyig-RNDF5H@N}a^LzTI(P(f)tz(r8LZv+^5C-uY#SGP&$*66mF?woeMwJSGQ0949YSvGNgU1Bi7r1r0U63h|98&PN+&UaPAG zF#%z_#P$WS#6ln#xM4XA!`B_mlycua_GrrJqn6E57_MB;a@H7Qse*-C!^P`shu}eG z)QAfTv$7UN*%yl)Kzl+(f($T5M~|tn6E_Tw*b=X8R2Dpdh~7vI7kgDEJ1_#gNa~Bg zZkt*}=v+z>B9=3EG<-f%R|^#dHcGL6qjJ^+-iRF-`Z1H4p=V8+G4wkb$HbpDzB!5g z^g3n??6@(xe_Y2`Vtfw;F(G|mU=rMwEtKKfRm>8tib0OpUF!U36!KA>AN|;K#3dK5 zlFi^QlbA=1myBZC+7j0H)V1*7%QCji6><) z`@(qPLA)LJS6XIzahv5K~fy6ky34XYsGl1i^1*k`My=F$GjZX8ysjP|rRWI6|SHQFJg@x(~P7cj>}Jq@|V5f)(JX%ARK zfI*01KSUVt4>A#;ppU|I^7Hf(UXZjf8&9o~CoBPb4TK>Dwl#<*dLtl>$wEefEekjU zWE3K-OvKy+;8+T(p<)E$U1y94QVX2#d#=l3L_m_|Wq_MW_K-O&Kj7R6{sMMVm=7sz zj0M!68E0o9QgjVzH_`ou(LIU7~@kE$*iFpf!QrUK`%9lu53 zvwQ=iv%CYG;eY|gspD|moI3u@xH1>64bICb{Pl6F0j{TPI!ue0!)XX15I@p;)`$On zXH^4ddtf%$JNR!kEsGxU_#I*~M??lGcI`Vx5Jd3$O5Jq_ER5w;q7$lO2M?aM>>avO zK2pnGcSKOT?xH&-IGmG34a%qv1p&OLwl9|8n?phMOr##eyx>kcn{8k*uj+)(%hwHg zSHVPq+H0^H324R+|4cd66DMw!6?~}GrG~c7VIx2$lZh+|ssL&+QrU+9RI3Cl17(dY z6uaj-Qh7GZTBY^vrDY>n=elp`i{p`HO{u0S9~SCS3jv&EqyFl^S_3rWo*;* znpfIpy&DH|t35X?a27xxoNPWgS!V*_Wb7XN@*HREgwKBlW2+4?No zH++L`d&yUUZY_Vo(6H!OPVh0Z#gdJ^^yQJQSJ}^RzVO+N7Z@%~PqG?{6g^?LW)J6pTw)6M_5>hLk8v3qOduHpj9J)f%0943FK2!E%N zzk<$(p$!jRnd5F$R5!WQ{eq_iiD!Qw=M40-r%nM%J&}5MZ`j@qx&u~xmDphb6~du& z!I>xtvH$)ZY~enKzb|b4+@d0=Q8pM{m#@4kPDird)NJi4UZoExsM)Id?2~P)u$zP1 zl#3oPs_x`POPNOJ9J+Hg<&qD(VOhAF>B{7@-J2{=k=9!bSN1eEDq|BwJxWDt678Iz z2q;Bq3AAhlb)U!Cc>L%p*S=GMZSX*7jc^~9de&h4$CQU8mSixqRD=aAp{j>cQ|Zdz z0NloHmkYYqK_BL7y~aG{E`cUpbx7v=+o{$F7zyJl8SmGdKeh>NXd3IxUAEZeF zoN42{5wzy8{1k1up9Jje{s_s%G>4brH*g*{d2y(K2ULCX=krxE38guVDD)Pd!fUfm z(XwpHwdcfw1L4pOQ$DtRX+|F#m9~PRK!#)~iyxMf&OhT-Gvkm=45I zgTB%F?D62`-Xkh!asjvPvbH|z$ekXV=`opR#n7^ul*u}40=bZWQXAt|=(+=%o>V<8 zn?_axE(3B+PoW~xB84!gLfw&o(Di&=loM+cXDBAIuA`aXCiVri1+;v;tDLUkgNw2^X+lV3;iIHf9mH{B6Qb)Rk-cTJ;yCz|Lm!up|1 zh5qhYYQfzxRidd%H_?!~yZ>qsqu#8SmJxpIoFdWZ%=3O#wZWr+VXD0d)+E!r%QZdD z^m!IJftf+1GKuEuzV(iF(H=j7;eYkZ(c9NToc zA!&q-zA=1Z{1wC;(4=Jf%W%NaD{zJr_>KP;moYW4q^7#Mh-zd46Qxa*6EZ#v$%a_n z5ddKRu2YxMVHg&E!)3exceb&25^K0egm*?^m9>i1U+$fbW${SN@16826h~)!L6Pa> zy|6`9hy?@j$-NQO9L_3fq>U+aaRCe3Fns=PBZ-5WoQWTdcs9)*yo`m8%;ka6C$0jo z!(%yq6&5m9G8%!uy1Ksg9~c~q!P21>;LE$d=$cZzr2+>M3DeK>*Eg5jfq20c}te;3*((qm6_Pt2H zr%-O#pj<(fN|rLOJ?X}S!;t}f6p#=lq@o#LXe2>&n`tk6`6j42T2i&ajXdaPcs)iV zJdwK#nZ^-<+F_#|HgSbxox{v=-7z&?2b zLF+*4|3`ddwk^YB5-Xv)S==h={{b7606(^W5c6`=)gYA)XM8%l@Fdw+WH9H(7~$HQ z;QI9m|NF#+td+#Y-u63iMqJ0|R^wJo+2V&GsZ>-OtJN49%p1=r}f;B+3X`6S`oykbvbkeQ62^!=!fUn{hP~`3yb#N3Y zXgCOn+2B+UsR0HBVge>fG$$Da(^MG~Tamhs`&kf4VKjFGMoS2c(oXo-6BtzrFxo|6 z#BsR;b)G~tB*X#%5F0*nsb3ZsV4$J%kR-};lsa5JlI5P20) z(e($|?z-bA+=zpG{@+k<-iQGUTm>lCB3*Y>mTxfVQx|%umNkRkhbL6**7hSR;V4b^ z|67P2d$(I(jDq7foH_E^7^Pj#jN>9Svh|x9>C7*IFAQMz*NtEclKb{+?AUv%hy`q-K z{2&i$OZN-IBD~7=S)c#&+u9{C3%7fh0Jum1&ed>RyS}$WA-oG5@xHaReK@oQ7SMyp z2!Nh6Q#Q|4)ar$f9*XRL@5cQ1^!eZWFa2nQew3u27jNq)+=u2Nq22ZGDr(i?c9o^? z+-Uc;KL6{twR;mTG660Ofy>jkwM!Adj1tNL*kobEyDU)1Q|7A|Y>)q2?p)%Kq`M_) z4m0hDK?+4ZVGA*^kDX3@&Cp=EUu>u24;$b@}k*(@m&OE#O8 zn%^#)MMArnBVhb1f`kH#;9fW<&{UaJkXN*z{&G-5DssHMx!NsZmU^NJyCfB5JC;A{ zmCdbqa#ifR5?DB`IZe(UI=f}AU|CHzS$U%lFWV)|GO1>xyrO7F@dFO&TxY5h7teWf z?H^|0o`Sr2fB}EgOiBnAMvsXILhk%wa z5)gLcFuz~W=l|s`@D0Zo7tro+7f5h!#vMN{91Po~xfRG~!}e3a5yUn3cAW)=jG_ly z(Iz?io>wjUw4$8*_y?Tb)9x9!8QbNS3$1W^V7&HmrS&(~H?z-w=g;^5N1=bYJ6T?t_7Zt#7|6uSC&YgkUTHx*-lwv zC~akpH(nI@7}jKiL(fWNL~Q;dLJ4fF%7qUeOfgAXQc#DYia3YiZ~(UOXrKQ-p*8ZB z{nyt#*nTSXr3f~Vheet+K>-D{S%24d_P+0$r4EjAq}sqRNH}!(z+isW4`S1l_b(e8 z8(D|a_M8`9>xfMA9!ztk ze;16@cOWlT1aK{wFGeOX?3w~L5MdB)VLj(w76gqjWt*mT&|!|)TN8UP$KPWj{7J5wB6qe?MB~d_e}pStmAeXHYsXXh1-qp|JBWQWyk%B zpSJs$(5~i2yI=hGcCjD-I^3?NH2-G11HJz9=YF2H>_X!+$jY|=e7l+{LwaSc^*o#w z-SZJLzCU*izU+}+|Iu?}Jg3KZUhq3Jywy+G&6J?PNVvo%;6i}^S)S9-AE3b#62n#5 zF#-a){9>#RS9`C2|9=^KvM}~cGIsCJj~$|yGhR_UF$|MT-Rv7MVgK6eZ@w}1%%rf( zoWRR|FN~iI3TE(Gfdj;I|8|ZE9AN+4>wope`|ygK3VJfE6kf%|19}qf5k4=x$o;c( z2aa|4ioIPHh}6Jz43x+?Kb#YgEw$m!8}oPd`q%xJ`G1R0NN$CZ%-{ZB=RX9T_%htA z5f`1pE=+KEMX&#fTiRvr86#QOAv6p3B}8O(E2g>gY1iGiHjZ~eqplCmVboshog58g zRL(lBAvxT%z{?-#^%vgK_APlwT)TuZPbFj4-P$a9&-~Uovj0e!xH1WI5Zuj`)DM3I z;#wB=M<{%Dgdn4eiqk2u(Y$p2{75a=-c zWO;=-B=`Dtx6R?E4Eq9^1N_J!TMnN15sgFccRf#F!$f+ER61N$kM4hW^!io*rM;Cx zduq~N@6WaO*jRgN-MAa=UHis=ec&cdGtHQWd)s(s1DbIcOI*71SU|#G<6)ZSE*6L7 zimo5GZ$9;n|33p(33zunlz%IBtb3H8OU;C#IU+`Ce(wbK6a9rl$ZVg1ME`q?-B&uB^@&EmnG2Fy&pdLZ$%AfXG^7=Qx zKda2YeL#T4Au)3Z&{#sE5eF8Dc$%)xO^r$DjHcM%oFRpx<#TvM{GGBny7LzTh*M6L`2OwfiJ~ zu%8cLIr%Kyd?VjW-ih1jEB3&3<{(a>--S~+3UqK_fSD*TD9US{uIm>{K&wE3aJ$@8 zbNc|7YcLy6upbWqQ6Tn(UF8tqyK{hH5ZH-0$+n#qVoD&f9E?B&E<{mphvQ?kkHGz` zV26+op|DNAqeo4>^XeTQH5N22emqwBMlOWo;TOf^tOXu6=Nl#x;o61~Ycp%{f*oHG zpCwn+?F$PztE7Iw@wteTy}MP-PW`6+Xqui5yr#fyk-+rL;uA<)k9<<_*d?~3Z|)&K zA{*6M*zP&Fx!)SlOPD+0Q+Y*nMa6MR{?*#dNJew)jx%?lx^3b&Kwel93;cv|(KoB$ zjWe+#sH)iuNMr>Xj9BXqk^zahJh;UaP~Ia2@4>G`&RO0L6{h9wG1}?x7-s(pAsiLQUJWrZ2uDRCQO)qTkt_mhk##YvAU6te ze()Qq&}c(w!1lw}T3+kGo$pa+T>ON42Jmw-3hU)wC1nBW*7it3Ox7&uakUEkd%qui4cKa`UJ_t72swIKc2@A zluUzgr=$)kH!8K8*e%<&pR5WfsZX*~<{iNeD%B_r98m@`W^G{W4IhiXRH3Setuu6q z4y)d)I;rq~5bFJ|?cClgzOzvo?*;sGoBsOmd!^^jEcy4e*p@Q`Xek(}qMDMay~*3B zL~Pk4!)4zF(-J<>xmhatj9CU6OeSH+nF{ z{ZnM88~L|Jkml6RH`?jH`b7iTc~N${h3EguzqJqFdA^0M`Pzy+DI~D!tF*?rJ($M6 zKVW$A>kfK6mrTK_G3?O@e1xYX*}4!bh^8uGzpSys=Mo+^ag;Rz5s2I+w6{bI82NmU zE;!*~y{vfq+jQVS3lqageGja|Ezq#eap2_A2iBc#SkV7qLaJ}4dCx+)raGjJK3~fA z&nN782dQ$mKRk{~$fjQNFI}#6$$&Jj)Yj}4Yaz4eKa%{<7{m|aI0XZD|w$>J_*0xsb3%+pw-?=v+ zy1UOl&;RGgOYY0eoS8Fc&di*1<{ah<*DBxqTh6i0v#H&Gv!Nen+L#?&_r}3F>M4

`2l#_fPWwh2wND-MKGpnzy&>*3pPJX169BJsrbiao3iyKlF2v)4eb-cSFw*8(ph|CL-0Nv5UoU zlIF1~d&NwbSVHkmU#;*ZIA(*nhc=%IV8amt*nCQPhximMB*j5rVbCPwDN)2GF|$~4 zeBP#+2CH;(eDUJ<%EHH&zW4)tx?tX%G8r?5>X$E_RfwvyIqxQPJAWg(oo?(6sl-6G zL>H2n3;&=Gs6jKiKI9aX#MS8!HiSdnNT(p0Bk+cQfUM=f-#A=J1dq-^Jf8Zp^9h2- z>qB^i*?_9xr<{D$2qK*lDT@dR%%3s)=+Rc4zg-t#*9F$SSqf*&1}ejbim*xLQ&?o< z^XR8Mp4)K-jjWUcndLFh>~c3*2sUMuP4tSi(V~#c>;dvZDUzHC6py4oQOOui)pOwSFYx_zyh{v_m%;x$l}HD&V-j`HwZ*ajof6O$Ov9x; zpe06c=nWR-^eFF;AnO?gXj_?Du}WfWJLP?`1YIO`CC;MD)N2Zi z&!2K8kj6^U*jbaYrb0yOpEzCKm(Jt2fb7lgetnd*a{-4uXn&zh7*}5q_X9W}$Vv!Z ziz&X<`n1X2h~kv~W#?MB$vR{KQwnvIz4x=`h@#1psLFuig*C* z00;j70YW|mc(~GG70b%SSQ`75h<(cSekFR0VaA}BB?d|L2$g7%>GeJth;MP>q;mr) ztJmR=vQXEtB}r%uKB5>Tr4XQ%ggmX2C0$&z|&tN zJe^Pn)4=<(P`!TA`Nj`C%5?&z3t2bcfHm~kr^4I&j)3@Z_OnaV@>7RE^uGnQ@Jqr$ z1rwo>Kb&;F@&m>T3`EIz>2>r2kmbuC#`(In4~MsRIc_MPrTWBwg;bO3yU<~Uk_Pb# zGrtz-9_veQVJHi)G?z9Q|M3IHk0JVDN48S2joyQU#3-bX-pTsy2-8`9e{zG=1|1i% zW-&N!;D~ch`t01Ilc+xNKE96@ypOv|A7=lsCJe^564NIg>S#D&%hvNcdJHJl;J(5_ z>CnFOX;2d@(a*#-i+S9);1`MBQ5;bU4P%K;f#7X0Fm-n-{5#1K|KfaD z<#N#Yo_2K*4db*tx*I`S*u?4w5$(z9D64t1gB%};P?rXeL!oL% z8T2P$_c`ExJ?$mPQ(BTo6BSEzoCGFW&~&87ym`EuA{LLT+oyTQgF|ujuujR1IO%+N zc-_bGb$=YghQ`RL9!=Sy7rbJ9vN{hQ4#n06%yX(ti3>zd7&xZG$ zM$DWEJu|CmWI_moG{UY=F2*z-o~}=$kx4J2rf!#&JBnFJ_X$q5|Grj$&sZqkg%i$; z7YoVWA9D#hve&_Y-q~slteK*cnRE%?71gqcs~9RJ=#RODl5(8_(Ze<{e4CKE-~#qO zd~dXLJmXv7D}n$1#@isuh*$PVBZyRB9Ab}6W$P0XLHy28ruiQrE_b|PVkzEer_#9_H z0S*l1FC8UQWUQiO3T1rl^ad%+>!N3&%MC%I@O(p_C|pgz*w-;QKLwvzl*;l?I9dhY zNq>PYf!|qv?B?F)FhWWklwQgxexY!h6h|A;eXBZN@l`ZG5MKIre(B3+x_?FK?p(A< zPBz+tPZrvu5TzPpm5=0o{5rJpEgVR=BTDgGIkv^mwb(n>#93ZE>HLnUqI<6sUv%q; zsHx$1r)@C5f+TVLX}jzM4_-omhEmwd zj)#S--v$YB{MWafoG!?CKS-TIG{d>lZ6R{le2r7hhoChNTev zB-wKr!l&Rhfbc0@AmY!aW|++t_12NpqVUt!T$w$F$~M`L`MF~KYa4(NTSKJ`E+bcT zmLFltV-k@9dInukZ3FabIjY1xu6qP! zJaF8c9#F=lZc~;-56Qt8>J>OS_a?-dY*xmAAA+JXc5+z%WR!H@nY(Q-AwSR^W(eSP z`veh_N#%~@SR7blwoiOS7?0>5(=#0ld`}+FbrVQfZ;xDfpUf>I2`CUyzgHJ{F?Yws zl6`+Dhhf`D;*{m>{JC%a%t{ZM0%mUCwY9`3FY%k41Ks&VHax%drSCwqV=1_4LPs<; z^csEpW_7rNeam$L<-q}s4NI3UQI!WujylcjBM&!Imns6v1==pjWk6NN1P)uQ;<@#e z50oh2v&7F8<6n|1JLUvQhqo8c?>y?nBb4sCpt1+NO8!JJEt_S5@65uPi$Ua5C%Zo6 z$=a0P5gWWFS~dHGb1w{ZHg{bkq0C!|e+~2<;kVjN&SViA>;kQ-NMZ*n>b| z1)<%ERBq?@HYsQ~1hlIG?LK+J=|(*5&40QEez(>{XjeMO@6rhECV6Rh)iuKJ*3Kui ztG=Ih_4m`Rf`Pb%=XWyKTDc~RYY6!YB&qeuo#RDmp@_jFX7(utpWN^X}LnNu0(4m+#;_dv3x4x=QrVJt$79tu^HDnml zgO3Kx+yXlDo1D@>$gG<+d_ePb2E(f%p3~$sO&msNPJzy(gvwTUsjQlUISGhNZfqRz z5}9~7kqwd<$ZC+ph@ERmG$F9$1~znN-ps`de1{R(uR3BSYZR(ajyvNBf#Hv#Yb^=v z+-d=RReR~H)xwH2)psCs`y>PY1$V=@6NM(quRVIEdmoqZ-j|KUV35!oq4EwVPi=|| zKQkW@S|e-OgzpnYb?@y>=sw0qB#WK4n|%0T&q-oGU|I7eZ^b~?p0hwFFncQv6(#EH zge@1zuUq-0I*NLRh;Uu%CjnytVrIx8r$ih}uTU38ad4jPS_zpw7RMZ zBxDE@HjejvOhnX*3liPhV^|^z;Z2@k!-1anv&$rGC?uxl-C$dg=_U-ybS3y&5`;Ko zREbzrk}blKkdkb18P=Bx_(J5nTlkuicFy~f*y+h!>QSgE1~1(RTp_>OP9ec8gem9T(-;&F|BO)SE5OVsL$S|U@j z(c|RI!{ECi52$)Bz{8nUw3F>BC}Y$g#=xZJsdI49RhRXY2ri0=<$c@`dJCEdR5OlY zSL0I8CQWO<0|R|HH02u#$Dr9ZhPc^%8UFEPr--{d9RCf|f95AR7Sl%&LlmICwAa7x z2r4Aw4gMZSjh-6ZSF5h}KXhsOaDUoF{(mfX&_>^qbWA&RKl-@vemXhh4!raJw{=7I zru-TP@A=<3NE7&7|C3MP!aJ<-CRrP&7)Knh+4-Q2arVPF5MkfDoS&f9WlYDTCDCCn zX>i=`1L9K>b_BW@rI36-3i&8+zVAuC?~(6|p?stMRX)ov#}0@auZ*kf{IA)p#?2t6Xo`k^v6s}02cX$j-L+INf*M!$r z?dq_YL@_*ZKQ=xtGFFm2#czDfmJrpEW6sOOfO0Qpd_*U!Cq%@%*d{h9Q;KM|pb(DU zH%JfArkh;PaZq7Q<3+2OhB;Yj<~KzWUL8{jyzSFVQ*Yy%kS0x?0{l5}-->G!E|jI) za}2(?F}Sc~n}iq^B7&F-r7lKqIT?Y2j{OzyjHZS!wCWa}w5o zuT?wYi_5B$Sr(I0La}cP|3fFrAsO%H>-(O-Y_`+Vs-v*}Beuf=B+6s&xkS} zqY&56P3LQ+kF6&gV-cmM^ONikY>*(tFPxM1_3Xd`+)7Wcax1m|YF&XgBz!%>ymfUJ zAZXQ(_VgT_R>;68=E+{qebXboxmXn z$NS^Lm;&A#?r_RwIyjVwi-k5*sXeIf^58Y;>(_X`0lg$EXQ$2b+288UhWX>_#;d&j zH4-7Fjz=31XH)&=Wu>j2kB1SpUHvd5+pdkoCAy!QxPAqbRVzJ8K1>E-WITOB-ZCuz zlO#W~v4QpVQP<{$q9~LAW(zm5aD~su>_j{jfytu{-n@+g&9;X4mkBUFJ3s;;6kdZF z__qH_Xlug&Lb=eCI?@H*LVILPyI(j7iw9?Al^2D9k9qh7(BlSNRsQhz2VJ88%d+Di zo78lTDA=<9sPj4>(~$g?c3va9Sj#o8VdFp0Kt9H(&{o2E9}(bM1~^nV&c+`+KzWv$ zKe0=^sR>$|2*YmlzxpIc4}cJ8_&}piQ`CE?jTQHQC(DDl#k}70G`ASBb10!+mMa`P z>Yj4=hlU?H&?t7=0uq|!{9F59X}ongPTupjp^s17HLS6to2HOQa!7A;gjDD-gXphR1E4u1BY=PDn-WcLqNgr|u$ zz&93(6bB4bIp}NP)l6_p&A}Va44em3LYyKCEM^5fZ@vO_d0T#oYlsyPHTM1bcK=Q7 zogXINh77cG28 z9Ua0OGPKGYzTn?}G4$5*8E1D~;=c`6v|$nFEPjc=@!8bl@8}`b{Me`Ac^`Xy z&K>x;{+hB};@~N|)@u2QbKc}??Uo<8S_4~V)sMAYU#)_ORGa0*Ko-d;L5^s zv&Mee+Nos&XN^*4QoNf~@Gbjg=eM8kp}QP8n(`g0BbfUI9ir;OVJtqa+B}S9@@_gf zEg_P}PV_&yA8k1TJB!7*KZf58_&tH&KK!1-Zw{dmBcEOI%Z8kQ$U zPUfF*n;eNdSX(%-?)HIrfpBuYS|?F`a(FTpu#~$KYtP>ZlUKncA3ZI$%zww6PAAeL zHI0b&RE;Fi^6nAmNg@e3fhASv37+rFc?V&uYQ%w-wMU#s$+yqRx5NCm;&;qyL|6*6 zymQ3)8TodAd^<$GSvPuWq=A;zN1UIM42$(lym+$cgDu#7RAuUgYY!VCE+^1`OGrqOtT3X$~_O7#bB ziUs^6+~E-*Rs>G4JIt#^3leg!>m8g`ES?&w)cyK8^k_td=8Xnd)qig=I7`q!^bRx1 z)|bK3_5^=~mI$|yJ<-7>g^o^moRmOnBPPY9JFOeJ)Xez$biz#Zv*BcHwWvH{{4kIS z{|V&vPub;Oh|~#CD*;NnV$wZuNB;-7v8zSTC4>yYRUt0n|I}3L9LjR^Q#J~Kv*eaD z$FajDFdrKR^PvRMeK4zT3^g@NTvPH=LjN@$wP903HM;B9*x2C^T~Rnpb5E>2z|`&j z)as-Fv{s_~;5ZuwRqW?50GfpTmtGu3P#iou;agHtIzh5c3?msT%URW*niX&6ahxSy zU9uqI#1P;p-LY%zsNsNH?~n0E;J)*z)#Zh|{fZNx2++qwpa1UhH*w;YQ>_?mw1^Zt9$Mx23GwDZQ=73IKe&{_ zx<^%X+(zueTv}ppg-~Xs4suK77tQTNI#Pckv6gAu-ib zt0Q<8!pmUvAO(Ih7?wB2n`fc-_dOx6AXXuHRd3%BXsMAzHA8hsWFuat^Dp^J?C}j^ zaD9GvPZZ50tv}ipimMn`FXkNZCRMtCa#2!nRD%8*tMMXz3PHLxk}_bt=f|7#{lT#D zCQGdQiJ&4`qFDCS>eFHWz5SLER$Ig~6(+btkSq zCH0QMSNY)}sk&;;Cv`Kw%F}{Gw}Q*%$_04sgYbfe!Bgq>Uww*12Su7f9%8MNaID(+ z9Nw@3!}z<|iv~eP>HdB-;y#d|h2by>pLveUeY}hf6TsFDf(;x7cC_xjs}c8s1^*a? zS}VCed*L9^NS*VafZp3q0`oUq?ssnu!hGRh!+hg^hADe-!CjckuNoZY|A5>?E_cgq zw33jIfq>-s>0lX3-HTT-``(M&dm71RtrpL_o4m~1^R3=~;2Y_<+nKovPVXQLRd1ql zfBQL<{szq~=v(bD26u2XMm=nqaTQiKq$lOX^d?=HGGK^G@|02QXFrFeWMslb=c%hO zrx8qa-XyeBD6jgZp0`@9f0NKolU#Rez_6CWErw|7=WI4Hwf?R6)FuM3NzU48#3Oa*2UxN?!(8Xf_X;ech~-#>yhc1qcV>X^GSYz}Vf=YN zKZVZ<-EqRnk@MEk!LgY_h{$2C5r^nL^M3pV0mJxl^ceZ(q{z1(@3$WYzfHzBOU2JM z%S0KU4RV2^!iC38jREE+kGa-iwmHlzJn)TQS7~=GGS`yZh7+8!-9=jB z<7m@asBct9xl8QWa|+ zsyiH(p|P~;&K13gCTr2#SJ-pHg1L}iqGvk!^{bcP&Zcyidy^4T?lCm0CtHvo8bmZ% z--pB{T)cvX0(*{7rkJd0Y|g5i<`rZq%f1&eWEIhb z;fIdRJ#huo3ws`=v`WeHq{&%ztNv{g+1usdXOR_7VOeN3!DX4G=TXC7ltnb`q%{So zl_HxnM8VU)$e?)|dQS9v7)?s{4YEmjryV27Q(PeL z-Gi$c6=(VD6-*iI1ys3%pETNGf9-gW*oLyNky-0)=b-$^CPme(S{)2Z5Z(R)B4)!w z2w%oK|GtcO?=2%!;)>!cbo@IsjLdzZV|1_IZ5WTFyI5oQ-_x!+RHoFjc0m8RpCL+_ zNl)zvw3K}YUqE1&H^DBuoWv@`vi7B%wcv0rw^-t6(fPFlkBK6hpF7m5@+<%8bco7$ zRqFz+dS%lp(-qW|uo5q`@I zvR2`dh$$XMnS(qM@xlTrS&2p!djy||23Ac*Np>&DgcPCX^FUpz{ym?IjES-V2*J&E zmu34veUr|fNj4UEpP>B=?`>ii1{n50e;sg#Qi!9ZO1k1M#M*$b`KVu6CS39C4nR+L zIWBG5M5a3}-`l&Lq<_|+&+FI3E1Uf5-xd}dT5)osmzNM258eagEwFz;QGOh+diV-N ziEa_yRY=_D#DqU$3A^Iy2{^br0I_3wc>yEK%k7qsZ0ZPW9d9i(!@)6!`HtM<<%jMGvd1(n4tlYz0yRi^O#k zQy8e@Qbft{mK8oeMV+*jPDvyg&+O}eGG})GlfQKJKY0_^0Iu7Aqf*DdAWfC-?SE2% zi&9clxLmk?eV*gK!0!=UpWz~KV$j}4a81M&1=tz*O~!Q_c_-s{8m`~qdN78f zX5jbT_V&2n;@5<$7}pE9;!(HfNP1lUNT>WYI*3ZeW&R^YLAXm@`Xk4UCeP3dkbjr( zYyLZaahW;1;9&Q%xrx}sbvZOG>~{OU0hdF~%2)4VtZ96}hSaVz;jQ~S+gEn6l;6&- zX;iAZt1j_%U#6c^XHhF6Ul(I;rug+dya#7edOcKZe(Lx}PrTkUHTEotF@WzF51>Bi z2m6SHH0Em+1-C~cs4m7y44sH3mKl;F$_h-@WImdr&Pt@72w4{yQ?8;tX#uG-JSAQJ zyF}7aM)PU47kD<%o`q8CIRA~vI zRia8uqV=U>0bEUVUu7UFli5|+%NKE`@G>ca4UG53i%_bH0UL3l?Y;5V%d5Jm!*V*j zDcYg85ovznfQ#@sSv zeZjJ9Yb|~4#ivroTPG!U!)&|ftyWnh)5bK(s!41EL@I`_(Aq^%?%NhEkj-@mrM~QG zRMjrpAS>Rkgl^fk=xo^jY+F*YsJen$An(2gYK^z(Qf<~1C4S3l1EOCnNIhpATYKTm z9Z}NG$KzM(QkPhds+M-`VK<1D_MBg&`I$Say5qZtS=zmDou}WTxx}4YbZJMxroVZP zst$};;Jd+Z>F&NCxf_-re2=R3FdH5`Frx1VZh>#lwpON5)Fx_T7!qIr7(*n6Q&Q78 zt}&pJPHnO-31}{9(#=bN$4norfqS+!26V_;eRle^5i{G?0HJNBKF$`9ZL1AnL$fO? zCQcF>hj_X|+v2(}aTmjSw%HO|nGX3*rcI8#9SJ1r17d!C%{3;lp{Y%tri9c|PsMgo z#(0V^fbkY^IP5kvj-oo4R@qKj8-u(XWI{drPI1{4$i#+rf6bw8G8@yx)XIdmc=6tH zf+IK|0i4@ZBqOGvvtfrC>FlN^x{OZR{#^HU&ZcV&$WES=m_jQ*_S7eN;(OBS>Nbcx zJ3Of15zdy-NEerR%pZGFdpyNGv++&l*@EcLF z>cp<@mpH|%zaXAn!MT2(Hmbi7WTW5@;5}pG5cC4fNA6`luwi=B|8Org_9$K`VFe#v zO@q(5i0R0tEoRMDj*#jQZ)v$D@D{>ru+4g}FPNWp@f}$Zud>TQu^TkvVRNyN&J_4B z(zW0)9vBtjUBo79fUPNG=Ftnpc7|%D!@HYTxaIW1-TrltEnqWla$}EFH2IF{wlg&9 zh;cr4M@5qaPh+~DyH;%Szqp+pnKO6UWEnO<6-{AQmMV9Awb152tEM7U#6(kemX45) z>0xM!U0*z7r7`WRL(GlFJ+bA5!={_#PK zrPHT_-yh-k;~m-QYb!4`d1kalty)UgJRaN{u)1C9+Q=OV^~+F2^R zr}_u3)Hfg@?kmg1Tbq`x92=P;>e<&VrOe9WO$hMvEmh|WGe$`UaLv|aobb9(B|N;Z zbQ_FEVU?2lxv~YmRe1yv{P+yv$I9bp`-zh-0W?sNMUc{^zM2yV((LsjH zNdz?y52D8AnbE3QwSr##c!*0y*9f>7<(Jb0+%z}xxUu?C;k&ypaxldlt0@vy^#cL* z%3_awW!<-ayB&|M;LWSKAmlY7FQqrq2BWCuDL$WVeots$2Fcf}qRy!38>$1u?a_CG z>Gej+V5CcoqB^Usq#zUHr7w-ta4+SLPlNFA1nLo{}t4c^3&}?CEF$nnibu0K6lsx&oF=6E^t+ zQ>&`Y1(=pO6pH4V2I&CMV-~z`&r|h1w(Tf_Bi&Hp9Fy22Fb7hm1uc&%H)_zTH}AHJ zATiM>u{tQf31~{y6_k9&VNP^7%3bmcUr#y|@gRW=LvRB2j4`~|7U_8+93{{%0ez(X;y zQs6Z29-PtyMO9ZU*KQ8gebON`^upKdKhOvPaVSuz);-NIacH51>Z!iD zsW+-)Rk68z1=S97oJtSx>c;SF6-rhc!%(o=Ay*qCyp7FeOi|lO&P0_Y4FtpTu9oy&}q z#?rC6!!MDJiuKKSfEv~>7rq|slp>YEC>tWjggWvZ^T z(hFbDNB;^PQbZT&_yWs80E1*@N}^`O$t!8YRH{%{Bqp7L@=!q4btEfyn9-c2iwq72 zdZ*kNu6NmHF4Dtp+!)46*cxCri_X$zsj_m*jS(ilyZr%@61OB!Q{&{xIQ@?}4JjhN zY!z*TzxTSvx)<&1f-{XI9yo>(Dc-IJ<0%5%0 zk(Ik_pogj(tnBVkUqUa@;Y@}R{t0C*8mb~rZllXHsY=}v0XKtVzUB7TyJH@qfCZLJ zc(TBKd8A_>BJgK{2e-T>@I@z8ZuBYd^e;Ek<(=_MXtqY+sg_X-KZMC8rSWFD z(2=%5uIbupquH)lIS!T2OIwl`SE{V=%o8t(%rPnFZlf1SU6E9AH(B8KJ+Vz2S*-TN zMry_LOXi8mh|mWyPl=RKN_8GX7&>^Oky;?hlw{GF(RGViNmjr!68M(E*)jzZtDxkk zFu!Edg~6|-XVHpn1C5cZw~4wTEDd7H*P1IYn!+&4Slv(mZ_hLADtrXSBwT(jp3$~2*em(>MP24mdeasvAi}{53y-5hHljjjN61P zm0p*oH!8yOYXfv!Zgq>P)OHVX_OZ_CuqkWl@O(Fk8pF;q`E0Y%1-=7Q%cOdT5}A_9 zBxASY*Dj^TuAMqcmYKjd!9xqBSA|8?PFw3ThOLif5KVwE+o`dVvFUna7$SZkHb-;1 ze&6j($*OcJD*<0qQ;V|_*r-$i97B#or=~l?^Udk?Xc?ARH9LRIO2F;dZ>KiSvPx-y zYkZV|u}yo^ZVVffzgjB=plY08)egad$?ysMYa%E=U$B}z(^;(XY=s1jIyCE+z|n-arUwxv zDB4$En7cH;C^y4K=q5QgHA7N$IhBu*XfTH1Od&shY>|~|3oG-MNUY+tI&FBx5=o_a z#$0KoWDI}HmMyIGUo#RP*^%r6<|8Zd^}Ann!_stCmbf#nhOKgL9=3R$2)E z^}Ky=S_NXeyg}6@MVC8fSA-VSBt4+$&|+2INPLSho3TuvQxQ79+%c~rbWX+w$hI6W zl5cB}CAi%20`9BF;pIY74x+=Y#r;d$>`j$mYlt#cwPRtG{}ORe zM*R|{;j-5lD_N<0H?a&Uj;l4gAler2AHicCG8sB9QeXz{Dv{!sG z0;x(AJ#BSU^lCx}3=!R+f9|&XqadCXDrN8qBJ10>wQkbFc28SSSx`4kf$XeldR8$n z4M#T9$bb?bpifDDkhXMTql~eR8S*H3Ejb{AOf1^>Vwrg4S$Xn!Ev<~q!y1z*-#bbe zQb>UzMbdl}UfMX`Mnj_wkzvL!gh%KoThs=TpRG2ENJ0;{LfXAr8ys(59Njp=#%^*f z4sUE?-G~rHQJM@|ScmH%kS~uMrAoP}jPdVDoH@OlrE+q0I9V&DQe*1ffmHE2vLV;Z zqoaKvF8`38vHCkQj@=T7+3>#Q1{aT7Q=|h(ck)w{7 zQVS(0wlc&fUARbxLy`<-URCcN#fwe$lBI`fHf=-sQQ@T((chFs;XLfZmpx0OUdwNd zDwuz}TjUk6V0LSHkR~V6V}rf0`1w?rOzW(LB?VK!cr?$n=Q1~Etdu4Pl8Gf(!r!Yg zqNrRE?&;)2R7=)30`u_dKDldep?`p~uW&0KlS~p!$QOwk7y_LZ9j(|!tC6-ugi5H9 z{EQUIHNV~JozMSycE(o!pC;!HVRAko!Q2eT`v3d6`AGl2pPO6WzzXd@&CNK;`u{pN zgKhl#nfZ6#nK|j+nOTOJnI9wn&vSEQ|KQx*V*a1z<~RC>=H|Xv__^8K|1aj|-(hZs ziiA3}ydUGuJ2#s$gt_^T{ln+xmbbWJb91+iBXn?P1WyEBnrWG|6_0aEMAeA8l1tXP zWWK&4%-4d9pe1G4!d~;m(0;)peO;oD9Az-BEitx~8`sIc4Zz&L`ddGcm({qw?^j!` zs`XeXCuHgL&gI#XKjc_C|6+nb<$MCX@ z3*6Y5;brS_j(H;0q-vt=a(Zmbj3#M>w1^&4_6&nHA6c*=w+PWyH*KqTe{#@m6qyT^ z=&bNpOFlU`cjp=7BmL~;4Gd|_9MYIIamDjJY#0eyJ|7FKXXNlJH;)cC835QZcSiCA ztHV_DsHnP>n$=PBmZ z$0B+IVPK6ABOxF;*3J=fLilWJHDs-FFas7cdb{I!HgiTS%_i3x5iru_Twc6g>2R7` zDuEd4DJiTdis%KtYzSsk8|{4tYcW=CPK9a+z~jO*6N zO0B9E z14Z)mNT_k$D0#T8R?LumK)E-coGRFLj_;A?w|El$r20p$*Hu3>EW=J|rc;a`bv8c` zugM5LAPzfaDyA@{fVtamDEdCVH@(SsYjl_DD77suC@5&Fa5Bu2nw;|qOq>AWy0ZUXv(%nmKiwrj^$b6OoIE!*{&m^le z00-7rc))}vKp_JeI+0xh9353EmI@P{0iHC>vYEUIc)nHgWpTGeOuG^pjP6i zj+GE;7Myw_W-W@4nEENj%z^4lzzL;Iw@KEhYux^Rt!iH?$u19XYLhet11ai#>9L=) ziLu|R_hrON>~s8Ue@RTwU;{BX^GaE)N8FJQD88qyd(&&erRc=I_qSLhp*xNJtTren zl(Ai@B?+}@)*vPpa)a2Qu_C2*NN6yT@W^{vVE7HNO2PxfZh!|0%u^@2!PZoxrUECN zk}!-Dj`~-ekdW;?jPMkCPhf;Y^h;P_J6IunczIc2^*yYRA*`_EBhmks7yfkJ%L_HZ z{|8>k{Lae@C-A)Ri%6aqGBbyG;lx2+sG-2>cwSh3mlq-zc%e$*g-bG?0*-iIIFILr zc>*u2Mkr$KeY|in2}yiEFVrR!xWh7@|0h0};r#!_2dm@m@d9R7N+L_Bx&m23Dlr@& zY|Oi6#kj1D>{;D7n+>hHUSG4aHnLJY^}DDtO+?MK>RL@r3{w_Da6`?Fk&MkKF^S5g zg_@bACEd5n;7o5(^mRzBv5^eVpL)&*mYuM5%z!tpMu{yL{9V!*i490FczmRyR&qAf z&l(A2LBB7jZm+P-RutYY4IR}eY0b0yP|eNwQ;>4&{Vy_P)S8zF4=>eT!$+C-Bb_vF z6%0Y5Lm$$LBP7an|DLVd@!{&&@!HvSfqKN!Ok?FU4Ml0*7>rKp6>-AI>kFi|AVl+v zETU6X2|?Ej=cX8I0}>v*ZZpCkOU|-o$uYG?R$iOymuGd(n$f`;{`!}hd5O+vigFX@ ziV{DJD3qn>5_aarKdMZTC8{I_2jz~U{97EZI5-lf;7YOY$QDJItTg1|){#B?*%ckK zwvjFug@dAPvJRQ6og8i@`(vt9Gpbc)T}PSs`@3D#jx|#w{C19XJ1Gbu+hnaVe!F(Y zyw}_+3I8U1*G>uC6uZ)>*5JoS__enMpA8G>iUH!zTZr8ROP#Y6?Dv7km*_`DaMWgq zp$i_RFa?h+92w!e`Q){nnV!}eGk3RK+46&UGRum)M^UYkjv1GIshhh|XT=z%L-ygH zLv}nHXv+;Bzox^_2GL(`QA`Gze{&C9%h~O}Q)WPDpI=kqKNbdKnG?J&#J5m_b&iBg zIh27^=Ho@@5h)h4`$vn;S$ZxM#volxVN8LhKLf*4TqvtCJzS{!Zd-ug@2oMuC+l`m z>OQiP`ax>b)%;1sM8V27g3amiFPJ6k`ZYcu9jP^T=+0YUOjanAB2TW-psL?aBBiL=bQjc8-wKx>LE0XhpinnH@%;U z9^xK7Z_6USEkw`T_bh44ppJOBp0}@3XwyIIm0QY4iw5%y*DE7zJK2E?IwMS*Xc(G9 zbX!mu392y7f!0My*Pw4)(lDr0TDl0jq_{<_yc~L@n%YBFV<2fRbV!=HTZVLcWL1Zd zKX=O?hPOzf*n zZWvlka|iMA?{zyGleeCf<<3<^-ysIBMoGbEl<5P6L)}9YD##F1rhSy-I1woTRR<)= zx*v!Eda17*m6s+uRtQQmLWer4rCL4`wj5s-}Cz8lt5<{4z*^1;T ziXb{!QWCr zL~@NS9j~H>vf|HX!*J**L{wMSGHS~YzCCda1m|vzq)SDgfw4jD7I(| zDbNW0j)r79+1xP&GM|xK^dU^*#y`eS@K4NVhz5oEEvBh}^HY}OulUhi;W;l|qWMAm z-4^->u}edp{#1!Q*m+f-eaksjrRH>nXNjg#df~hC(pSXY!LU@XoU%SiQkh?|MSJ?i z*+@#j)o*FlbVwoCTe`bVvr~F;7mw)W)O&GED$sl={>r(QgP+Y_c&c~dDJzdz=JW_i z_<`8&B&s!PY3ai8o`p*x*(z9lvHEqc3`k67UbB@cYH9XC#o2*^jl^os?eIOoVC2@V z2wxgs;prw_82&Ol8r24FiocuPs5zRyes|3ArtjL+2YmL3`xBs$s@~EnZB*@%Hn+FI zE0yUFu;{vx@c!}YQPhz~MhYF>pKyRUV0p*)M#9;!D5AFk8bFl5b$^1%3QRO=ZX}$B zTvgL3z0lMoeP={{g{MG9)KfXzp!L$cj8ac#-;uROHIJ`HFz{wiQ&d6LFV!=#RRBps z=@+R~=La8G9@+UC?oS%aCR zveDKkiK3Clp2ZS$)!Y_Y-{?TW`eYPhl~>*94x!8|l=i4m*x6Wi z8_5=D&L~@YtHj*yu}!au^C5{_=2Hc6cWhDN?L<0ilRywEfdM1Fhxr1`>tflwfYOyC z&`eCXEpw@YnK$E?DTQSP8Iz`mwg>~VJ<=^ozc+msvmu41Mt)0c^I{`2)8H-X%|IkVZ7SyYpwEWwxnNfs|BGfRRT}2+ zmxt(KC60j^6Qzkdijk8+C-@BN-8ZXm6GYb|5`(>6KAj;<>KVFy5vxFtKoCt3eb^=@ zBIr>z38YST;9KIBQ_*jWs^L$Rc+kaImy%MkN`M_7JioGXNA)r|oxvjeZXO5WDDXf`o#i5Q4AD+|mm4|5rzw+?f7b1jB9Hrv$gE|>%h64?4U%(367#Tjj%sk8s6 z7Ef{Qe?^^5tHtT+Y^qI+$jti45tpV1^_2fj9qku?A!>x7v$&#B2WK@?}*5| z9dXjkT{e8yGBNPQyRSNQrwkX#e2G49J>F&Gojz-8kV&NJU@{RAgx-eMc4U>JK z0azbGav?jH4gaIsbXOF}RuFu2sQm=N$4&@7x|#a~A4K3WDEvV73wLR$<>(+SnU1*y z{?T{d%Rf4COp1a2dy0Qua5Y? z)jW-Uea6c?9A>P{w<=98H#o@2W^-ob>T`NlEf{R5_fCx!$EKlKP(3yDT(Ot<4%v#h zW>c=&lB~QnkD|hubPuerYX)F8P{_*jMHFc+j7%yMF_S3WzB4#|Z%&Ua3p$=YVgiuhJ%3)8YE) z0z1l)wG8eG3zow|;2U$+GDWao5zPE~gOiv!BQk?hdpwz+)urnr{mI>yj%BdGec&{X z+y*hFz7J%I>Xt_wTOBNkn78`PCv~f?n3wwt%$1NIxaw@`!!o~8U#VVA6-1$_AsBE5 z49s`?@ABt*HxXcgNq}+k1~f1?p)%7HbFLSP&Go@qh@q95@2P2`ZF#kkFyW?be<9T% z7KOYW^n*Ycvfee0X-{|Ld(MU&VGi&$?VZj4mK-nK)4dtOfX;od^iyKW2~%<-nPoHdd#J1|R-3jeX?uY^D`=6lYl z@~&*2ex+5^H+c(BESkR(iq%{v!y}gUG$Zys2r)NPJ`P)S*1>m2cmonVssB(F~1s_Gu#ME;m*td#AgQ%;11dJh^XXPyyxq|(^D79)a$(_fzW{X_2 z88X1qL4J4v@iUob!$m{gs9Ed=Es~kGC}?VkkM>Hen2)iAp6r@+};qWZ#fNr{{(B@5?_v4jj`W8uRKt3H|D_|0$0VZqZhI*KwBV$$48ZF? zMA;LY-ry5r4n&!KE8Nz&2jQ5%j2fG*dClE+r32=)Cc)I5d|%VLNBp!eiq}xdGY#vX zoAhXWPVfRz{2K}5d|?KayL4_&o;xRBWzP3NvxNVr-wI$uR<9hL`y&5k#@#QTw*u-{ zdRQnj==#ECmtGCXDKuN&z3j;kFz1_FQd%u-m$4aBWI`@gv(nclDPtNJ_uQx^?xR~& ztp)oBs`<4fD_$KP(fBPJx;lCU4jbW!W6I(_+6Wo&~#6PAg9`AWw>=_?m9`EtY4v3%V!M*Xd%kdLD#k1Y;1;BN~2Qr)gwv%Eh&1x2`Ps7_~47; zlJ(Cf$mY(U6F<>i{6<3jqbi^#e!K(!PcI8#gKAbqC$4{X(gfW=Y5WTbscG)isVZOw zYG(ZRqz9y?c~}K2PMx?+?|d$Md`fw;9(7NarX==7w1RqhTGPxKMr)=y|3qtWOEuC<&3@z1!{YfQ**i9<{W*w{_hEnHg|iQ<6YIJ zc8_OQKwG5aUGhu*A|PLr$2szDqL#r#LHK-{|J)>Q2)g`OYkjlZ@%M!0=6bsdfa;qr zVUP5Ow)*D3G|gsx*S9haewV9m!Y!lkW%J(?>KoncWW+H4GfC_I`1YnX%Qj0dACg|) zw9~rFcJQbhX$~GyZ93&~w@=%&2k$m>KbwC_*wo?P)v>8Vb$Ykw%qO=`zrU>OuPZ&D zSkJ6KxZieqe?a?tj&_G07GhJ&Ra9J8|i-DM7( zbouBpyYspB-ObHA+I;MPU5Raf`|j`_d+VFcJv(3gIFF6p{O!-|`@Axr3U2}uSHDNI zKAYMct!T{;SeuV$zzHx@|CWFh zM}3py^iJqS=^f2uT^rZfk-T{eu(Gt&ypdp~ezgi1M=JdHGzHY#pgCrJ%+1Se<=PUD zEx>H8Z?=sMtWiIF_M;rOw?-{J+n8A`qSkd}LW5K(pBN<>MROYF>1IR={li^r3wNEdIFgwQLhAcD)s|ku%U3b zhV!^Rz4ikKaob~9k$y^q;i=yzLM9h1+q?dO?{)_jGsz#EpJv}XcF1)4_R&L`^gF&t z^3=@rc1d_ThP|t6Gl^pD&@PKh?~+inW~zHmAZyGnQO3g}XYJ1pwL>d%fIV1Ma_++BXuitRXY8E#wOc%eF-9+qn~Vfqbs zb799$@%beGly9PtPr^gP{NMNb-E0Cd<~n^Ju#DK@nQ)@6WyRf0L$J=@pRGEawpr9# zZH5${?$z29$koViOa{%jSQ|~|q*vG55%z4;E6F8?D4lYx8vbDP@DcH@X%;{)fNrg^uKi0l6jse!*wsZ5bL+70>zq@UD&*b=Xg4tW&dd@SH`sksK z&6jR^I>kSuYfj$IfG^##2DOf=d!<)LZ=V;KA)>~*)jFDe8l$K8v5xbb!VYy-ztvwKB|fdj+$E-XJx3xOaS8^HnQM ztJ?oR%Dx1ysVi&zB_tuhvl6Pf1luGCh{800f>0d;A|kfmho~4s>p&<`skVSxl(Ewg zwh*BWku6c$m%t+=WsM7nO9Ln_)hS?IM`sX3l)6wC)E0RE^Ab?ou`}P_pO^P?-@WIY zd+xdC?&nZAvq>GuapS`2bPf-L|J^(mSZIN@dSG(15qO-ia`?5WN^d~Ai>HyM)w-%8 z{kKl&G^ph~gUOAqt18rgO9i`6+T;X{3iC99#{NADPcyIeBMb&Uplx1NHCI>`!ds3F zc66Dubp&z>z!#!UdM{|D(1dE}o(1X~r?po)JzM(r5vR0A?YV0bN^e~5eAZIzMd5gv z%s-IG%sfEwCX6OY{$tgou$bZ;u5>bhvs7v2U`c835$oS)nOm$_t4nz3$fNn zJrDD`dhKoP7lR(n&N@<2VPEaeYtmtJbioL_0eu_#{G$}x2h_0rt;t{f)rj}(z0gI@|%5~5ky$OL=9e^-0n{}xO#xT?L*SsQA5}@q|^;< z=3$hQ*;JT^kXoyCmPPxJ%anaf^aZ02(wd*yfx>J1U_z40!sC;m^DZEuO)sg~3Qryt znO)aoPtmn<;1Zw1{qEVMiY6Pd<(r}sR!!LQ#?n)tGuvAbD=C44m)&kp4l5h`={0zn z9_DDJto;~CnY#VJ*f+i<=`%XRb?o~=q%?u;k(PZnaKR2x{i@S^SPW~&ky+bH6aLC$ z@DXS~c|>UfDt0)8&QQ+TUApZO?Ba$X*EHX%J4YXIJk7w^t6d#kT+TZ_oa^THcR_5F zI`gd6rn)^U{l}a=`!p(L{iJJq8VnyPfAFb4WU4>FH6J$DAI9K+_hD9}+Uu31T~`l2^^1?t<(&yRBZ+$(_I-IM)QLAD@D{WF0$Z51_!ZJL3Sn-B+VV@Z%;#JC7>G} zbR5m@S=;`~>%8zl$s>tOs~jg2G+9f}10XiLeYA8nH{+vX1BG+N1Ujwb0v97C1cU#i zkX$jh+gcTxo6|7ostHsXB(Vt5c#^ATYc2f!0b}1NlpR#Mev_%HaQ5s*qrKNv5LsB} zY_~x`kgrYGo_XNWjCwUgEIQrTU}+Dq6_cj`gZNXGRl8wi;U&^R$MsmG@AyDzIq%RrR4k|) zjECKpb#r3fw&>Hpe83@mq&ibtyHSVXTwubW(R`@kwDx(6o9%FC)`K#8;L<7W)h=$v z15g(OrjCDb2L_;>gWACEo6Ub>b@zaZV415qCay!v*AE7-lRb!A`f%8`QDbUAKq~k* z;khx3dl(5H>s4+{Zt(-)DU33e-_SW~Oy`N%XI$4`Z_&G&~a((fr8-#uU`;AofVYdOhswr+Mnt9eoo0=Tztc;2%_aBPY$>Ypn_r zrb6q<^JRyI9Ut+w%_~onz-6>B(gp}QQi8oH9S<(ky{q3h(}XQ>8~W8i33r-LIm8N@ zD`y2d6^DcIECv;pZ5BBA3L)6rviLlps$Wc^TizW`&>;J>UNJzAN3-A6iH18l>2)* zBn}CTDvfeErQ}ZfqlI~E}QZ+Y3zbQh^4>T$N*M}d# z6^zelV6w+on_Z48Gk4GTt$dT!>GuGA!{vvDlkqO+L-d;&{s?;5L_L8B$rdeMS@%tP$13XM#{~k?J_ymEo8Y|UZds= zXvl9cBFN#wDBSvu90})|KSZS;X5`bWLdux#(`kc7tkhoP7wAh;Q(~Ddonx9$o7u+G zzJ?Hq5is5fVUrlmB*wk<02O+tEUtMRYWFF?cv8)Y(2(C=i*cfKr3GWDulscSjx*RP zw8TpTxJqWJtn)LtPWH7POCy&F-2O@U@+jd{b2*D|G|%S=U~aOQ1+(K9eUrzD< zFw$k#`ci6`7xLaJlXmlprGVy>F8wB0?Gz{{i2=>&$d62dZ+u`i0QSyeB^dngE@p|f zpOh5xt` z6iMCO^>H!x!5)xvyR(=_*XcJU8aK$$X|d|X8>Xz+us8I}pEl)OPOYyr1FrS>jLmj> zSW$Q%$%YwF9Hq|z6etB~brw01ml8JEO0Szym%YwD^FX*Wfu*=cWz$q9b03FN%~g`79B zWZKP*>K)L7YC^F>lK_T|B`;^F=(tcqBdV*VPsOibRbuxxw)9K=q5a7GplR?`It z^7K0#{tY@oTsMN;G(cQ8)r`81EE)m3KrlZCW8E!Jh=wNwcwONR5#~~9y;`dBL@+g9 z&0H=ACobH(M9a_MC2SfpQGrdok71DaS6xP+0a(=G;a-)alE?D#L z3#j4#6YRyqF&=3BH-Cy7NF5nS#rI5Av)NPCQ>SH4#fN_G-iH62h(GD>{^Vx=XHS2M zyF1X+ojf>{ir=|Al>Ae7%G1G*f9f7dzSEt2H@;`!=fs|Yp~3Y}yMG>h`tj554ZQ=Y zcYk^^nEd4F-Jg=5-0S}Q$-w>Cp`Qn~^$*A1?%pt+dZYW!&7Ivp#XTMB?vA_HeP`Rv z{(-^dy8}Z2Z{Wt=R2;9+R`(eoG(u27P(gTrRrd`-Xov7Ugv$`TAdqqTZ>#%uR#*3} zfN;uC-KVLl?yIP)?#qB+g5QAx~owUD5rp_)Z>?oFfQ`S+T{yNv11>2jI(V@!iII7-L)NxQw|0z1iQCoL7~dR~78d&N;8#`}NnVvXb*Ts?uUhYWuSJut*$IqTVe)6;#qE4MU{(Z|uMO(-B?VV>K!8iEHOXlN$ z&&0D%Uh6bp%xb%2Ht)iR&Rn{5Efc?Yrb~lAJa@cPlZ6l5$8XGAq49>$2Z0OW9)!~n zPC#gZa1O%H5Jn(8hfn~a3_=kEHH145oEGaHf?pBrUz1e^3Mt3in_x;A|K6SQGvk!tugyRd3 z;CMc~r$cCfFkK|lWWlp3OQ=~0;Q+j!`YHbA-Xa_?fcI*Mvx9&`I10a8+uGVTY}~l< z!yKWe41O0ud|9SY(+BUl5O&xKH5VWpg7-d#P%{YW?n3wpLO+CE5H>@e?;zAeD1vkv zNT-DOl>p}uj-T*!1KzHV)QEsMD8h*w@STKJ(+6dR&;a2mgmeh`5Q-oaKo|iSqS=rq z3&+*)yAQ%qdZY$-v+&Yw_f7nxsUpKsLsdMEAA8HiFvB3PvaQ7fK8>1}@18ZU^O0AK z?WarV3*8@mAZ%KVL;9OjM25j9>xb#DSQNCP+!)FqC?NQvfvC5+nr_RuM==Ja9xURD#1RS<{e3m}v(`{KbN z0Mc&SMo;Jze_fN1vp?&rtX>nuOsCU3SN>29F#(%4#aH4G6=aF}#u9~Q-7B6X!IpoaYEItV;0S)W)`)M@Zm&Cr&t|6*hN)N*OK$aMhsSU=s(t@DsS z&skr76ZfdA@Yqa7@SKknDn-X8ev?yJAS$aY%AuF(Q7yBw{1(8X6^hK;MVT^DzaDS< zS?~HaURIv#9Z-q$j_7;K@MFb$%gvvQ%E~<|@mzn^LVa&BEY2K*?AU?@pjBI5-OI9eh2Oype-oRTdtfJC+7$Uz+4 zkEDw7%X1fkaPk&(9LvcoU-|Q$%qmgV4SK$ouE&eA8Xl!$6DnPg;zhI*Q6>BkLqbg2i_1;}=Yi2hZUV6&(&G{(C!cOno?C5iT`Gz&!Z z91mzVxqqQ9IAnP0&#+!kXvnqLV8H0b*`CG|m5 z&Fb8^G+@(b&}uiHlzt$R*MY7x=yQ|3D*;i@f+`X$5(S77T%mpDzD->KjT3OM6iv)2 zUr7oT&}jaP=&?Aaw5}h+<#mtZ%4xANf&|e_#~6u`Yk-kv zXs(S^MtA(TII>biXCxT(^mPC7DqIi=A5>rEy4K**$ng*E@#Q!!T|s`C*jTQ|adR}8 zJ-ghX2U_J?K)Uv4+Qb;dMO3&Trlbrp8G{s)(K=9ese+0qy;hFT0`aJfGJt_h4TV3>Cm!J`s#`MfeAV5 zi)y`d?tvuAs~@=ty|nq-+G1N$L*;3a8Tg~H7!o82^CmB5lJ^)O+gk5={x@F*G7jQM zj7JOp3Jf#rRT!XP-EY@q1u8cV_f04=9QAyAW@pTzg|^kWU=nVqsVxT8@F)xvEZ{4z z03ytjNj>%G!C1Xy*=CtzL`cGT+s|x^@g{Yg$L30plO$hq>X#10qO;of?vSUr5N z!P^!sC*P%0t#B$bM`Ip$$K33W$;0xrg~KtK!!gH)WAZ99Z^WEDiDy2Hc{~zx^L~t> zlJ+oWuYOo-{!pa;UxbPu-y1WtI3~Z`@Y$C+c{OhNSqKAQmm9vgUDsQI)B8Fze5zFq z==q%YI=SK@6x(KkiHG7yS;`hG1=;?_TG zsHweCTYOjF`xnv72;trufsd##T6nw8b_h5BNwkl9uyC1B<)e=;!sos(G+<@bWL*wE zdD2N-yrje1eAm#H3NJ~7*Xr&M_CLf+BqI3q^cF7l5tY`pewT6SJG{p?%cBk!wcdHh ztt|oS^TEP^YW&!ZfFAt8#a5rylTw7&YL9Of-Yf6dR<;2qU(wuDp?7ufe*B!i=w1S3 zdeYYZ!}Y#-Cl+}x@+ARGm{Ny7K&L#wYj3n^SO0JedL(Z>G-r=nq@Wa&;?d*3?8IOK z&@xN+$h?lm7JAjW&J^La6k+*Q&_A>-LS&0*(l+6}+CWz3B;km@1j94@wa*uy?8YBU zgm*E}+WC4=c8H&-_o9gQi4bZY{z>^D!Cje%P)z|T8E5X(O1!5&+I$_dTu)lmS zj%Nl6hxIw-`nCXl{7I4d3JyJ{=Q}hPp>&(5cNl1SLwIP4^t$M=zYvhCrs(6p#50|R zS=sb_Jt(5gMZ);|6`Ah{Eif|z^yR6d!aoUb{z;f$nWydjN%YuTc$_ZG$3Qn{;+b=V zFoNmF1(QWU!K0_EGOt)OlGr~IJ^J6M-Ud9AV@-rOhzkEDgmh5Jk8GD`{`eAylL)yk zn)!|pttmI)nSX!rA%2Qz?kORSE6lIXtLw#Z0c%x>%Ym#t1Y}D zyx9))l|i4Z@68ewjtald$*U|+5Fu@%!V%#izk8KATKwty=}NGeo4INjSPRitFNeVNci|?;Ws&DSU(+yez=5w6*+5dpU>)CF`WLSvyF4WP-EEF zch3F9jRfgsQ8|X=J=q6N##I2L`);~Dy@8w0;8iDotlC#4JXYZlhp zu5a*tTVMW6l(T*rtxA|zGqYB>u!@_Gdd;803@3da($NT#$&NdF`>@Dg2 zS(I5lR^hWng)wW#Dm)-DGjgp3FNxzD(M_!oVC8E^YCbth*2xXg+&W>-`W1U~%Bu6U zcRKs~@x6`GhoVWC5Uq7}72$%rqD;YBs7w7*sLR;#y3B{V1Z^n2XKe);0a(uZ_(vt1 zjxSsL^b|DcDf^!QWBSaDoe#5|s|cBb>%V>v`|9xw;_MwG98QcORo$JI#>_vw3= z$B-SXbgwAWeyss}+K)@GS=wIX+xN8dN!Az|PR7Qc@bN!Y9e)tdv{`Fypy$c)V`<$Z ziW9xB;n58zsZ#WK?%G`OIn1LR?>egQ{XFJa+gS`L76Ic07cC%{vhHD1UxH-$pQ`md z|1@^xlXU+_InHRM>&_T6(7{=2`xMXo$J%j?;Tju*d@ahHw-(jMgRVlnM31kmy{9k3 zR6c9s%VO}%i)+=CGW|0>h-Hs|t)K_Qk(B%R*qAndeR++@a8UZC=p5Exj$ew~>DhBB z?yrxWWF&Rv&?O#gYxC8|FTyXCgNk1TG3FBd97cXUhuK0L^waR(tHp1&u008Du~h_} z&ZB|}$Rz-oD+ZulJ~|7q#Ufnotn$gZR9;~?_*5KksCnY#NvA2**6K}9`!L^F4Y z1cybB_X3CSVY4vkD!cs4LFr(wD@1C?hyKSdX)6r%0pj?1X7`P4BtEmd=Oai^)60!{ zDv38V80wx-+(F+w;(t&gSy|NWzmNMtZp(G+5_(tkRFB`TdxX66lny8L^u75p0-fmbj&(0Z z+BF+Q`lJ~*mx~0wBu!K69!=qmV6*g~FAepV;^QxH{5`Lqj9+;|>i?+G^-us)EA!Wx zjd*W1um;(W_h!c6+5`U!~LZAuP1J~pVIDY+38vhsmbwe z=KJdsvhaL8%pmq%(#{mD%Xvct5esXw@(#cgl;_fQnM=tuFQYQk*3C?_MCs?v>&)1z zh3QGtYJ(m|!KGaU8OTjvu}7$|L7XQ-Y~V`!x3xi6?08>bg;TL;PoX8)l2nU!-l ztlM}mClBAZJ|@2!B=P}%r#P$3T@Eu|ppTZYE`WX+(0kXpxpnaNu9%rXV$K_fb?8IG z5m|oqO!hk3v~{i(FkiB~6}{t+H}>Iqv{%#SUYC^(%zSH|n+M&yX5T$6e49`+cgDJT zi^!rbsImTbgx^_~-{Y{~SVu#xuq|(|g>6lX&9otl27fKEtR&Dq4j7IY^lo|nmhvCR z4VAsMQ2zHtH)pT&)-JmTX}u}}sG{CVs1x|%U2)9Y5@&hmq5pHNSeBh=10VmxsVJ1df+JC)&yF%7Vv)a<@`74N+FKD&?*E`Mt}W$jvAhuuIQ@ zK(2j{5U3}hAl(je;0bPfo)bIQj>T9#LRt5(AT9V0HvBg2J!0pT*QT{N#)Lb?PPx2X z-`o%YfeufU1O3Ae!xKj#$Vr~SZ-nGa9J1mxvE3iyKRVocl z{+ZZ&I_)!;U%FGt4GzFoY70hF#vPf!E(_uUKFGl6BRY+Y&DBCeNR?}we3M{j2c@>! zB5+Vny4AeR-0)B0x?LC*X*R+MMM!hSUQ>mE6)1J;?4MHIZNW7$YTxdN$l6ASW=&4N zK$M0kvbrsVL722oT35o`&W-=4Hm?S4-Tc-<$*H4@uH5)-;5B!xQ| z+ey4Toa6Sv{zKyG4LsO}gNTjv4Il;N%Vhj2v7(wVyRt-4sI%qMiUdLgyYYyS>OT1? zw~~m{6G6UFHi$rCj*JS1%g}JnH^Lnf%%ZaWINP_Sgd&`zCn=#6&i3GxP%1Cf2CkMZ z4_&kS3hZNRk$fAUIAVhnf4qE~R2Hpa_2J*5B^P2wLgxq9x`jy~2anD!uflu1x z()7#0x8t6zfb)x9=*w?z=ZI%3ZpU2?E=`vw!(mfrM`VTosnf1MX4^y|J&n|9Pf^&Z zt!Fu>DLsGhUhdcA(>R41c8Q2IhdRH&6z)c;_%DRV^f`hh!5(kA!CjKbRkGkA zQZGcvtRh{?`8VC~n?WwzS#11?%Fm+J%n<4yNJ~xOYu!RZ@(*}JLwdHKdNRn=i7Cw*7$cTRS>~p5iRU-JR1*)plE=ULo)pSL1 zsa=GSooe}!lte-e_?OQ~Vodw{{6Ln{lf3!>JR=QgqxN`@(eW}(PZ%@#WtCYph`dRhw6*UC z!dg$UMURI|oaYkh&xmZ&&H^H6#1#4_2U1s(tUF{6sY?QG2TO_AjbwGKr8!7~o8U?| zSsfc`=p>ZE`6we6s^j)A{LGAK`7bN#i7+P89nOkK5pCFRJFZwG7KhWs7l$n>dl`dd z-TbRQ@h|Ad$LY7ou%$kN@YCb>dmd6apo+kGMC1idQa>jFx<;zU^rh)5iKK0hfsk2D ziPO^~V2y)YK)~r-@TF0O%`UC7?^ciX5oC{)I{&uM(iaHjFA$F1ZA2%dcATONrE=@= zGXC1#cb}lMNn=I{ErewHOla33#|gOl6`946t};hPZiS9Pv|AKaYA2+#U&NzYnz z^bt<04H9GkSM;qm6t-M?mNn*;-X88JF85nn+A)6jCjHLH@7sFc$fk{e=cQvqQY~2Y z!oNmb$Ts$hez`L8J8fb~E3ndyPD7bWKR$;;Lp}KzjZ+He);N)oG&CZzYPUc@LwA99 zAA9qv<+cYpXm2LgdM#>Ziz;0j@)+UTgzalzFIxEaAQQAuki;OlBRkL=8> z9u(meK}qQa?$6^+6T!PZP+^e~?oUL)De{+`3OTBRWsAY;2}O!M0dL~E#Z=j1o8^8b zs()Je@MG}cA~OWC4!;^fbAQXbT_ZbpK#UHKB4|kE41Tj<#AZoD9)o(44(Lhmt_CLj zk=waj^>fDC@tU9Q~wP~vK7g1D^n^MTyz}ZNWYtCM#kX%N;Cj_h6%Vx z_xwe%I|vxADRj-oD$=>A!NQgYjHgy+SjV`h{*9hi3wOrp6~K4%v596WJkP$w^(#^E zEAe~C;8}CbOJ#b)3mi}jfP0oj0)TGBJke}z6D=b|!8!6<6H}o(V?1O}R@ws#su`Y5I4C2T}%1M`U z3Z*(b1Wfj^c}fj=idJH}eUwr|0k1IR-HCJ51W8@UaYwcvN?lViAS!cKPQ(GQ>dVwF)Xj+`aZ5E>FNi5hmD;I&dD zvH>23^zFAW4g7)`1HbH@UuvC;fnV6}a+sIsK>VcX!ON?ZMqP{?s|Yq$1vG;Nw;6+d z4t35Vg6}KEz$gQTG(05U`y8#c9C>V|BFok0*5EVWgRigFaO5EsX{AyI2Pc^cmic(F z`3KI}7s^8_rIkt@9GnZ+9n9^oe4#@0yF9ab)mTcK5^vgaIUN4#0UxDyF>+3u`PPDB zk2hEQQjvo5Kt^y-pfA*0I0B05-TC$Plgx)%5*M^t&9g&z;gkhk3|o>268&LL^C7U6 zWD2M7s1y!ou2O|r5>Xd)u`_s!$vbd)8&MrE9Fd)ZTLbXSn+pdqb7_`)l5qZ2i?|Kf zen{G%4?s+qv{ei4Tk4=Gq721nDYi)3Ht|xhlO?$b_Iy!$@sfq;l+E_}_U#N1O(a$& z1)EpWCXTX*d|^ver=`lq-Oa{;;$CNaJ1l8Zw4RCSf-$4A?@8@ud*?H@`SxYD;9SWT zb-8ZKcnfJx>9IuywgDpd{tZ2UZyTA=J)B{@kpdQ-jK8QQ5vz0*N(u$RZU)1Iu{)KM z5{{%$sAeN8sVBJG$myZjV3v4YIQTuFzFW2Tj$|5bjvR&(5>Fai9>yRI0pky9BXN$~ zgIcnx^X+TwOy5%i_GHA$&9aXW_=4Z7^=6Qb?b=?;+#-(LRG(wjRUaa{S9e5J3;XR=2)Rok#{`IcN#@-7LVE&olv;+Oe2 z(#NQs_E!Q(Ml}1NO4(}ZVLmu`#11P>Y(y##mhR#&Rrl_EBz1-E^|1wS;lJkx(SZDL zOG?@lTz`Z=o|{!K=fgOFtzN3`eia0AZMPN1bB-sUqudIEp#UwN!?Zl zHH@R8b4S^{0M$Rn?U>v^-m~|OWAWk~@y^W`Wcxc{^OMVZkLl6G=C$zA z>Cy&iYfC7ni{n;?L|+|&^e$8$=gxuY2+!xK6ZtvWhz`Hvc-#$_wA!a zPp!ZWHsDCe9<=WVCoorO2o(XdAd#W`5CDGlo`K>*MZpiSC7&lNFm6Y3AL%Tk2Ci$@ zjvt7Gc@eo50quga{Kg1_wA-05Xc^HU$o7iFOVN!dZ~r5SGxPr6kG9lJ-1%g7d(P4~ z!}wK{qOg(6rP7UcPeXS##1O=>OCRL&SjvxgCzp1Km2of?DE4yNk_gr*8aCWvwrc=4rK8k{79c6 zrv-NWc%@JMk6X`n>fTO>u09^h^L$)F%wDW_E&MhR+dbU2HYP!J7X9k;#}A0k4>Pm= z_it67cHitg$T5Hr-sD$cB#{3V2tv~nLzA-knmy7?N25AP&R67?E=D2* zQhB=Cr^=^5OGL;unzS9Ug?zB@6RYOmUa3hfC>zKAwIVffqo9d~NmG15 z@fc>!o-|3sGHD54S?nlu&yAi}o*R;4=KSdpk!D3U7qn87j0$T!NXG7beBRy3{9 z<`P!)#&0$9w6s_QAFFbVg%qh(yRAhw#5KifrGz5Y_-$gMvWk!C9hFA@sdA$P-051& zY^+X`Xf#qiAFFhfLSA*%J}X*7a#ON)3z4Wce)|gc%WZJC_|tK`HNVGuehhDVQ@U32 zd%Vwj0k3!*Z{170O^*Px&j*B29rUghIg~gf$)C>;bWHLCIS!J8J7#NHHS(aKv@Oc{ z{8&Fnm`qd!2c`N%5{}Es8djtR1trEy1NcfmM=5+u4wCpp5ROZ&bsH3<*$ptIek9DG zz=BZ1F+{-kOHcIE6e)6Jck{v0G}Id0*R~1N3fy+y5npd%{0Bp{GfGu59n(jzq1DOf}iAvkf&*jI;9r<#86-$wmY)|5Y zQj>L>xL&!P&rfw!rt;GyBm*nc<7^0pG4Z1ye`z9LDRGoa_=$eW#Hf{rMn5c`pZ2+? zMEaQ{26@!Uzl@G!O8c84Cw3!0aYORZsCbOLJ z8Pn6YCmMqSl%MfQD1OO5jXDa*I!gP(=%*=(O#_^jsf6b8;8I3H}Efw!{7N5e%g-o^P{Ed0G|}8+@RFN4Oj-BZ10lvb7RmI zS!ohu6+Z{~$1mk7jOnMw;45+g{(Mjq&})?jEBw;i#xN*yjecp{V-l-xR`Mf=$Y_pqHDB|MNFA&mbqpraB&wzG<$mN^PV8!a+TTQ}!G)uUrSWM} zW8us7$Tb}0YQ7?0BoF>_RLC926tP6Pk`Kmzl2!vIktA6D8%$@%Fzpqot0=*;-{6WE z!?hJ~eLgB&F^(-_3E&&UmI>HWUzQ5!I6Q{yW09mPI5_z?*doTT6^hhN>A@fW2HWyi zuqBKNeO`mDDp`>k{FhOYJR)Mebcr7+7xM+-oTN~G6DvXzymky<#Bzm1QqQT7>vPpVMt_VeQwB_ zCdP&+wnQwZ%cBIF-4Zu!jEY>js(SK!43RD}+N?V>m0X!xGdJ`cJ>iSm8mg&vYJ!3g z`9+4BKcq#(!>V%)^F0**yf)wdC}}hkmlIJZ%nP1J9yH5Zr>+U?790%54zp^Q&HI$c z9o_y4Ll^5Bk$kbLPAbh z#FzKB^P4mo&vm|yiZ=zUdnoBfL231=th5xA z2CMSq!eqpHg+$CiOr4YKC0Hqg9SSCk87%|E^s}eXlQX;9&pz^1o|~AT+t<+Ew*|AGd0`S~Tk$He9@@SbkxineOhT3y zrfpAwnCYkoxaMqUOh>vev)1b;z^e7tn=rTPc?)SgHu36@rWr6LFs(&&A0iCcc}j)X z_4+rv8(I1)SHW$p`A10DH3PYHY_gyU>zRghu_67{e|ABR7zE}&&HI6JfX7a4J_>o+ z#^vgx=*igy$va^mAnh}l!KP(`<0X|4N!u!GAAw~y)fB`*E>L5tX<&|Hn5|Z=p-Px{ zbnTH&@vs(*%f7Ym~FqO5A*F zdOzyYb#54_BmIz{)n2{g&=-cnu5rx-xM6Br_C~ucGGebgGu$+N@4L`g91gS9hbCfb ztjcbV(O?JF}#} zFlVI|*b~|}2=E0I5v3tL*i~4P8}z^Ti}T~*_U8nc^q$KFKd#hG^g%Hj4+C++iZyc5|uNGytVni8pA@d$n*X3@~3Z@?(_}IiiqW3V4 zGzG;C&3}t?P1$wbJ!OU+w6G8Dt~*@)tQD4vuIH3Jx#|ZTPMJQ<1!bqEh^Dc(w1y#R z$+A-;bNpnGL@mY?D0BTZDq|5Mp3V+RhK@_bcJXG%cP&K{<5I9M=J=(6k$-Q*IhPKo z0@*3k?a&EHJESQhyQ`m}6CaXzO3EHx^#eLyY^NzzMcaunB(bD*8LVjK z6hBGyBNqk4P?U)zk<-}mfIBhHT9hz^^D&t-#n}#pMwSw77Zhg#%kq9@%xqZim7{i& z4Q$9u7SM%h$qmI%j6)a9@dJ+J+jVg<_Weu8=;s_5dIC(rJ5Qwr6%5UP`vq9wY_uK9 zNZer}7vik+yan`hx$B&#r6seCy69;x4Dm8#jJK3_XA94?kYXrsDiD^o10a0PR3rjJ z*|1*zL}B4s)f~T)`BP=i)7d|><+AAMF3#czB<+hao*^=4w(9f~@(bI=9lnTLC~2Po z&p;;UxGd28&GXZtqIn&rCT^NfD#s zP$Y!sBnS@<5j%zOSRu!sg@{@30)U4ye{@()`aWE(jg)WzM@%RzGKIGayVmTtXRnG9 zqftDksMqBO8iukjtZ*UHT?m(%qOH(+(oz(uDqHI3^s^fsLM5~TP;Kav%DD{osxa8B zTLOg*IWas&Z8&GS1jqqu+ev&Iy4C}}kHkPM&*_io9m>1_9Xmo~zllVYz{(nspiwE* zDm$u<=S0F)YvGuWO6>Hm1PTFMEbS^eXvZ#Ax2kwfsy|>PaFHFlW@Zg2tASDNz$p4_ z%fM*%9E6>zNOo8gMMoa;oJ3+{pGLyDuk2z_d)}e|UJ~1VZTACCkJu@3GcbHZ>*cOX z2OYZFDP3Z;i|5q!hv^DgauCgV*+^a1cJ>ck-M1<;TXEmDw}FelVnkJ(H_NOIkHg6ul@ ze9>IcnY;EwFg;)70AUyW=7T;BC&yG^%kjK@FgAkPM1-I@QJ6C5BU0A=*6eSXpK_w0|9g>ATRMuyc%epJUti5R7>2_5a|C^>?;`>QgN0JJ)xlaMzp@(P9;LEimA2x+5)h|v&`lEpCIgabLjzG5fHdI2X$$(w82h2kyZmM-JO+$#V~?7)p4vY|4O!KqXar+3p{9%0PnLMtq)%Z z&%|Rr1bDkHinTsWBd@a~rJm65!8|Azo&<~mR4^~; zg8jNJ(5_&uIh=b1-$-rFHOS0O#_J^|m> z9ArlEW<)F@>yA|hnP0I|U&TD7(drALXKqr_8|wW=7%_8!DmpiF82j&AQkol{Oe zON!3eK+Zka>V&+LeXc2O!*E`Lk(7`DG^>E=v0KUE-)GvS9c1;eSGRkDYM2(idIY`$ z7sc3i^1DPEyPnkQyH;CdT1eL40S0^9j@Ca?B~YQDP0%T1Zjd8OpRj8+2$5A2*|QVI zbo3vpq6>^4foU%gsa}^b#Zm}i>rl?cySJ-&DBI%~yQ+s?!}=ps*b}RvswoKv3HifP zigWm+rq;;AX7=Hn!xpO((2`L5rW6^^5e!B&sUS8i9GR24wpAr|O0ftjP)Z`VBTGrj z)9dg9lc1Dmx1nz7IppvZL9;*)Su;AMoS=-!_aA2cv3-yr%i#1D$RaZ3WzUmx(h+#I zo$PrU?b#(NF$$FhT|W>4vp=XQ$OW|vl)}qU&V}s{9ac+I`8ys)_x;lTCfL8>Il>1; zmQ;FNA(JtckedWA*Gj>(HPmA&NcDDdbkJzW&dF_+@tj~x^asE%vR7|^m^$xU7}6qV zua0ww92kTCjDAGZMi3^LM(YHaPU@zp(Jm!_8g=iX3Ar^sONc0*V~}s4&S%poJWOat zV9)%ALGygYj^M-Mp)YTmu$ArSE1m{I9$hrK{ZsGHl~AmC;Th z?^^qq|1%wDGf-FXdqg1x7n)s{DL7^dH*Sr(H76k+|LQ!;-*p0FK+lQWft!5HiUWd>u| zTsUpQQDdccY(Hr(f9dY7oe!lv*ufn;yJlG{qt!lNl;s%0C==(It`5jys>J;$}z1dCTJFoIRo9dPzg2%DPFj|-EF=VQGB)~dx-z_K}bKe__&$Z!JEC?hYT5f zo(Uc+_I`v;&82=m@qL@Hqc;8f`crHW_Tn8pI03MX_de%X^u#f37Rc2;R3* z0fbr79gcbZWPXMh0-j`UTeJISgCAuYtOD%tmGhc>rKPMEoM={?PwUJ(%t^_?XHt{4 z2G^ftC7m^+Q%6bxT-#j)|h z;FT=8loKhPnRDRX{<$-M4|h8%WZWV8_uUzT2#kP!;dd~z9}oyYK$wEq*n*vMa7K?# zaHi9TvI6_(@_r9dh;GRK@fC=#p%MBsB>jJgt13mVI2yS~SV&yeX*9BBkJAfcimS9J;n9NdDX*Xu*?Q`;{P zvMx^@ldEEKq(+wVDo4k3RWW(wyMj|tF#_!|r_46Y#ma53?b)Z1p{&>PX~BHPH=rOv z;{KTTVNkAE=~h{s8x#nNMe3LZ;f(zjaaD0=moyH_xNZ*M_a4?BoewagXFLy^hM=X{ z-%`hF8*3B-gep?OOjh)SU)t+|9?5(ZYQzEzt!mGQ zY0PKZyQ4BK2hRGNPPeLB1+cCZqk08i!o(UYBmk-6!j1--r^A$rL#<%r5RCgiLH8&O zCeoy(2k%eWH8gv5i3d%`3a2}fXdU|e$z4c${86?unMzwpa#fnwV zRLG2SXn`P+&=lF%p-Wzrm2FQc*gXm(AZ4lSJydmCpi${sLSIy&D$b+tDb%7z zi^Cb6mSe1flzl_hTKTAo>j9J-S}UY|PpYfLP$e7%CU4Tk@nvy7Py&=mmH{UCkWgW; z9Eox?Vy4+F_F+>ZOUL!mgEe|)E-ROEl!;CUYu>7s&@*aPoO`KVYuqf2d{E9h)5139 zx@Zndn*Vihj;(gns8Jq$8OFi7IRBl`!a}S93EHUr1JL*$Ca!<8q17I7&U?eL8f*gs zC|JR^CzH=Naoq=vtonMIitDb63m{MQa_1`xg4u^5l__q1n^1T*Thv7hwM}4zW6{9?3G?f$j!}r@cWE`d}tXC^dY9&B9`>|}T@+ebw zY7{dBqjs<}q2mT%N}BSpdFS)`Lwul62{Z41*qP#Hnf5rI{no^tC5v%{aX(}MvS2Mg z&K;hZHW(;W?lq&$diCK}ZotmxW{d{r*D(X%RG|bg%|gY=?{u-SNG|i_nt`jh@1>peO;55pvEVAEFYhT>|f(~R(Xw(VE^udwe zk*nrPrJ3NyB-;*Yfm7+moxid*i2ZA+4M%G1+Mg0+Sz-&o;2~&3^m$GoE4_1sRQM{c z8~eH{oYp=UMAS`k$m#5e3#c!*F~#pPwS5Co;P#6mS9WR;nlua@at{3Y^<|!w9rT~e zEaT2>hpr0{%|xe?J+fTuAcs>HI5Hr&}++8&b!`3v6GLvITVhp?C?$#Opc}yji`d#Y@oMLJ_jR zb&)eJTU3;cJ3FUwu#4m7$MlLRceRyb(*4_oW8JQNjZkJ<6g=q>puqJ34 zv@jBz5l%G!J2n$m-#pg7WpVCO1NY)7D*CMq6wBF(gzdZ33Z8$G_1F61AZ8*E-;_x48L#C}&8`3S>5XOwJk<}{3-2a=b{@?WBZ^%6b z0yL%#$-VcM>f!&W4#(y7g{T%_uU5g=Pz7>Q|B|8bGPR z?gfd+3tpu;pqM>NnjB?Z@4Tup{xRD;Ef1E;1|ZLrXggLl9_-WMk`pHS2gjQip?_ay?;ZTMj54@}ut!UuR~2KMEql zM7qw6fEcTo6cAVyllrb)wUqj9>aB&nw`NeYTSp-Ue3p3AWlV}}DdlQv_R&#!6fCxf zofwAR&-VYZ_wI2`UHRVd&dwFG)kKjh*v?Kg3RF7*Yy~ehi4+8D2T<_R=@}9Y7pLt2 zt+jRRG>I(+ic>DOf>kGpjYcd}pw^--GXWKm!i>_^s+Cr0)2d@zw2C*#e!go5yiLzJ z&-1?T=lSFPoWO5i*7~ire(S#WTEELVS`tS-P1b!d{TJtm$+DvQ|GL~rq5a#p&1<6n zttc?DsQ?f;iVvE!z@|SYcy=j zulade6<9M|H)tl#VFvTd+Hg)N@c)GN&D@~t-$)!2I$QYrJhgo33D zPbPE;>68p|69#Ugz)c*uNdh-1xus;h9^3wD&Ma?MEQA^BdXMn?D=qjGk8OwN^v(fc z&di_6rn<6Ld9}0ky8TLRhu7PooIVrump$xyMt+ZLhPO0l)`;GAet#uHnete2;VjuH z88#+nNu}9Aiw$dfzz?O1sU&+Om!rsDd8VydVLBeQrivL(zEG2!Z*Vc$vwE^;mc7P8 zLgt(ZYhJp&{q$GtrK1m?(`$PD6T|3ZD=6$bh%ji{MW%@}!Hgw>@uorkB*ggxt!`En zc0uelQop8xncM8+STI~pWMgt>rsvE;ype(?k+3);xSKw$05uX(mA?ObxyK;-rW@4E!Syh!~`OkakEyC2QN-#h5nABw( zSx4O3jg@SSI{ehO7~UrGd}Zl!yQnn69$jkRywNV%y!h0^r4z8rDk`0Xt7OeL zgByHRN@iI4;eIA0^|Q6wS!|3cEJl6biL}gZ<{0&u%sFPrBdMbQ0b%&~`osbOwtHTz zNSW3*epH;Q!YP2b%EcD$=zgwwKbII!*$a=WN?uKG^INhGq-qby?bBnh=Nuy}g4Yqk@InzZqKC;cD5K0@T zt*?Q+>~3~#**<$}-GP=d)JbyE*778nrqUNvSy>0dGr|)#ZfH(cwT`873$Z!0Vs~BL zfql00xn=SnKSW&ibh2HLY+L>6p1A2N5=;jM3ee)N(`HIX5 zY4RCb?SbhrTSO?PeFlk`+O#lTTsCcVFcY>Xo^G8fD1z`!^^YG2U}jv9BB3E4PJ zFkixAS8b|YpKRTioMJGE$_%16@(R`=#IFS~hu7sOTT*`V$))M*gF59d2aJpdFSf$c zx;6CkVaCPW3UaX5GENZM&m1rJ4tRTeFJFD17+v;y4{ZAF(sYx!?0CT!Z;8{zZzPRg zp7uDmbSS`upxknA-(UdAgkKC0n>PD)fK!rN0b)&eMITBhp5*uxXvuLd^fw}tqih8d zXNI+ks9fjC7fzaSmTi(yInXcA5B8E=ea@EezK9=F)WK2v=BF5JqO#f%#RbUu`e9p! zNe*%Aht-bAjvEm@^2r_V(~|QP<~s(`Q9ItITfd{KjQ71H?t?|iZ>i&gI9KTUG3#d0 ziH}f=FB#~Cuu*?0e8CczVGb47fYy_mrccLXk36%z`Mf?%=B0TzkJ=*2G6dzKj)IC*O* z6jRu1Bxh)kQHy)z8Kn;|;Zt~RNzY;z4&_}-8jO+G9I3A^&BR@&Tb`1L<6E5O8${HO zM+Ec5eEQ?lL-N8i(ii6G!>;LKiJA!(*H2Z3QOV&6;98PIP;)OW7UT++CMS{9zLuOUWWmW;9tU%13Y z3bG+x#McKNd*lhFQfkopIQ7geAF-164-pb(sN`GnHLx}=>SmUhr)7Nl zC{i~IPypKKhI;}pbLr~0O2i~tipu=cHoLMkF3y(ujjM{FR+vm7yL{j9QjC2Um6GH$u!2{cFLLj13k|i2vA9O05pZR9K-B zcc}ywrZL&G!kx4H%~Ovx32R*L!@Hb%e{V z{F`do4NVFI+=EpXn@U^V@St5A*AQM^KQ6Bt77A0hijqezQCFwO8|pq#biC~h^*0Yc zR^!rmccrn{ocCW#O}C_*g42?&GQy?lOBzUZr-cv(5xlkFSba23DB~~1SH#=m3&{)# z7829g7}J;-(|tJa!c2o zd7RNS?ixJ%;foLXh%liPapzYiLqg~yNNMJ5Ab zZ$D#ZC1#W}cZHS&GqMu0ht6-{GO{hfJtwg_SklrJL_w4moUI6&Hf@G{;HIb;nu?iEwHT}qCvnnM=t z8Iy9=4I|Z2q&(9FlMM$#FevFKw~8snMK)kWIy20#+hKvsyI8XdG^MLT7EOJhZ&Oyv zoOV;;WX+j3O|VxeK^kE7w^Uk6UOg^r3nC5kNVn2laFa0nf6K@_#kB%==1q6%%|P2# z2~c|mV`#eZK1P@rO<_hzcfcUCrp%FURA?8kOxHiIO}*kWhS*f2)AjQ)9T`-i>G~&7 zZRyP+HlwnZwlzP_Ozvt<=xLrgAT}6B*o-4%^uIBGHJB$?b42O~Y>Okr{QF(tmnkCU zfY2D0QV+7@=KmnjoQFNR%%}kfwTs6+USS;L%iUF>8Z&NQZIG=w!ck>$G+VkLMjk}u zL%p5amSpO~P2Ywm*i`qeo3MLaf-Y%Ut)!tj0t!UTyHc`stGt;xKTnbJYkq;i<DoSq8l*CLdTAJBzsb&OB zwFX*zGHjffm+o2*;n$KF1Bsc4zVb0o7Lo=TH@&%A8hNJJ`qIVta0 zm3ehvB>D#gf-MqLvmvh;5+f7ytjR|!j3Msl981omt5`#`u0j=(eDTO*%Dj4A?(;j# z4SHR*)1=qW7c;@*t|cmQ_@S@R&oSu@H5-XM3G;YYv$m(1O==uD5M(okz>s>a#Bks= zny^GdnkHgL%^_A;2rk>nqV(tUZIcaOQCFkPD!aUBIw6 z!8RIB+NgQ*P4mRTHcE6z&4^vo!d5EO5#u(-jDSHdb?!KIL^y=3b1|Xa8gJ*0WF+Y{ z!({P%T|?Pp(&3|#0n!cbK8w{1GAG(9!XjlnHAT#Q1(VD zcjS6uAq3_aBvDyzo|+VS(By zx-pQ5MP~^0U`JB5ypYhAH&Q(e>}=uP^O>t#z74m_Gl~!gGb-~+pX4k@XfEA*efFz= zyFOb4K>fT-GwGpI4bXJ3Xc$AsC1TO7nx%)}^> z5y4NPC8r7V0Kta&qI6a*qzyu$ z1^NIcuzfLf>z7pOT)oM`S6(;{l|Si=>xjxFqL+I zOC7S8N~v8`QUl$3m>MLolcbjvMoSJLF`+>y3ZxOa3P~HFCx}lma-CWzo){yPG*Q$a z7d#`yfIdborcQmfZlt`TB!0*Rkc-~F7rFIKBDO&9h@p$# zqSQD`YX6B{s9zHOw2#f2x>J>^R%EIt)Jn(6&7W{kSutJmXHW zEhcoutJoS`;YOFhNpW_GdgEIcYNfpmO6V*JEn#z&jC|*@PAo4rnR_IZqrVJV9t2cx zZdq3*2CkAXj~uzY4(98cAWU<#$r!NR({dp{Q%JZ`blbU-;b z+GSQkcqm@k?1=Gk0T>UM8t@THnk)D3DICaIn^?ba%4N|KDLD??3HZXa60{4*g)gK`Ptl6j4AZ;u(|6(-x-Ex&e$g6izb$OaL$aJDN<%k1-|Z4 zHwS+z4a>X|oS*Kk4T5f`r(jnpzoyO;7J4HnKcjB3J9K4GI<3ghaHMNShkhUnS3j7L zQ*lr&9d3}0U=wUe;()Ylx3b|Ao!Y^D7(*j>wNhU#=gJw|5e4Ji)PuWgrI0stzYC|Z z(37IY&|eaNU!+u>#H8w8ofPtD`lS0Y2By5P>+se}?1g8z`PS<90`40Phk|Trz^y8FF<7gWWV|WOHPB;z5CW^srEybZ&F_RIT>%qzzBo zopGbXb3Nj$tjmnr;J`l4sjxUrq2~TtF&P{%cuT3!ls^;-DKdy8v2wM%2Kv1+(+A>5 z*Pr5I-aEcitbUBqPE~w3ik9paoOPZ~(CTy(G8aD0{OT3~c`(t4(LBCctr;659v-O& zmCP7+ye&o(#)uv?v375yF}@%h&m;{jaY^tVkLtAfgEYz~iVr#xIeDV9$BifcX1UDL-nxQG$cW7zTA*a%fzfx5+_ zo9Y!&|dU*W^8!pgZZUN!YjTbd62>O&wSQwU2u1z9H8$PjZfT zVI^*WyrAziYy1fQdT+LkU1SZ=~CK*f$==7PMc;pMO z_7U%1+Gf&rnIa72bCI2=J~WaBGxIflT*0NU1rd6E0(ZT>iZ&LSJtn()MRl&BUc7L{ zOIg)kN3IuJ_a!A+PpgiPJe%HDXvy}Le25dB7h^VUzu3P3DBfqh?Vb5wdC#xPzu@it z(RT6IT>Gk%t-T$#tiC#EM9TVux2}&|FGg|R4i$2M$Ut+}(_VbqgUxOAm-&D6=D)aM zH4(KreL+@Hx$khuXr&l*PE5Q0cb0hWAHoq+3M%JhEYH@%@O6+cg>*+=Lpp;?CY^P zD2Qe#B0ZaCYtx1QSX^)}?OIyI(Mf-&VY(L`eXjM$B_;aLjj5!+>mydqA2F?ga5aU} z{`-4#tyuzEM_e zbZz5`u$gbtgf;4K%*h&Gmz7YL{n2o(9?At-Jnvact6Ow0Lq-f7AruyZT_T;W&C=Cr z$^N^tp(U=R^_us=wGdIlVv~lJ%H>!?SHkbhvuPs;i-N(Mc}C7#Kc45P5EW z)9@9~nv6=xH89tNlyp#XQhm6xEV+WK5}MM~$pTk0J)?R`(AAlhZN{@_N;(c3&v(Ze zk%?Hk^`G1pERYF1O0M3Z3G1C`bGhG+nqZ=JY8oohERO9q!!|BuHAW7{j%_yAmu#T} z@*|dP8zj41c7(22guvk#$66e!EgPEU|S?rZrFeA zY~a48tmnq; z34!O|avb+HkA;~C`%d+jIjFO(Yf(7QZpWLt9D|&U2i@PCSZflo9VbquTZ!g_Rq8!MwqHsm^fL1DEkwMO%s$6^?%u z{SE|t(L*QBAYmG1j$OABYm_;=IPjmreW%QNgmZ2riSa1)N4O!)l1YURt2#L6dnD3E z8o?VJzaR7)B1HDbYBf&?8>L_)NqmvA`+ITo$Uy3K=r5IP1Dw2+ZCh9NCiG-Y!~@acV4Fs${CSp$Lo= zL8J_fH9U=~jhwvtR-ylyL!lCPQs@@QtFcrytttWuL@gsJR^n7lt6t@-^GJd5C0+h1 zhXd+>hlR5)zfDd2kUJVoCE5nsfz{7JyE2-obtO@38x^s+ID3?Y8IO|_@S=_vF{8*g zt}wLI9lxAKaUtLW(7yHH?abTAXzIFf^S8tGxb#l74^cAjxz<}r*p$ipz*3^R}T$l<6N zNkplQBDILldR5OR=$%)& z9u@eDdd^rL z&wRfpMkQ7|WRrw4Y%*%=LNw!$Q;cb-hvk4=z;6K)esg)Y7Wb)uIKWH*>M1ilm|0=| zjfYv`j`T3$%nFnr6sAVM&X>MS_4>om)Wim=O~$PDJ?>#vYbJTD=QyT>)DP6=-tyMW z^DreEjmP>8$87pH&twm?$vob})VSy3;!}H=eZC}IG-{9acpx>XtzyTMy2c>$85jL^ zCm!vzHcpWkMNJ$@7e#?t%bnn1&ifwlG||j?^DvL~6D~Sykk+ibXl>URJWRWJoX5JK zV@}>nj#=knPMX6!P)g6-xZ4x@W6h6xm>X`C#2$`G3HaV7%{|k@r1(NTOq6d1E}Bp* zb-Cz^b%VqXwbke-$f05aV6_Wth30q>dIxme{jh_51UQ;$ z@HQ)X9ENd!xr1-m;qdqhSnl&X*qOj`PX&T+IKg@lE&N0P>p`Mc^-G|c&+cGj(EQCY zBr*o=pLwzyeZY4Do@_*h`MVw1Db%8)xPx&q`*xtQ$k@xX#{sY@GJ67GG5}q^3{Ynw z&j7R)XCE}yahM?>-@}YRcFz)Rw#SKD-L@cH8s)fL4|eu)%qxMXWqyn!u3$mOzVZvC zlB#78`k<(b=Q()|!5~3*23a%x&WGQ%RI=7H0i<#?AmUXV6mZ!ot0k}Y;LI2Kst&?% zjKQyqyqu#|N6GyJtvW*PhiMhBP<$^PPazI9LMy_a}W&l|x3LYl!cf7Uf|i`lJyeCW6vx zCuGKQ&>@7^I2n1H!?{{QpgsqRct<+MuSGbNAIiL+vz{VY@v`V$oK^WT9*c$Rg?zZo z=b)Pc%InE#QsAr%`>ZiW3RW$wf8nAp=kno(P%$hEC_WL*C1`qGC%hEc=M;fH%hz(R z19w(7K=k9MT0*ch>0#^!OJ&cdH#auYiN6LhzMr{qeMR_Gr^@SBTQ6~ow#PVc43t$W zpj{fNRLknYv2WqZf8a{qxm$BF*2w7xPsi+MacW_43lL<;hz62MO;>e{!9)?B0o~k; z%=tBkFK=w()Kua7aNptf18oeidb}l%vXni)DE>R$V~%tOzmwj}U5K)px$>#Ykv_U1 zu2r(kmryL4bKLgPwB&Q5u88cj26T(&2j(rOpM&n;T6*S_?$0??n_XEF4Kl=&Mr%zTDtN`1_b3fFj_DpC&to}b(qkYk)hwHvhh+xl@*4R zy^8ag?D6Bke*Toil3tma@vHoaYcnrB@RVe|@MVdFKZo5ji7r}Ag-@FXz4I?pPf2D4 zH@s(o+K;-u*o$RG)=jS5D=1bSj)vy?@`>Eh2vYr3K~4=3?4$uxass+7@Qo+x4T-^u-)F#2!gzE>FCMDEwo z9myKIbO9rKSthaLEM+SC|6;&Gz*LG-aI?K!4DMfZ+)uxS8`jq&vT#S=v%;(mS>fH* z_0GSnIT6rR4zn{qa^pxj67}UZq~E#tcJGmGEV-I(cpMH@GPQ#aOu<8aVp8!{jErl# zc;BIQBmbg0g>@u}22-eT0C%i)X*#@`h-^{W>Lomq+93!asrj@bWYV6i)=q9s1Mhox zeC@a6`-#{^;NzQ7t=i9F5N4~PfS0VTi^fo@@B6JEb4ct|Bp=PwmxdxDthc0ndSp-x zKKK#Azp5I@3O5kP;Fx3G#jUB}!w-e#UogWCy<2y1^&ZknB4p0C{yMe7p$_DicPig? zk(pVhR(J;;ty=@Abq$K4PYNEdtU|%4ht@ULQXG5m=?o>pzpUvRdL`pGImg%RiF9WZL-7+-lS{0Dc0SNo%XeNXrf z65bIAUn`6gjQd3U5o_K&6bbj2Klo*6R}=n@^BFSs8L712k|`Fc8#ENz$ehZhEhepY zu9&|${F;$AEcDB-`Y$-d7t7YYb;1_*fesb|#+d^KF=bZMMG?V_gH ze$NMu7X4!|kK(j#exmsKEiUth2xI%adQAz}h%L^#1{REeA8*4+o^LzX9~B|kXnII> zZXm5Mu!>7vOv)(TM5!wLSgUI)xQ_GAf0FP;T!R2-%D(lS>Z^fT5wI51sS64A5?XbD z(0=<}GdeH}Q`8uY?Q^uaqdX`Jix$RGlkpq@=m(?{cS=F^0}uU>B$;~Y|_H9BX z`toTG$Afsp$LdE4$VlOFugv=8pwq5f)1>wO{_?A&n)q69hV~Clxk%k7;qcMR#0O&h zM_>U;zJ5t;J7vyKIO}GTvMZNz9wsqYte|k^CrU65EOmdyD|=zkMv!mkG{1QzK0^nb z1q8QB=BOsE0AxSQQx!D$;T^;T_nD+F| zS^%ebS%BX_PpRa5>&WM@kuoy#Jo=D1kF%OPRlg&7E~eK9Xv-`Fn~^Vvsb5S=<; zZNCYWDj_x)2&ypp@d2wncF3u`<>ufQuQ2-3K-DPwcuR51x)>qp%~)dRq0Mu)@if-a z7PU=d;;c`HJpQ)XgcdO_Rbu0PH?#5r^^xZ2 zH=c^&U9nItA9b^Au%aMO!Mo0|o8F^P&hUj~7M$|L#%`|2NPY1g4Ove(c*KLF8j0K^ zE|=XL9M;6E`sgASTbKgly8a6uK02%a#$Z<=*mg-;Q%ve&h4sn}O9qL2iNtt_OH2tw zTYmY5+&&Z+2`x!$h)G?dC_i_jY!I7wO@EJqYpR`1dzLH~iY2(%#m3g3vT_wR$49N9 zR9bF-(hFi^J%?ST@3Y0mI?AI9%cyU6}8bUI&Bv@r8b;`%2ewsK%Fc=$jY>3XF>QJMEaYTVL zSQsRc;Musk-@2-QMS8%bUaq(#W9foCak!dIeLm^oGl>FfJ4}GUCZL!!cHlpvr(6zk zgG1nZk<)MMpPrrz#x#D^SUfc~y(jZw4qH#YXSmE7zkTZ536=#t7HrZdv{=@*gvX`E zt<_;f78LrN$xRe^}O%zf(SBrZaMwuHaYF(^%+SDJT#siU} z%vg%7xGs;?y1d_wx;QjPSZ)20viLE{5liCo=DxHz@ZH-BP7Ia)-5$p!ovZyC6-JIv znK3xRYlYQEh#y4jH;;GxJmeSaWX3wGy+xr^{;$OfwE&FPy=#>nc9xfloO*XCC#cW`Ir!UpW6Tr!8cm zZj+&zQTc)Os){n&fhf<}ADjQ2^4%{;03e5c5t#iEm(ddN9|ix?F9stc{)iUwY2Ug} z@Kzx;DV9%*n$~cYc)Ue(gGr5Kg!%l|2%*dP%$;cwX2(EUyi5-9H{X@k-L%|FYg&Vp z4=^c~p97BBhSH+f{2a&@pH@2JlH|-8F_fiAgZ7A!kI;<)@(G^4f0r(n80QGIA9foX znj+i0fNw=t(8AbQ>rf+uycXZ^t~^be9Q@we1eG;T^fxfFV+*hxh)^Ba3udJ>z0S>k zyl-=c;|f|MiAR@Vg_=gbLE>=UahW(jO`7LmJPVyTA|mH=y3}$YqS58g7As=Gx{)}W z>iDepHPUb&_(T`W;xvWIIVjh?rqtQl(ui5&DI(H(V@d1PPO}!pf^FR9M@!F)@E0gQ z$$yw_CG?RtJmQno=d?L<-phIHl=fA3>IQe{i@l*IE~5pbC!-y)8o z;w}1~BkdrmV%Va}`;4vaIdf$EU_;um?l~p9ij~k*>T{&y;Q8*p^AWIz=N#1ORw|)@ z^W#+{U?5EBs-g8WY1j1uyfFd1QofJe#zR7=mbbnTy!9!yC|10vQZZ>Nc<|6Br#*ai z+M9Gz!$rPR;iGJb45Y@~?plO?W7R#hkUnxN4Zg$hV}tR}_tJ7N&G*of)G&+>9iU~> zRDOg$wwAk#mfKyAr)4G5kmNiDhM!wBT;;o5pa4P_4fQ|5*9qHQU)#hscKYu1isg{HmaV%(UJRwty_Yd zB(;+20^e4ysvxxH*R?@SK^p$~{6kIPJ=Uz<+7#^D4A0U{;3uZB2~kz>?oyCiE3Gcj zSmCRAoA}mXp)56TBC)K9!0|mf%f&37y76`7bK)1r6oTSXdy7)dl7aJi0yFxv|EwTcQ8% za9v6zssg;@6-KGK0=~?+((~|tqXwM0X?#?>vYMA%wUb-`hyxr}2TV1_xqs%#R~ ziq55-i1s~Ca`*XDNLn&U-by0s}=M3>u=$UYsJ9V`w9sD>x1~AQ8K&!dkE@2 zKqcl;(FHZe=EHp8_~<;nE>@xW!&d#@4>tvC6W2oLe`$MwRNp!-SC4!e_Z+rIM^8G0 z^|tmA1u0)_bz&nV^dyxVofV@{{q?Z%sT%FXN*w*6AkD9Gp-YFOWQ>by^5YZ*I}U4K zs033XmD$gD1l0v7&0JEXHd0149zjzuwEm+&_laGqfOj_WwgkMD@P37Ow+q3^EkxNa zC%%6ozMEiGKxM4HdeEAYrXj}b^@BjXuq^O7h7bgN2w+k{&-K` zTL08xa}Kv9n5es_tix-Z!)nmtRKGo399_Tkus5nwlE+2MYK)5x>((mbqxG4GqeV5A zIhBc9xG9oZK^PMR0-H)zp<+oF0}(>T|qsvejOs8b$MI5_Jx`Xq7U+Fp1crovcdkqQ&37cQME3wkB?9hxx zfk%07Y`&EwHjM8kqoPydGAeJy=Ta#eR7&@%Km&R1uINHH$+JU=uuI~HRQZNBYXypI zXZ6LGgQ}e8nv2goBl|u`Y+T<~@J1WP5K*4^}l}yQ%C?3T!t8nqs%GSeYmAt>89KKih14p{-zL+xJ4T@%gp_ z_0B1nQc!X%kPcH{A7ThMR#Lw3h`J2$nK20 zd@^s0yxsj5pezN}u(tBCZO0Z+)-i46t)3~eSwVM}cN(`j%&KfFSF|0=psXX>%9}j% zWlsg2J+t}IvrenLtvtBx*nd#gptkZ4J;n9a&drH7tSiNB1){cNiz%b9t)SkMr+i7! zR)5?{1|{Egev~8&8ZyrK;yIF~T1k`C{lwPhtA~#Me8?Tgqmc2Dgcuwfr*R|-vc4hV z%#Q@Zkr*G|+I;TNQQslW!yFkn10y8F#Z(m@=QoEUo9oXUnj{oEPamrPvxkIl?ml$% zt3$1Qeq)Kp?#yehYBruYRB-&zMw!_7#i4@NJft}rKRZMSVU%bkvV89W+q{+$W37`()4V>vJ0cIoAWnG&1beW3e3{2 zO+w63QnTORM7w{4lSYEo7THY|)r!sHKzOmc-`^zCd=&^Ub>9TCxtoL+2Exx`PnIUM< zTDq@RiiL!a^TRcTO?wP>_YS2dDAKA9VFjyuxDu1B`Dgz#ByUpRCI6OSs79mU1&zxp zbI%s65Bd?b^adZ_O+PcLO7(6#hB(SGoh55HQ1&&jeAj^$dP7du02=a~Ib9B!R{_BU zD+5`3RTybaH;M2nPfJh})>oQS#G#KkLyL%Ke>R`v}`a77Ie34+ROs9Ogq? z>K7i;;7vrF&ENX@H3sebh7`2W_vx1U#}8?~LDunA9auN2++9e_eF1b~ohyQ)?_YR+ zcY0u%sB#}6-sj;ITEo%)i2cN~cRW{0<^68UQq>*gqG#W03t{)FVv=SQ81k&ydaWD#pdYviHww*z@hC3!R- zCwY8|uQB%*$OD#`n!Q`<*+af#fjmkz$Nck&KkfdUU^tj}lV5_;f(^ z9w6y`<;QMWTxFFi(L1;z!nYHIV^pId!*^!Qfm%st(CH5qr;jVh!YI<|8^;}6EhQ@> z{sYDwx0UotvQ#0xoG`n&Z}^F~`NkHzwW@rl%Ht%yd!x~puldQ`?z^_7O?5olJ#{NV zAOis(9R2>B@p^%~&)??k7P{qI36eR6kN>RkS^;5I=BFMk)O=drnSVv(Bw5YRezF?# zUE-4^F%B)=+!y&6%@_G(HB$zY^*93wHwj6ynxFjqPz5S9B0gz%)YfYSXN~LcSgnzC zcx1nykWQ!y4b}~<)o?&|%eCgw=8syBe$+||#eDOYduEB0(A>Pc_2}+abef&2p%9tp z#U5vq(9zCz3pLmLn^%za7n%WCfL*;EKI##xyS3cadTbG8-PT&3mC~XL##+zfVVn3; z@b&Px{OF3TkYXSNx1uAuRKeZCPPB`mT)3}nAz3zGycPZCeS`)$Vv{#g<@@QDN9YPs z5n?dXLu<34I8dl04$Tj@QJ0RowRCj<>y~rodF4($sEANS>iJdkU~3`N`7R(5GP|C= zjecYJ&@w~wuYj-byW76|6le9;Wv%6=*3u`e#@2FUt7^oKGe`HUjda;VinA(6E5#}T zt4M7OTda>UirwD@a@*tIyfi={)*EO19VOPZ*7CI0B5a0Qf74q2L~DA2Nm+@EY|*0mm;+3IWe^F=T0lr+)ZQj$6M zVLzFcNJy+X8dPF;TOb@JHw^vFF|9`*YHj@win_N{++PL={^C})H>aRCqTISk47)LwdOzhO(){yw zkYJ@%+*&SbElsovTg!#5XX>`Ap4-opP-aq`UZo)I0gJzLs$zX!n)#oB2tM&|PPs)u zyT4<#@$$if%LlRBZ@qZ1{Nll9WG@Gu6_jV~k5KU+QO)_F&2hH#CDUkjwfnWf73i{NYUB%b3r5lTR_uu>xDkj|VU}fa3j+rQGXlGp{Qi`6hqwH1TeKd9}zEUq3%RmL{rC}6Rf$UjnTFW zshO8bf1WJU{;Vq*FIR&|MkeVWJm-G*Gsw8OAdhYfuS{v#5q=*|Z>RRF6%)mhfTk_VU5qP?Qs++#_-tnFx_s+A7imDI^LT{1gqcSuQseDk`g@=3d8Egk-n z1hiqQGl)&_YA5t)r?yaPrNePKb%D*{Vi)ZjRZ=4#zixW)qJ7es{r-}gM2eb4Qyoh0 zcs8}h%Lt3~RL4|ijLzOtcTLyviKW_W(Ot24FEgVgzqE$L^$ry0X*d@Easq zsAE&hbzk-1Box@XA6uwyWop?K@1wROCkAscttqsmTmI0xS;M9^1^4{JU(zihhc46) zw6@!;+tQ=!CK&_&oOg;19CwrUjw-2^&srBBJZZ1AtJ7an4O+W})T2ta+6x6=x)VLR zYLbj2^@=yrmiiPs>4VWF8S)eB9%d$e5L9v4Uy{*E;@>ii&G70pJ-WvR%fh?xc3Dga zlm%31@ntcerXrOn2#8RJ_Jstbb{Nr4Nph$pm7*5CKPd+~|qIs0|ita*X zQiBw_Zl?%aMU+nMOC5G?QCkYT>Ft1vFa@4#Lf@Q zN-bvbTIMZJwOk=CsC>u^^_G`$tmWOF)YF$O9WA{_u240~)0=HaYFL7k;3U^B=f-`Z zOKaql7fm0wabGZMerZjhJUi*K8n0zjkEMi^Cp2Q6_Skx>*&TaFEv=SEEQ$}_u~!Oi z&ZVS0*VEKw(hGGq7tUHbWjdE_UA%Z*^_U$^qjf1>xjJ>Rml>CY>@ePg-XfId{NRrh zb@RR6YA+L(G)uq)BODq71k^}N*vmHzZMkk98y}i1fx--$nkAV6R#LRHfMOR?CI9o| zOQ8JH_1V-#o=54DfW2r1QN?3Zsm?yVq%f7>6L0)|<9yYQVSw*wLb%Jgh)+sF(bc=tG42aB^ zz?%XhiUouQd^t&5nz0xmUhZBFX@}JykUbc|D&7eRtA1GsD~w}F=}f!tSA*f86(R`y zI5Y{SyUc2S2!ul*LbWG2|4kJvI93G_TQDBy#^4EviKN$tJdX>j4g?=0=UgDHEehr> znX$*#T_+!N>UYLe3&PaZ^ex(A-WlWmjth&e5>6reqRmjc=)2H&BvzSs6#U-MWx|>- z_TdVC0Ja6IRP(T_T@E(j(9%5B%v{AY6W%G%TwZM-Rqp6%R4B7!hn;TqYP9Z{d zmK;^)TYiJ{cPX}7*<^^LcMFQwxvy|pMXYWETjDNhXpvJ5!I+KeKGs6j{l=>EHZkUq zM=h4+w#P7)mAq*PqB57?Ao}nx**+JTWRGTtRy8!`uZfd!GTE+P$ zQKuNJ^yKu4a%xcKi_JdS5fqiizc^KCyBEI9k`I7{uZZuioq)5l_b_!D3+KsSb>F5n)5 zapRFQ6jmWIMn#L`d+annLo?Dt;X%&JobL@+BKD)PnQT)jBb90im8@DKh`zwBgP8J6 zs^y(`8Jv5m-+9-!=W5i%HrjELJru?`zvr+wqA7JH;(XkroVN$$pW0rU;_TrPhf|s+ zH1^5nmcFB3bL!R!cn&mtpBY_&JhwD6=KX!sHWQ;;L8|<-E0sx!^vni^7 zHs!@5+;u49<#5j=W3(6UKzs(zFTzbhiM(X&t_J)Su-I{B_E)%bfH8<;{Lj~C#{(?D zeHCB_JYrNq7b_#L6_|b7)kh(!xfI3ZYMEgEc6)>4C;nOF{${(go16R*tOYuKJ=>XJ zbMiY(ul46MsuV?|WHUNJnyc4VSc6=B(k| z%Uwl_DNEJ!kQS?$Be0aMwAfcx%%N>_ggQGM#mJb>veGt3qO;>FHOvvcz6axtt6ipP z+>VUAo^a$duwbJtx@VHSq-3YefhJo01`Z8Rr?(iEQNH~gu4ewK;jiu%E?HwyMd&g z=3O;v#*Pm}H47H)Rygyx`aG`1Noy7a#x0VRd*^oNZ-?SRa+-%I1By1=qD`on zND`dqnjPDn>98$Xm;Ssz`n=y@qNar?oWJ4fe}nNc z#r=379Tb%sB@{;C>KjY0ZvLv_uf8$F#XN?J6l%s$^#+7Q15VI5wm1Kps};;^@Inh2 z8uT7+C!K^oID^w91>%hqn(yP|4CUkGuNwa98_mbbUp0Z}J5qEHrAX+x59zwe1#v-i zh>@E0F8wIZIg#rT3Fd}`)g%X}jpFnyhso14R`MWZP}O6@SGh!j23W)v(On`Tz7ZiG zja6}jNZcY4p`}{71ul`K4BwO=DJw)$??>$G30Q3-0w7wd1$qVN$YaY#aA652L}As= zAg(8mfXl!uJT^LqS{gsNu7qNhj0D$-}+me zmA+`cOo!&9RsMBjM+z4C9jN2mGto1>x8@?uS3D5=f>!NqCAK^uUW`TUe%8?5br=qMd?H=@F;p zoYA~;JK4uXH|hO5d-@-&?+TZ%_O4D?4XuqbkG@IheyooXuQ^l{Oy#>2smGuZWmyxB zi93g#Flv70jvG&A98p8bO3s_X*uWw?C*e3To+ zpWSb{tT#CDe(#8*RggKo#)}{jM%k($i{(mL+2xH@Olej5&rrrD(nTo28(FHSs)%R- z1=eZ^#oq0Z*)# zvGx~siZp$$0IL!j=l}fvrv(1*l|YK|*+jExzOhiBUpU|RQp(C_Q&v8$UzxMOod26; z&p+{p7ZS|N7OZ@B{vV!QxYE4HynJEq%EZFF1;*zGN&FS=GXP5gF9J3KJ^*|M_!*!S zfTtPo1c2beY#e_l%W?8PbiecYPPhM4d>l&M74MyK4LuLt|GG`A`|STBY<^p;3)(E! ztptQ`38eih?)I%>-QK^5b)N$6q$kpG`~9)O=iRvP2Yd|}?iB0p1AGElj5z1I#JZ&a zB0t$k|1*FNxHkrYr1u4(h4|rl7~&nGB@EAx0Eqig`g0MEydQyk@1Wmaq@N1+tGIsv z8veNd`s`N#YXR#3uLIryR01{v-Uj>yunn*SunX`$;A21wfZ(?QIssjP6M%03{{mbF z3;+ZNuFn<&f&jw+O2BBqSO5!{1o$-|9$)|@1JVIc0+s__0;~bN0{A~oe8=C>#kZmPn-kZ^Qq0@!y-?P`V^-iBu}%f}|8T>OPdr6+j=w z2}KllJp|9afQx`j0k?s>-AGvy_<#Bv3O{rwqDuF|kl!!e|GRX5Da?@Dz3Gtmd;Nyq zhwlGbdPDw0aoig>`F6e+hH!@5hu(+oB+h$(#BIob=>DIDC;q<_$55QV6c-6I6yLq~ zq4e&(--|c&zI+a)n+M1PEFOfXaBl#-4tNXT1k?^fZ!)F3IhWE6$6W=O3P=Jx33wJ@ z0c-&50DK5&2Xq5IOQCf40U`iX0FMIZ02Tli1M&cC0P6t`KpkK|;OU@(pcjJv7-R{0 zEvO{uji3!d)j?Z>wgq{DPzWL!qZk!BcHFPj6DCDYerR~GOe(=4uY+O*TB?ppO`07S zGnwjH>DbjZ=CglRy#DszpRRj@5`5D)>xCunzcQv}@jv^1`U&O#x4x&Jo?b5uUOINH z<#kdaD;lfwzPc~*l~12rae~x@V3{PQ{AB8djDmFRx02uF%JiD2y$ci9;)sC%y?>SK z?|JEG$8&@4lyjH$$wL<`nxS`!K5S7QubY4Cof7|f!u5APy8TWuJF+HxamPC~Zu7*w zcfL~-PkeLNJ2hw3-S1TKJ@0~5`MFt(=O@jMjv7C1^l<6D-ee(n`zN4g-+tj+=9hQ8 zlg9Yo?RUQ2#@~A9U+MCpcm9>4-W+@%e5Jwz??bP=QdT~pfIB^!+=qPeL>9fbUvVsa z_p4~jUA~myH+LclS`w|V<&uX*EI z%)gOr=pXylitwkN@YwQyID4V+{n7imU3-!e1n+7N-}tjWO!dj9!=Cj|TzoQS1iN#~ zt5xF7AE`^1eSh%GbFJ@9cye9#q^pZAzg7Rg+ItVUrn0SV{3L{41jXKt1q3MuL{wA= zRZs*3#BPKnKqM5CfMD;vJGOD`UB|Ka-h1!8_ud=I|5+y|aCFd__nrIw?*IGlJ>kjP zd+oK??tOEzzQc&K@p;#myz`&?(&5nClVy8M7_en)Y?a4<9649d;=u4Vw~lVVcp|24 zK#L?FtMH*~6Cyp+W}Ir$*re3w$t|;+jq6%tTTX5H$1|<0uhjP{qd(tm;XU)q^Xi1X zP7F=CZ8N7)r9tH+m0f3zS=H{sg5J+Y#WkP(>rT7w5%b;q?b+|^)+cyk-B+5_^cP~6 zV^^m=>NK^den>BKx$UHohez*)1&y)Vd1Rw% z#i@P2R|!mV^|aH+h}-RU>M^`_`xj=mO*6Bm_qIP)vewzi=yQ3}RNw4gcb@j`GPeGl zPB}~V_Gz+w{@wD4Ut08BZ~bgp^XhN!>uOXxV0tt8>gqOXMM8<$UK7ij`?;V#NpNIw z@MC}&eaGW{9|KHq7iJ}>gr}w@7-j?Pw7Gf{a^_}u=Me1Hyxj(S{`+CK<@MO3k#&Te z1N@%@zcl))E1+d~S{9x2p#wNS;Awe2+zLFc$nz`lv@%bt@ZnYEDa+GpynA(?ig+qU z-*gM%n(%fBFK>z_atVA&&sN04oOic?e5*s4>+{r#r`9~RLHv%~LOOZ79ZyT}{_T0{ z!1GJ;;go{E2FQ=Hcri|A=r70ftMc+JPpk3#>O8H%)0(`y6Y{+i^f>dh7V=XDy9-ZU zk^g3}*XF4k%Hbi>>CUIygV*E9(>lCOm#03^{}OuY@p8UAtq)51*MOI6 zi1fXKoF8v*#Je{}{b2Tg3~0jF4}U&?0(dIpX&_I7c$%b7OiR)$)2R0@bZme{L-J((D$ju=o9 zG%lom*W;getet;(?ZfuF5*ogAc-eMd|A6slJ5^dbWr_I(QTqWUw+-^Dxx1H5D}Bdp z+OI3G^<8LoWt#rww4FQE)9wszy6ySC={rjtnQc=u)BT~xl7aeWR~E16aB1kroYYxVkzHvRYrOLA8pW`RVR0O4&Aui`QAH zHd}Sc@jSSz-ynDG_}LG(&uN}qVNuqI=DX&$)a)<+VEoCNW>e1%s%Q5mYgQNgGCSv$ zx6stD64@=h*4iyA@WV2d8a7*UAu9UNZ|z@adZs?>KSrOan4jyIdtji2c>l;x1>43x z*2K(vKlkIdSGisHy%Bw4CNWB;Ipd8z7tF)ITeDE!meb-4eAMRv5r!@nW>go(6#L~b zT8LyK{P<>mh)5;|-4H60nSk~T6Uj`;4r&IxbKP+w4+<|0{r(0tGapaUaCvPQ&5 zJgq?&ftCbyj}plOK|4bZ+Wut^-iq|c zwN(+n^}TX$dOf>vk;#$EU*7!gFz(Isjq^V~TsXkJll!*GuTGh)U>A+|>YaG^N?y?M z5vLP+>8??{@bp1E`x1TIa(n$$*}B8WI(enFu6xX_%#0E}n?1fidRm_fUvCB7j-Iq@ z%7xH|v)|0B``DvjFOzPsWb+hv?``?eG|2tttCMBZL^SweIgKuo%ljVa-^4J@>yNsK z450p70y+eI8b?Nf(p|Jo7#GZWO7B0L06yj4Tu^kM%wkY$==r4|>Nw<HSZ3>$y40dfsgK&*#U}fm)Q@B zVZ$)qfgXjO;zj-`z7)PS=up`4YhcV-(2}6nKxs978dv@M$r&;Zz@K`EbOKto_} ziE{a^uSgcl%f*3`zIaf2S^*azFJe5H9epUDTQXTaD4)%lN}#5o2f9=FS~HE|ZpKKM zDX?2Go=jHm$AAE)GUM0{{_}^L#ZY_@mN-9r=$<|z8O6gS-$G3BC9`S1p%v16$t>T( zG9L28H_s0r8Oh6AKu;T9k7fQ)&M)b-$`2p-ptnJ%J+G$&G9?A(Qfw)^b7%*o$B`AA{>sagW=nBp zJq7kMyqRRmBA#)`Pnye?u5#b0vX%WkDLNuwoOM z`%~Pi@-igP@^K?`HMUe?{#R#9ndKsU;@9BisV}I>iY3%0NlzV~p9r~Hthm;Ep6?<^ zyDKk4^0j$0<*yqrL;2+{Fnb8%?1{24wj(FrFQwg?70c#B2bo3XsCP81N5thMg=K2O z^C?`3fN$#P!0DvAByu$6%#IE`@Me-R)J5pTfrmwdN#5uZ+aQ}kRH5WN^ega2d*4Rk3tZZsZEIGhMop_{N4f=E|r&+ zO;O(3+DOc)|0O*RHX*NTLY`zw@_f=+%0}|x1SrM9k=Jt^_R_qWWXjk`3d^^wfL~6) zFE5A#e$A&ajTL!5#i5doq_9p_7VxVG_*DgZSb?4zJbyRz)U=V9>;a`XJMnyqr?VhF zwQP#&jEjwFVII2LaLW~LU0mD7yfB`gf^h2y!u1vCsV~seKp@|cH}686{A@zLtmt7V zmjD}y6^&mM&me((ut0x^fFCO0hY9#i1^jRUKSIE7$@BLk4zV_pmk0R#iR0r>6{MBG zZ-T&YYn~sA{-KRPrmaAxoq*q7z?a(?+8XKaY-7gNH)=1bJpUNX8s0CpmvoeovESD7 z`A_z2fjP&fX#tBoBz`x(yw1RHu8q0nMNlg1JVAWA3*ys@=SLzfy?Haq_Yu^Mz5;$f z0pG;J)M_)||4S?k^@q}BZei+p4m!we$@8f#TU!{?OMDxiPxai^qNu*vSs2nXRe4 zc9WP{()^U->@JA2hrsM9F|(q%D9O|j@TC$n=azgv)D`f3c>N^bL}J>=o)6bwViw@R zn?ogLVa<8JC=APXJYObAW1z&`S`L1DAV^|fJq7d{$~RbI=zl2wArf<&9Nuq5iDA4T zzL~@@UXZ!6fX{T6FdxiiVywRk3aT>9*O4OGj!{_Wj26jG0QqA@vMyr`l+3Gnvo*|Q zZv(s-_h)2+caz63p04I8$(u|R$)YESWT602qn*qaaBBwYJWV941NZ^~Ko}4WBmi=VvS2LWn{&i&(|#=0-YpT!9tjY~n-4A!%LpwN8QiUTYLvYS zxuAvLg4~E-1@K#JFwcUFJ?y0c3M&hI1t=j4FzSng9KmQOYUGhl3t$lZjsnO`*bOtu zb%VcEg81cvmkT@L1?lAV-U20E6+pj_dvW#-e<3IRiTi!zolqym^9*>Id>oAFBpu(U zoBW-HJjK;0N0j80uf(!7FaL~B55%$>4~zJsXGLa`Uje(zQ?YE*6XZRx;IYBIK{2{0 z3?cF$LntoX;&@kIh-D*yWzUfYgu4pn@8yPk7e6U)UyV2#W%~-uM&6I8mQRn-{m7#t zJp++1v4XrInJEJI#sc#eUd|jmMr1;N%)r;50%)C2dmUr7Vi`4{_}|1bI58`Zh-K8Y z_8bz+u;tFA>cuiM&^Mswpp~-4GTP(NgVL1PK1VFG1$_WYQ)+29F>OUN<>0?Gs7)eE9b>PH>EBYAfj7jm@}TqfqyBG&zq@YJYy+8+Q#4>NtJ!`}=+7r64S}gMcJpg_^P@8nI%oj8gv_9xBptLvCGeaz+ zy`ejxexMDq#4_3=ng`mL_^ZS++9P7Sie>(wWABRTA7_}Xm13C;^u_ODSs-ZmQuHsN z^H5J57+;3=i;PdE$VE)%h2k$%r2OMxJO*Ygu@{ubtmpVQm^cwr%|uoThyj$q+ZrY^ zU3C*#6`&c=4m_q-J;sfplpCJf)$JKmMr6*2&@S+8!M$=LWWc>9Banf>! ze74Wo-!^5;CfoE29=+nNT2Ibuc&huOnso;~{k8H-CS^O5*`s5TwcwaH?` zaEro9b(Y9303`st!Gkle;VJP6BWr$(lCBb22N#K~4qyRP078I$wIwn=5Druae1MKX zL}Q6;WfKD|K!@<=Tmj$cPSgQ>%7exuJ_dZ4^f{m}W5qm9kjU-=b6QJeH$Y9=NMxHj zNMwCGN@O>AS`y|80P&3U72Gr*K5=`&zotuM>wvF1iL7phM8;+r!lAI}q4N|Q(2ZCt zl=~fNgLx-!rbUF(ef~AX z;d{Rgw@PHqfdC*Bs12k5c4s6qH=riq$kPg-Re`+o64|A5s8^r^c{AzlJL+RVhbf=2 zH!MPZ4;OuA!Yv5gJP`>mAR#;~HK!e9x&thtq~Jljdv7@OkiIA|PEQR^-+deAofsoN zed5j|Y_NKxGNI?jSnPfLYMAH#)w#=Go!k7?xsQph+1UxyU1h8^#J zdXn3xIp>#6dh5|AVr1#?fd>+fFmX=%P1D&2?+r2h|IfGAIa5VOv$(g)eO@PhH=l6s zCO7}>+1tih|Ed^1{ov#l96I0nR zQ&U+Bb5q$7OH)}BTfoj#_SM0Z>*tCBpo)?%|W?uik$6{FV3b=2W$ODO);T3?B*u+$1C2|y%z;{UzndxJS zkA=ul>`31{#|knfI0@$c!;b+4fbApf{R1_DIzRx>3}_E%fL_2TU^=h_*bE#5ZUCnr ze+;+>JOd<8uwM(*0BQsNKyx4gQ1j4&4g`J$eg}2|$AD`9$-LyLQQq_^_ICj{fO!6( zEqF88JHo65h5)|-D}jB$W#9#1iaXVofE`d0C<{~t#Mr!YWTi69T4?$r2@DDj2@Pu+ z9?`6MWQ(Zin3l0|@vRbCw`tohF-f6RC8wmSyQFE-GcvQfYIXYToNl>!-KAdMb$#mj z)^E_zji#g64zRPVRIy~~1_8caHEY!N$m-TRPm`9U3Xcv8jE`&A@y7jU5A#32dVAse zxs!W#A38dA@{Fk?NAw@GX!(NKYgTXCx_`&PW0$X-Jyr1G<-6N=o<3T?V&k@@zt5jD zW@x{`6MmWgYc1B*vr*%E-c`#vlrfRmTD6X8+o^eEXi#QqVzN%(tNXCgL;6k}Kkc`b z>$Y!Lwq)+Sk6+)vxO?mIlb!pHAGmty^ci(VO6P2CkDe_P1qGmvp7VzoE2#btiW>Gm%A!3Y8s8{jqq~!c}XxY@Rf3 z%FN-T1`fD(@x=LEdygExck{vXPhZ}=X2#vtnoqiuZ8!62Ps=HfdQ=)!kWq2?2X)B- zFFThW_%5Zv;>*nf{2*JQ)tkX(!!IuNi@x@Ild$vieF9I+sT;p{y>r~I71i1u z-ssZt$hJB+x|)o?pCg(0tdH$)4|A=i<)>F2{kcoIVXqVpecvj}47m`|Xvy`c#>>t% ztvBza%zN&hR<+jcj%8OKYVW$?Xa~>jV@0}Klg;#ZXO!smWU58?$0I9eejQOE^<)21 zi7y5@Ccj_Qu=%Cs{*hM~)DJx~TN-qFjZ^D=tE?*~w!!pTG1fX)o4!$5vk(`%BP!?YX3e6Uq(fvAW&dt*3w6 zUGVza?WCH)KCDFKcu%=sKQClZe3$vn*SZX{ocQeS@wdP49d$O&SL^IhMrw9G=Uwu| zgf(I9*LPo7esY5$*WZ7=KmGic{d>aiwi%qdFjr=gSWfIxqrs7bPcM#sxcp=IF!fZc z#cmtlwmZ{oefLRSx>ks>s_R#>_Ls|74sZWF<8j`!HX|BsuCR20W=PLFk$XE-cQ!OFDIQz$b@fx;^@1E@yCo%PAFVw+f6>HYgEHPm-*rE0yZ4sQ?wYe4`$>}ZO_ep{ zO+zj({Iq`RkPVaN_j|vuyub1J)6TDa$C<4t(>ggPr*xQ4LgdBtgLWV5JUlS<;jrNw zmo5%zqY5|6t(Cf?+)a!A4d%M^I^5xMz~d^PKaRLCZS&G!H)l7CZ&$xdneH#GPE=T3 zd%U0Lml97kS6duivUS9=2h$IZa_(uaQFaK8oYQ!K`;AIFZK^)^FX(u@=k;mJH*LQ- z=EKag8NR(+Md>?D@Lc78((XkSh8gBivc@#;nqkXY`>M9;A74MakUXrd-2p#&MC`td_uOi zYPM|mmNuhL&dhjx|5MKcZ!Zq;vSP=TEN8N?n`iRc_{O1!w+8)waYoFT=bw`weYv1N zCt7O{Je<;b*yqjKC1#2-T1VM*{Hpm(#EgvP=W>;{{>Qu3m{h`gmi~qL063jj$NlZ(@ao6V|!!nt$5==K2>h zi-YB3-7fnnqn^rh(hGVH`-K@aZGFiF%TCqYz5S){jh*GfEl)RUSNm=!P4xR-y){yp^f$ZJ{cKrJM?T}vv1J(Dt9Npap^mIoZsBlt3sL`ZJ(gNp4-{xVP$Qd&;Fy% zN%qftTjtK+Uk7yew7Wm#U8Ow}&(@wjcSVE#D<_1d z9q%3=ezk3q$K%FXb|0&bd2e=a`WeT)OIKE(wQ;<3!2TXlUCy@Y5OKRn7x$M{a=H2U z`pP>c8IAf|UUUw&y^#7)2dkeuH@r^b;pT42X*Tsv z4?gN;HEVR^ty`lTWLHi*Q(7;*_1oxCv&S_Y+j(N+9koV` zxO#6)?C1IY@7_}mZqwdv+w-tTn|wPjUf-`*>gs_Wb(YnYK3n{#%(8hMtu?d8rhA{M zmG%0>*Mt>UBbs-;7+KMG|7WxJyQ{Nnj!kTmeaNM+->aF^Kfepxyy5f91$hN;-ud4Q zeq3<(*P~k=c%10i$g~b+L$k$oV#LOLQnPB(p|5OI+K0*>V!1S zj@Zn#_Z*VMpHC!j51ZM^qJ5`!Cwo6|=YJFYCP7X+({6<0su(RmW}F@F~8U(Si1L2E4OztQ`rjnY=U9+}hieXAJnPq$jU{wja5W#5CR zy>@vW_CG%OT*2W1gEyS@nU;6*=~llh?Ph(x@a%?-y6u;v>3uJc?p%Lgw9E5(*CzqfW<$d4AT<~_!nHDfDtz9GMbEQqj9X?|o{&ccc!HWdDPqQ5CTWmey z_{+2jvl`k2?Km1-tyljZlR5|Yi4J45AKLHC`C>gdwON^_ znh8=#Voi^|s)x;|Idn>BS9(ZR`Et_q3zh0MnJMnib~0;kR@wSV#VaLRE|^gN-saf4 z0n;7)hxR?;H|oUXntn$U*xQdwd&Ivx?N(iCu#)V!N}qTRDiEiI>(-;-`W=1rHZdh-nykST-n>)W5fM%mA8*o+OMztie1qqyz9o-*8;Z<>~-c+g~xZUrng*s z=FR>=rw1fV(UjV;C{5Y@W73x=2UWwPJBS=FYRnXhCM7<-wY3;^fX!&s$zC0KC$RHb zZP%1JC-0avZhA)2{L3KQQ)z3h=6_nWww`9ns-SZRH(!>0-17Tv%?0o54%b7E+n&49 zw#mt*ze_JV`!UyA_HB9oK$*l7+tQLEYyI^2J#{N~*0E)Uhg`4=;M!iJ_SJF%hj zC7p*Pt zZ~XZ2`L@x)+t!yoJ9pkJ*>^-|KG>Cn5J^E$J=94L{w=B47wl<)-@2c=i zZnhU9D_Sjo*UZGXb9YJL?&qDax4NFP==tajue@#Qu#u}14_6qFyk*v@Oef!4sj(Bg z*&H!xYQ1@58FBSG&Ze!lHQKb-#d_Q*>RBOhxf3xiq9lLM1^@rQa9t|q4vza#f z)Og!%XYa0mex+x%>zA$1oH{)?=+>E+A68#Y%@}a0>d`XW`n7l7`0i%66`9?dt}l15 zoyE|sE+q;MH8M-?U@dYen4ub@{v+wb>4LPx(BqmixwoulJv(K4K7N2CYS(I$hKbH8 z3*VRNe4<5Db;RXv8UD?>oc!ZTyK@(lt*^^oG`dhf?vE{t_s-aStL8DUB zs<&)rkvG~$a`pMd@~e;f1y_{1S*5>{JJyfBSuZ`k<*v{>gVyFGb?UwEO=Qr+1@)h% zSr>Fz_r`4f(`OCRKDQe-bN(MQYdZ97UiDstOLEI6ciK1E#q``TTe01A%B67MO07=+ zsxA|-=u6Gx@&T%jHLlEEHmOq5>jZXC?B*F~UCpy5O-fI(sTb93%M{5=y~g5DxoSPV z$94+y^gY(-_Ka@sn>_lZRzz&o0LyJ50bRG{M>5zqpqzxn%VSP zJ-Ni71vl^PU;6fsk(Vv&p06_UmmAHT5~m-#eagAQsb^^~>wGf1INU;cAxEt9KhQ-P zTh*;x*&eLT=9^_(cTeo7>1H`}$EJ&6w=8Z&Za_{`muD{xE-PGQB>h4>e5J!|alIW-#19^A71{ijtEU9*neI=_5F#j82hvcfB! zFdJ9v?22}aC#-oiWz?9fI|mo6zcO~gjxjCX)H~=S9ys22_op?ddS*HAJac7LXXmhM z2eYf>G}%;t>xY70%$CiFv%7n_L7hOU=#Ld$;+~GJb-}Cb|KN3v#oc@R9vQl=MCH)+1#Q~x zZGOglm0Mu^k|Sf%dv6cFdBO2Wr&A^R*1xfEa_MKUrrmZin|*e~`n{KO-o`9xGQ8^c z7mv#ySvj}V*$$Ty4nFaGHOad{p9kkN8cR|o{$r8@!aF}Jx!t3^wO)Vj-Y*}kq;GR* ztDieQv*g#icN%o-xo)xd^^q60?Kz>_=(VZQ0q=FArk`f?RTpj_p5OGTQ_i~yY4d6( z`z=-c*6z;RRG%7a^lmQ?=GGWf=J4(5Dv#S=Hf+luIQ(Mu>YkE$COyqdJ#M|ILX8*u zeRTOs%_C`A^TP)Q*BLPA>Zj?=`^?!fC5S`gFQ&3<2(vM87D$2Ha$e5puQ;lJ>{OsD{L{HC-EE;m zUfj&UT`a>5VY-___iG#gx-VD_pj%skKqAl&*a_eSndt|JpoH!?()$=hxTGP%Q8q4f zG4%gIB3zOYv49ki0iBs2K2SwR(p;R3@iNBE7(a?5-2)-eAw7Xk&IuH6f)x*IPy(HA z6DUmt<73oq)M?aZ)Iokpo;J!UFX(O|-9f4dR0V1PZUEigqx*Nk0NtTe06Jg*Fc;Vj z+y=yyxWD-r^TJ3eKZG!WT?on_At+5kz*_j&JCtNB%q`8VOsyq0CbnWbQ3ydN;>cK7SmLqbAM5WPo44`VSwofAeGhAO4`9 zr8mvtt#Wv;93Bh)p*BH}v0WJHcg@54FPewVUo{WAfB2O6hY$bm$A24f_%}b){^_AU zfF5H%V5Ef|!4C{S=obDq`yX~6|I|ArTr4sXNpKm=3|GW0M3(r_wJ~daZ1Az=KXxL+ zhc1rM$DaQ)aP*-7SSAb%%In#p1SlBL_^-J#Wy_VXP_a_wDplEP)oavra<1j#THDRt!?RA&Jv+Zfjhpxf$bNiT zuYHG(o#dT=d}Xgk&tARz^zGMwz`#L+hYTGye8k96qsNRLH-5q|6DLicGWFMKzfGSp zbJpxRbLY)puyE1hB};!__Q&!SD_5;vvv%G34I4LY-m-Pu_8mKS?cTF@-~Iy!4;?;o z^w{weCr_O|bN1Z%3l}e4zH;^2^&2;D-M(}8-u(v;A3c8Z^x5+lFJHZW^Y-2Q4If=yw16{U4hHY?AwN*I7;sTeEyihcgyQ?qi#LZRq8bKECum1~yYS!$Z? zbF-EXrsZap>FC(fVVbSna=+w^g}==(>qM(F7SGN0OEPg++rr*bY+~h5jxAr(T4HKb zszNmvscZF$j<#mzcBL!TsO{CDp|@Mj%4JHFt>WZf*RPR}hjZ0hp7k0x@vT$eKVZx# zMm7WZ1Bd~-0&-v{a1(e2^asX|W@L^)HNY1L0}_B_pclZfSk|#v)U$mVrZZ{-3()fe z{@a;&=PV$a#mLM7Tc8wB9;ga90d9a7P#F2A~JJ1AT$Pz(`;` zFa?+a%mbDHD}Z&t7GM`pa}Far2YLm##oLKz#C!0pVGjkG11*8pKu16UsDVr%8|VS_ z1BL*jfC<1G2QL^<0t110z#iZ( zUF6zMSeRLA{lJgRXKf`BDN#4Z$s0DPu2cBMIBBw(wjNID9!^Te zvvxL|>l$Q=f@hrEq;)k)_|YgC{PYHc-`-&G;~NZqeFHR)!S8PX8YVD1g~3m7F!&7) z20y~V;8!?EK08sHM}D-N0Ui~p41U~$!LNHT^z$BYQzAleCISf^QAlMNOpw)bEO;On_{r9i!71F& zsfC|Y9OIN;#|ilZP9p1+#5$>1qZ8}YmI-XZ#Iz{RsU5kdBj+LvdRV6{CcYihv_(AQ zF%U-Wg*L%V9@CkQ;8CgPT&lN9ZP)u-rr6XMOA zbSmDIs5dxrev|a-EEW;f>a7?>W>y~SNt)SYZDu;_ByEt(>N7d&&T3Q{oXLvOsr0O8 zl1_(glKxyWNiWaVt2OeZ>|{>`lbo)XD^SBSwT#h0lb!{KAUq9%h(v}1Fo1Aea)HfY z^^$VTa1sde@+p*Hg2H_ZEkWT-P-GB^Ch0Y4j7F`~%TtwFwptT5s#Rnp5-BGhLM2kj zR%!HdeWqNiO8-XsJ9d*MEcx>APgdhUl$bxe5=W~_CLJFB8LC`8Q;iQ$uGYy_=~?5hjm|4~%aWCy#E@~i7j5<%Wne!f)Hbx9b-iSqY_g=2gBaC%TP z@NjbE2XekaUhv3$b7}+n2CX8+# z{#ja8jye^m_Q~vOMErLc*J?@~BWFTganhLSyAIp-~|bQBA*> z)TtD5R4kHAPSogB-@9wl<+?0+mRCb>xiU3Pl_%#0Ge~nWaM5I9>`uV&UD!W*`J($o z|40w|NMk-~l=4IcRZo0VIt+a|4P$cj@D#j3p`mVZO7yuHAXD_I)C1QQ^uU4;yu!j7 z7(*yjtXE-xN*C5VR8n-!`dnlWzLl97DnpM9vr4Bxk>&DzGd~3I!5b>p4+BT~3Ii8< zOj7GJlas$6Hw3Yk)-B2xp+|)#4IaII=2MWPLZ8~)Zt4tO_n-O1Xl2YPq0fvYMQTcB zCMxZ>!<;a>D91vtKP_+?6OEEeR7}+BR25pGHZz6wr&02IW@Fad*gg$;o|%zEF=urvlB`vA{YjD3 z|3Q)HbB!K<7@nY32}Trcp+{jQ5ESG$A<{q+FOO{#5*imQj}8lq3yo*pSade%Y&|hE z*2=Yf8>dwXTbqpyZ7To9Q(Q#5P_Ff(hfr~|X)Q)egD>hYNXa)0!(5K}i>~hnP2AAq zKrdyfFlPkqP1uTrO%=6GkGbv7yi%WATp^-wEb=SNS3$7S`bCYaurJL>;#)5ouP`nU zP-iHxrq0yqRaul6uOD>Lp@`EDqLi-AAPqmMU0#2#U0jT@E;AI1(f<#!QY!T-wo+4v z@ekuqD*pEgAm9J2%l#5mpF&u0ora^{3U6uzpFUb&IPA+9IDn zs+o0*uR_|~Bm~M;z8{spPw_sHMvNDnPcK3LD~xS}BAyRVP&a8|6ZwMOm zo9hcPJuGU`!qf|T%3^v0gWtsTERD)I9{gYgLY^1pfN-$Il2)nGBy#yKEHFX9#WY*a zRf|>lx7}Wmr*Br%!tgRR3i4Il5R0CYV)=dl!YNJsaZuF3e%~!{e!BflKU@jY9F}W` zS&5jVqE-a93Wqq*5PaTY(CNE(zlp zP4kUrZhTYaa1&<`R1KY8o2}5(&}Wdws*f5fEf{Je5ZFBYF(|rXeLzbqig0jT5Qa{9 zXhOWabznriQM;ZGDVdgv#SC-CGUH0DC?o&0E8~o~B&TyRO;#soa-E9{Eus*C^ekEd z31bb(WG$pM`r5AFdi2yJ>hy?rp;vTdf@MNZt^&(MDmh_o6gK4_bRP=c-yeq&BXves zLkYm}=j<<9{w87rFrzC)_Q$p9o28L37dYL2S#S|iEsIJ`m>1eymHKaYYm_FPA~ECp z#2EQh`hsf3%l>ub;(`OC{uDi~(kRu5DRn7Vyo;Hn*EO`|VjDAg^d^tRcUA_k#s(wo zJjf%rpc2*%V+BUfK|X)vPx`a+gU{mp>APj>xb6yzjX$jjXf_fSTzr7~Zrb#pg(sL# z(r{#4Hy3Tm6jea%ydYpAW~%Xj(U@Y?Ri5Z zA=CF2i{o)?|H3XPCa`H}@pT2wh~$mo7aM=R{})C;LHn@6CP7;$nxsDsJi`7#FiE5| zP@CWrQC#!j+^J_3^rSK0)_G{*R=x%;y5h8u2p^Ea{ab}`e^#j1CaQ~TtLXUQz@@rq z3@|YN#uyM6AB%&Oq9V{>Ckdc41Q2{<&rP1CQeh#Ll_H3p6H zyJ*r<1#6D~?Rx2dzt;GluQP+Xe1c3aW^0CXO;qM2DQVSeoNfv` z5`ll}N{sE8YcE`Tz^;}uvl~qnzFmHD^$itLr{Ws+-7p<`LxwQ9Aryqus1sql| zIEC>B=$MF@1}B`2_|UNsaq8g|gpVmVMxx5*WMpM?TXMyAz$i2nT;T{x?UQe}8f+Y+ z=b&vEQ~{M%uh!v3e*A)4n;d2DD@ zXlr?VL<=mdLZjr7aY3#u4X!RYlKX)S7Gcdvh(2iC)Z-LJhiX^Gw{bx{P~8&Kan_NB zDCTK06P3npDJHOOB!UewW(-$Q`dlQ6--!Dkm*QWygu-6r+iIgls9gEi7tAdL6-O#< zP*@Z~pVZf>6nYis7njnCCME*USSc6lS)I`>l{?p^+1C&Dc)Wk$m&OgX@~_id*z&2E z_){G+8tW3yAh_cZnl>2DOM|23p|P>ivGOS1fQ5=-siDxS=;R1#rW$2DXE7{3co901 z&PYsG;as`v4~4Lt!T}67WfAIOs^Q2>k)Gw^%-5JC9BiO_LoHWo+e`JoPiy!LYFY?x*0C2Wa-s7Gs6WHS6p<_Suv_Cg;x{YbHVivcNP|J zp`~t-C0CI{*;dFXg`QPQ{M(w`|NXGN{K#3E)N#tDuuZIwQ1V(7Ch-4UEFA zr`DmdxG)kMit_~~v`xG`u5BD|i)+mrqFaaHB!ZI&2@Q>ji^P{v#!yt`Ilifsq zH}(3K5gQ-;Eh8c-KDJdHU05+_k8euu!7;6j+FJ`Oyze4cifxgNcMgh0wUS4-GDetZ zgYY_Wu_`@1o27e6hDx24i84U-raMg;$?6oHI*Ys6#npI}aqAc=1gSR!=;+nYN$1Wg zFilHimFgTnx>iNKC=HoprtIeA(O$sg+>^1*lggs^Rj%0;!31h(QVPF%RfvWuMGG}Y_>TtE5vvUb8jGK^^nX1N#wlKOzJ%#ZXDl23bDI->l zwonh3i2{3YCJu-d=&m!h(h#+dCV)yt!1OAP>0KPNZgEVX;+XY{WBL}ytY64%84=C2 zM4MsIn$g+9z;$-9AxvCkGOIad|N*8%shD zbq0FM^mJU%!QDw(A!=3l_JjhBg7k6!YfpD6@yka&8T=@;Bg}+>hZxxbG5*J#{xRH+ z{h?gsQQW8h8*(3x<39f1kn4Mjk){0&xhKudWc2^)e-*zskozjo2QUB6K2$}M)F~)v zc``QRx!X0lG)s!gWOaqrI*IG=(-TwF3N|SZXAIm0G8UK7iezx#2z@B)VsPTd?Tk!4 zcRkqElZ}996-$f+Z_blSiQo4|!(k1&(YvcNxJ@WOmg`28Y;bHaKR~ePycO9R%>I>y zLq_pl4Z$eYDL9J2P_NQ)LE_e&BK5n_DB@7pO^qWS>=kKoXB<}CgDOVO(6+JGRVS+z ziQEh^nQ!6|hDfu9yfF@x@tK+6WaJqVr!(A?wnE>_rI1x~nZYF-V`*YWEj`OA&qE{Q z8ZkdnLYAUak<-jao)$(2;WElhXT561>M@FUW@|dhjbd|$%v8p+X0-akuDWI9pyA48p6-KSnjqK;;Q7k ze@_+zAzh(1RXyI#u21lN8+-DRfT?b0Y=KLCE5WOHIxVJwc!oVJKM^WbO1t z867vrZex;E=%4(3qSk$(rhC-P4K&$0h8eO#>nYzloPg&9t<+f!Vwl$@NDqM{U*P4RkDI4&jd|KjDiT6b1WUr`63 z{$aI!h1&J7I_F7s(eKpkOKR_HYVJ*S;Go1yvV3I8&l#Xk=5plEf&Yy({n`Jr{OAA6 z@?ZQf%byC{;zp@RDG2|KR^LI@&A;>fKYDVYq>=ww)nav_CxmE6d}?gDKwpwERxVDK zlFP~dN1XhR3fUb<$^PPh-UMagFVLHBA{2*$O9Vl9VU!8`eMXZBp1Tjrk-h(OWbgO_ z*;lEN-J*dsT*=CjCF>|;UkUfS87Db}z73*Sj!c&1zCM1`s_*N24pp&E-STDhWNg=f>eUgr_r>N#HmO-ipz0gH%@8igE( z1pCP_{QFs$<0HZTd06U4f-@gE4hr@!!cq_7=NG47xzI~Sme5F!x(4(% z_USybUm6E;RE#XacEOAkCF4x+DCF5-f9e-00=7b{j^hH7V;Tu69aB29P z{lcp&XZNONVI3%2Gbi-d+K0AYphkqf4upQ_1?b;lfa(wuhss?)cKBPBH?ZWs7r#&4 z4fX7pp5g=SC2T5z*zUn4ZyXs|!omG@xEQ$hL3$h98{xhK?p<*Az&&_X5I%zEKg0FI zeaIf6M|Kxn+u&+}D*!nA;i`u#c^a~3!Bqs;JCKfps|BvA#|D;chARs$5akO9#09)S z>w@sCg6I2iQ{xiz2bS!79HDnWK2t%q6w>b$Vs{FRIA!I&Dy)B1pir_hD?BbLDol^n z!Ut-hO~S%b%U2|>p40!Qf=%GjObc$0v5=L&6WVVAt4x!OCS(h3 z^L-Re$|~}-CYlUmkj&y>n!@5zGxHSI+<0g1g0$R)vA-2yZU&~I3{2QqG3E10&g6f(oPF*xrQfw1`BA-dgCJk zX5?aSJQ1xo85c_A9oYgihh`GJ^9VASi_WbUg6C!Yx3bgs@&XKP*_qhz2h>N6(Iuw0 z1zxaUbqR>F2ZNPC6LaDrA$TFIt21zNmOWU2`p2KSw@c6kzs18Tn1i}VSrEz2RCW=v z0son%E}bl>mz`-HIB}X9CeF_yg5%KX%1i$KrY--dOqMFb<9m?`kGur3(K} zX{zoj4dNOldu>D_oB5le|5SjNjKt-U6BkCh#{|@k1!T%!Xjz(^pS4kE#X13ghSa80 zBmdB*1G3c5M((s}?O5esj8^{NXw#AZLYqGRueIsDkrQv-Y17>e0yBt=ff4md;_Z>i z=T*p>r$e9TI`j1EYoPV^OR{)tij(8}cT&^CtT8!fW#; zHRnaNbft4wLUk} zJ!0qo1NwX2)UMl|{jXz!`Q`9w|D~q>);pu69VaISpU%`UMB;MJqpID>(5*Vb%m&y8l?VngMG=!uSH;Nh-1SiJ{gv5GFVN7=TEwp zZhnJc4%3mpM_dd&EjX_gHIj#9$BD@Enw`rDwIUrDbj1%3MKJ;3sc$4 zWK~4Ry3@(kM3t&`?^D(Ksw}?KTT@eQto--kuCv}_M=K8vHys?l6xVNQlzn+-wydrz z16K_7mb46eR52D4NznB4G1!4SunA+Zw=m4(QxQ}Isy6T3hkR`}$M~470zQCN-B`I< zD%PZvVB8ptO1=$yO@#SKpyl;W@Esi)C4_0bBIdbCV(Nz5_`e^6nYdjdP?A|m`55h~ zck0_V2BSQ;%fBGP#_H2nkMRxltFz-SL?=*Wbo!{QA}@$EVW`vhtx}wtOr8eLL1$ z)m&5M^~Q45ynn?okZJJvmk)Cuw?Ac=t9I9TDxJeM_3ZXN<)Bf}VUk>%cZ4*O$K|ds z=*SMu&SS`Jp4i}Vubr5Lmv_D}WywOQLFZ0a&en*1jMWh9k~>UUwoWUSrYLH5U7H3Y zGs6Ip@IlG#M`%pLGC)xn<}GS;$6NG_l>Zfh0^FbWza+?WQ94R<@`(-+~_1 zBq8*m(j-TQ$M&arh?uHcHQ{R;r5nAKri(ZEzG+k*lDR&i^Y2HQQ-){Dv5bt!O(LHR zQ44ler7_L)UTr$l%}4ewWD5OW7~Z+M5wU`vAa5~5Vk zc<#BABRAN>`vtFs$DQc-Vrc#8p=VgLhpdtXv-G>F9&uICn~qNLgjR)#>6Kzy`I6}+ zTha|-g=vLtnaY~lF_haev|1ItzGJ9RW!|KsamF+3WK3oSa1_2wHEy*^Q>Y5rq>`_& zmG%o_*CVfmS>`sTwhS#(U0Lm(p8Gx!`L@tKqfqq?TffoUvM~@N^2Kt+-axUGVC##$ zEo0BzMsHvg3HlN`mpMR3UJ*n?i2E0O&|2Eb38{Y^%H@XEb3-8)w39AOqTkO)S@JQV}Z} zAP)*m3%ax62gqdus(U$BYq1P9M&Hl?LKbzt=XDL;OxGdFSW7y{?4j$F$a#!7ByS`m zH-d^+WP=5l_w-2Pq*1oK`DGGR$KZLtYCLV>=|uhynjhx0;|a^BLYZqu+6M%bPokI@ zTs4ZCplnV?+C+oLP~EIXnO}{-Kn6%mH1J?V*0v!mlkB0~hlkcbJQQ+XIqCd3B`Akm z2I{ciGij}Urp+TORNcSH6SB}on{g+IdgBShGSIA6QH3h~CY3OnX&A+sIeLe_C}D>F zK-R023bg&hHZ9TILG%0sZ72WIR(A?ARJ(zzjp(<8Xt)QxU(c>Qk&yW8&5(?k@(Bd*qYWE(Vx35qI$_L&Hbw zMtc@O6_Eb=l2VO34rJ0uh9?TmAeD(jxf6%hPXtW~OuEpDHDy)O3`D6zzOzjF&iY1T znB8q$9DK$jtJbV&==SK@M84t`-*TW>dyL3TgkFX|!O8GB0w~oJol@el5#MqGfZqsBn!$#1Mmz-slrYQk#Ov_e%>xyE^9Xhp*&)xWi$2OMAYlmhMjDD;^W|O?eVC1M;nV9_t+V2>GLG2e9P{$7Q7mwRIB9 zc84)5c^D_nM~M6fLHRn5;WoG_l-WNFLlwc80_)rJk;d+1DVa4y#pX+2)@tTF#zG#=yB@)f7g z82=Kj@aVB?R~9Xswd`4=+lV%R58q5b=W%xoomL%}MP}W_PtOyhvN|j8dH61P{^J;) z|InSffuD64*5kYz)>Cl1eEzDt${V-dx@*qMMfs0ubWL;{hw|;3oec=Msvyfr>=13a zCbbR5(64We`cCdP8XO*NwdB5GS(Iem$?KM!At@95y1EU>xwq*&hh|JC+tZM>{vpQ7 zGU)+kZouy385?JJ8tvEF*k9jr*6&#EWL7oXe;Mn_FuD@?<$`nH$0CTaHoI0EA;Z3u zXI?cf7nu1*8d5fqKsEm559qzsT%eh!Ccu61`0i?bV9r*rk7okKkIKCdZ;hVvvIeHo zHH1~ATDkwz9rtEsW&fs=?2M;m^9|}nhp4dCvq>w57R=Myl=mXEa_QiWpX*#IP*OJ)h zo-f*9Waa~FLFOzUmt`+V@A{1Y-Qup#_QWM?Z2CuVR&y(bG=|)& zSHMkqE1rxG?OCcxQMA90A_s-$NECh$*?Hi0qG__7>lpj(a51~)eJts0(H;|=%}~(o%J4srRH_9CWwdTMof2prdGO zHJv5Tx6;F8b!$&&=F5tz){9ff_6n4y*VXFvZTfroclEA^dH!9F&(?DpJYT1GW#iw5 zhh5d~)c+W)-ukR!bLt`GbBXIu3^vM-hnywLTk|_IJwRxJMG?0(dZMvyFrI`TN)}Hl zpFz(~%u1bgDmyVvjtXB@8WOkk!F1>Q$ax8Gnk#Z=6aF_j0W($L9gdu)cf@JxUzWfiyXgNUj#gF)Vo&W-{-Pi1@6bM zXQfig?8HZ9J~?u8gzxC*8#v_MytOEi-5^IRPnYe=aJNP@{c%tdQd{d(ETSpHWY340 zQ47e@rKnavp87z$on?E=J|IgS$fqBtEr-;5S)}q8$gQW|+f24EL>rc>HmB~JTfMYA z1%mC3ty$qk7`Wi+TjbE~e6)3|e~$Um*x?5ItpJgv)iMX&t)Yo#+mMa@aE zQPWcr9#1dDzMV5+I`vM<9%@3$0ZN{77+XEWalP)Ps@i;olOvs}dMAgRsXAxsJ%Etv z4nebemsLeLTkmc9m%$V)zK}b@%YQ4=sn@yn`daAUSM>H2o_mGklktqlZ`0e8@h_Xg zI`frIqryV6;5>Iu!<1ha&Cf9kDA0qh&pv;v5NM zs3~m_blHzbjyR^=p~_vCRJCncIz1gpX(S&J@a~4!-E#-t%%SEy_$NLvS<{rwd6S)K zAs;wDNc$kKw(SwBBJv4M$%4UXcexL4<+Ua8gXPWmr|ouqhXpp-%WmVklJ(;JSDb%V z4bInhl=cHn{FFa6>@&3;Syz`YGKg*N%)wd<%I_WH-)|YLBgSk%Dk z!F>7XbN+}Bmsb&{)FX#s(3&?dr51WB&zd*inimH)LWcH*f;>pH&(uiP!OdD9O0769 z%fBkro2b{o9}EihR_e_*j*JWnDS2QhB>R(pQ;3xh*2|Kg=$ueDAY{p`-01}wagm;h zU@DzEl>3XVhu3L6rz}F8qVoXE+AE;^KE+~9#qul#xbcWO(sNx%A(i711fospAtsKf zJ)C7qS31{D&i_#zc}=K2{D^ZcN-?K|r6i=Jr>s3B2l=kjqughWGVlkteAUT25UCxf=CrI z!6*Yyw-fx2ypF@+Q7AJ)So9a>DSlJc+|oYL8_8*>tBJY-O%?I=phxk9r&fhF)r7~X z8%ZXEccmHE$jga38S)SY%e3H%jCw`p_M!H_fe$6ti(?}_H-*u4r18*zI4}D@8tC~} zEw#b_!9e8Y(dTfRHoO)&P0Gwf%<~1oabRHC4nx z4`=P_32Bsr8rS_*owh@n`66nR_gqkyMnGIxT%^=ZUhO&js3yDvHJeq9WVZ@!>F2Wc zz(RJ@I%P`&Xv2Hzmd`4_avx4CGr+1K|6MhuD*vq699r=bcDwT5QJdC=*8K$*QeY#X zry{>m!}M@Uo&OhMwqjaP><&CP^}t>`_$}A*nh4|yGB6^?yaBt3fwmSNmKSZ%SA>k= zv(M;@Y)t9mQM}yW4KN#+ots7qou3ybd_`}1ktutzY<^0iEGoxF<5LT94t6i!cg%t` zc1rEtQNl2l3rzIh7dK5=_Hsz+1XKh#@s2`LVequ~3TT08TCm8Zr=uN)P2wWGkoS-OjGUgfsM} zjZE3b`BrG>?4P!C?p^I6$QBVIjHX zr|s;KDEUgDrR;n9fQ^Aw)?M_w2`?l%;maJ$!2f~x%>jT~Um1VU0?5yqquUOm)&?9$ZIz!Q5)dxfVpN!JAw zgf5D8?6z^&?X}1H(G)wf`KigUUTmKR+kj5J-Qg&DK%p}c(16ZF$IX68lnBHNWOtjm zYh&e1eky|V@TEE=6_^%eUQp;Z5k)2jcfw_P}5`uSD`ti2?- zyW?M-+{m()N%O68L&N+~gBKJfrf8HAP=cKigkhW4LL?0ei1Rz3I9L^y%|R-AUxx`j z;pezYN>yQ{CVLC$Q+>A#4Z#9^<}-=1q3DTsbc!u zfqs-ozvSYPsGYr}#GfHC>WJm1Od^EIO~=K7(JeRbVsxh!VXMMMi9<>pGsQr6;V9kD zf3fp1xx_cn{X9WrK1^bM*BJAp)`oef&DcsLNxZMxa$Q{RoJteed3tfempDgg=cf?e z#Wv~_mHoGRdJ`Q!3Eb+%3M@MpjN=TZG;7RGt?GCERK#_iEUqQa@p9iYRhV3PwfK>7appFp&lL&QpWX!;{wfo8cZryf$-Ocpq}=i zAho}dL=L+|%;4z)1-BI@XhNP)7)-lscf-U*k<6TTd7EerZFgBi1N1=QCkltU-;Tiu z%W*Cvh8V?Xkm*}vHc_}aCezNsrC%_`b*^o7t8LG%4s#SLmj6_&D}Y%r|6@{x<0H^I zt<5f4$ci=Ebb9Vqt%-TPZqt;1O^St1TV}P+nDf5W(_`{}2d0Scq4K^jzx$btzZ%4C zzbq8W(taw{bU?)23071TtP2cj218HhnYsLocYp&hsCQRiR+A#hIxPgt`dKBGwbXBg ziv3_zFN^g@+%0?8Jbm~<%s>)k-YqZtR{cj2*z{I_>3v8vy|kyqYr@tSq@QEsp#!$t z#5fKZN-$Z|f>{1J*X()i6ANPu@3sF4n`?IoiuP0LyNW1JfoU$qXB&c`i>VHK9sSXV zyEC{OU}$fEfwpIqpu|xdJr8lc82l8r*pRpLIfPdEDS0Uar$H(KE$M!cw`Akt5Kqw( zh0aER6g!;`&rMJQafprP(|d3|>Ec9y>!EEWXw0ThL!zC(@f5c3qxD$*6qz&$(M%5F?_ZtpYe2-_DsD6oT(l-Kvu;16hT>`~2nsT!+A&NG0`rf(yCuyuVo>q+$ZD1LmOg|6~sOp|3C@2G_Mp;yY&N9NBHY@k|u` zQ|3p>ic=BrzU9VUyzfj9ry}IKGZ#7j(q~WSU2B=0Neb6vb>SD~5Z+$)hDGaB^R0$w5 zkJY8^VRQ0%LqT7AG?Src#-^3qRUoAu75k-WCHyb_If-=pIe`%!Cvl#qf347E5a3VI zg&X(3VJL{|)7ujrjETst?|UNAH3yqx;TObH6L#4MO1?djc_4OKDA^v3X2YQ` zJ5YUfkv+ZEzQb+*gr{G3)9=*2tY#kBbE+57JkZnKI}hM}yUcWXfx?L)iEi4)pIR%E=GvW0i2_;74;v+1 z2&tZu{EGtF!~#VqhOTnMdcbbwciKd4?>VW$?Pqh?KPq;*5&Oqjwwm|;QBg5D|AYz$ zjYauT+LvYEDN<7wYgum&ybwS5>v%#UjHrjzG&57X~FKdDc`dRmE8R^bqFuu1E zO|-+D6YS7Ik_l9LU#0oic6hzTHGhDu)0aFo4F#u9Vkt>|$ljnW4DE5y9)_LnVBL)I z@(q@qgGtd%G>yfE7@o+1Dru;*WLT&i7I+%ftGqQd+^d0SIHUMioY!|(o^CWR4$4BF z|L;QO-*LGXP0206dk`1>Km$K_)4_N>Lgf#mcvk@rlevvIMzdJt#{%ae-xhGaLqg@y zPk9mvSHebW%~%;h_=|{p^`GzvG^oiHTPc;nLsz@!SKS7BDq%{M>HKuJTq^HC zv8M$f;gL~KyDc%pBxRteE8}XpLd=g0;u@ZQc#4xXk|wjRn}kx(mKkQ!ZcUe#dq_}+ zpu~cKC9B{PCQX7az5!PsS_f$+2jvL(^eG`nf<7G0!D;;j6o>CZBH&#|0+EOo;q=6C zWEbxfP$JypTqtJ_T!H|HN)d_Xom0hL6ig@N9$B(&U09ZR>dK}I!m--&^KfSE@oQ;$ zx=5Yc@mC@CYaylC@r}^bEu^$L&I*m>)RopeP0Gp0@oHTO4dbF(wZc>8>vxPF&ZrDzPpFplnv)iXLZ6iNGeE<87g6GcNcn&hp5C zHp>Ut<%FBAv-xPr`P|w(6vdoPhC_XwFmOo$*=lxyEn^oay9}Z=l+i{pn`Tv zgfARR)uM=#mBM-)@;#WuIt9yaG{mtxu$UY#3OSF942fBC-~z<7Vkh8b$=PcCQI&2h z=Vf{;pA)(=Kt?VbMvj+DGFrObS|!^)uUfXkv%2aUri~fR!p$+vW498444v^ef-4J` zStDkV@Ki-Y4;z;1N;&p1se&A)x9f3ThufkaF(h1A(NW0p{oC0t!2oLeL8lTqqMqD8|V)kF3NxOj`oP~CM<7x)Ml_yCh` zQLShQN|s1Uc1z|2(YSn^DsVs-IE#y&k&yVq5)I&H zmS`JU7`ZQu+D89xdI7Ua#o7q2TIbz?QALqesbX&k{yqW1QjAr1SDx4?Btsk?)4~v@ z14h3|vioYVIe`XU6C4^*(J$@bJeXd&G%4|LzJ7@y;$Qta{=h%tw*dWm(M||>*%AB* z(pZLrAe|hM=c1w{!8UGVaqYV=uk6(3EX}i_a^2-)aVv< z4nJYbg6>W|_oj~9Pd8n{(%+|MtVUcw6|m`GlIb=Pw3*IH)Z3jj*Qu*KC-8}MP98={ zQGwocXAtmcftR6ZI0e!47fho=DHiOWg_3+@!mq;tR^ZKSzc9k*BF4$HN$ zpr8P^u@zJFsQ$8f@;R6fZTjvD&CHV6?sG=wN4~rJol*#AqjNW)x}W8|LUYB&?2$v` zEu@_z9 z3w%IoA9NomMMG_O18zXF2Hv=-{Hx$f)G@9jE~zIpH9pA7(m1{rx~lan%I!;a;n$6+ zUjmlcQ<_gNkfo()s+Kv(JO6ZF;GI2zca4iafB$v7)frf!2mNE_@Cy@|IeS2FAl4TM z%LPJKsyy1;Yibe9%8dlKT z_tV^u`d|ayeOBMyKzB9JIoW!?fdHTTQO&UCisnJhSh)@ zI{weJy%U3vie^I%6Ni1J&b11I)?iSU+VLhF#@BJLW6(Y|F!c^ux(0Rc&^z`Dv2{XC zVvQ|MmMo{*F}8}CN5fLeZlj%V^H9v5fQzMI8&a>zeN9N+EjV@yIZx;~n;z_HO-4;( zZnco5NS4*a}?cs47cQuSv!xzC%^BBX*nMDxh(XChD`)-30`*NM~P8 z1H)2}#jDsvJR+-9sm}|s|0=lF=tjFzMVo?7?ghxplA%z%B-_$&PiFArOg|`v-Gmz% zjrYSS89c?S8^zn?M`gpZE3yY=XJyA_D-)D|6z97X%^?}yfTXvNs56L!X|0M zqR&Ae-k<(X`|kh;s3ohcZ}ZF?>}AGdIVP)OQ{W|&|1_P2^I`QeSHdVg24qmOq}M3X z%rL#wzBi^5Q&UR%M%b;*?2AUWh2szE1AF*g4HRf=;2`Iksc%;z^a#n-@|1R0!+i!1 z>*06{ytT^HCeCHjH+5bMG&j=^#DZ4S2lIcm(T?MPiq>EXAUV z_A}O##-3~Nj+^nrYxHy-Jv!-Nqp=8V2C!+jOSS`L=xGxHIzX?Yje`QSiGXl0#IcNh z0xZOV^coVD_r_i!XA@36i^Il94)z4wk`WlYxYJuyTjING_1@R+G9?k>+=X*ZW zPTdkJSB?Pwoppj(xUx^2xn9E+h?7~1hMHV*{Xbh-z{v`r4fPvGM7v9x-l}HVSKOzE zSdV!|z1sBFX4;b84vjRuRaJ6MpeFyMO38APV8DhEw8M2+Ts!$c7mRR(9?ZC=X;7do zxJ#q4k??4s@w5f=HkQ8nv;0XTcjb3z0n?%>ySC=UWz1fcmWtr3`CW?%3U^YK2HeB4 z0Y$iF1Wrs;9v6Ul3|4!+ulUXkvDN0GH~`Jq7lNCCk1sNmp3x!)$ z+Z*BbfyPk1!t-hM4|v-Xz1h$ZGwYLqCGfIYw6TaTj&`KPf)5MJuuW?xxw#k0Qz`1G zelhhtHJf@+ahB2+KpZAIHFLwrBWYM>F#EXWsHm1l4Q5nj-W4;ua8JzkU9iS(J4|?+ z`AiRT%L(K$m&JtfO!0!HfQ{ZXqZYHbsQCSc6SLy>T2_>NBXA$bvfG=f$q)@;`@Lu~ zyzS>l5q5Oh9~|VhKO({0-Q8R8>o7{={*QBP4PL}|y``@vlrZ`!6+8xmz2yY(27A#2 z_3K)H|DutO*x(L5&B|*&+TGu5Kpn;pa=V(0{6VfGw_*QaLx&bM=o|L$(~5!6HUomp zhW#DJ!3IFtr>%GF*K`=`W4lfm`LkTdxSAT?qxZinoScl{B}SE<=PM(>k$H%(;|wN{ z0y=5-q@K~2HIhjm3d$C&P=atvI3oFRQKl(T*82-W?Z(n!@ado%sz^9M4)<~}3C3;1 zB{zN!g!gQ&3MFEo;BMTKjl;(8Bn_oOumUzg*21G|Kzstoz@2C+v09SRNATV%Yy<&SS2LXt=v?&44c zq$@`Rcs&_>WvIowgJl!-a1xMCr2T)!#>)9Pf?tn%ujeM*E#S^?#O=Uzj@$z0(rrO- zUeIlc1oslA3n@~B2#GGHXrh61We=_cd*zAxnjJ95q8D*3tcmu&i)#@VDq(G-Vav*u6N+70$&_t4vd4y`tpnrJY!9qh2%&C^LI(F00%SiOGz+;!OwO0f!p8l z^N%9Ez)#CRa94S)ZK?&fIxRb3*V{&^DBsv))l`%Ch@!$^Kb7*~9Z{@v1gx8Z7k>lx z=dmm_c6%>Or5uF&nc{9Z(J-CX?a&82I%+yrI}c5J=*sLNKrI*NS@q7%SP;pYEhoWc zfv4!PxTZso^&(3SbkZVc!8vEF4GNSje-w^?nx@Y_BpT-KLqMrb=Vv)}Z7{-30@i!Mdi?$#O13AA5b!o6}+@yOdW$)C{t30I>$id>02YA}xmSPie0mG=my4~C!nF`k<$ImeAzTY`xf4J247P>h2FFNE#N}jdp*YG* zEf|gCLYfrw4{0Df4w5nxw08l-ac}cyd}gqgTMG@*x-AxJ>PhZ8rbO0qc{pvLDo#o~ z-+?ST$*un>&dRCd0AK->btaRAT1ZikEEa3P^86KUKPiTJuZ$bk0^zn%itv8cqY(TB zC~Q`FNYQ;djpWgI_5-{C(tX^_%-WTJd6&=Tr-%$w{aiGY8c)>4Z` zAt0Mk$jVU&X&Qq(0u(JWN(=l$q2t<<+@#SuR$*TYbZyq4iF<77^2pON5c(FkC7Lpv zrLJJkftc3aIam-H;=dt8X2D{OrHkQA6xJwu83ZkoV6_F8$_{qei4dCr^w>mmj!C~9 z#{nY4RIUH|cX0n;yhlzLshd9nA-1S6ZPPUYjFEo<(>i9tlt7i`Q#|*?e|5r zKVevb1lzI$gSg)SC@B{`@);%ul@U{InARf_#L8_E3qo%CE3KH*xk2fW914KDQ{QUZbge^N%w%T4&DV#nhntQP&74cQTT0Cr3EbtOA3c7 z3hsiIngEI`e!CJXo(hj7oX5lD?vyN@Ea5!0R^+V!<4nNBqiz##*P%t`F$qFxKv7a+ zRd?Zp0Nu{J3YE$bXi_7Y7q#e+>@3!+I7K62H81Fv!IRY-KYCvXcNj0ffDrFzS<*{7q>6n=s~<0^CAXek=ID6-tf_2I0LF zh%eh{_&N^zQZr=6Q}7cb@$S%Z^{nIs`|=PQXZCTAnO;ZpqqV-bcN_mC z?Ak*bj|r8Z39+ByO6%3kf-!dpyZv#nfJZF14Wbv!0vhmf9pZX`wC+c+&}ZUx%%~3r zA~Jp;_{28GktOd#@KtiYFdbFxTgZ4ofS^03fL9nTWNhoLl6M4Vq2#rRSjHxSHtQh1 zHtLdL#5k3)QQ-FAg5uI7j)Yc0qFOW=_^fm45B(r!cO-%+kJ}Ol<_p_U#UavdS#(@} zmS~hg+5&xRGA+QiRADm3kKPxGmK1EB@vHt??y<4CX5~rlSzHFDjmPk`p{2H* zw+nEe1l*Z;9)dZi9@huBPvZ1UY9;mbPXUimFaH$q)Jd-8rx2k3FhFpPPvRP9Qu|MG z*p7|O{RjG~nc#!KR2YM2swb#N&vSCI1fJr>8R!XW+7)V8D;0t^f&b*=xLpy(vUv3( zHD%ouF}Yoad|ZHX?ur=i^V5`RSAw0J9u?lZ#i>T7MS64{t{_|x zXITGqKNS-fa!3Oew)x@f0VpnnT7X@rnNl)3Huai7g*v{v68rj4=`UdrdqQCK55CCp z@zuF!QZG9Wfy}XnctUb=FdWX2*K*`>C4i`yo;)1X^eFu21#mq_H)Ze!ok!914F&}~ z^y$>|M!CI(D*`gj0wze#V@R$Th-JN8Gj+b^&`CO}XEA?`;W0PK(HQM1($ zQ81is2Oy%Ry;mOUF}CQpzwzO}u?=R3!0j`-a|uH=#5bb$k;+!#w0>R4%$HfW(HC|9 zX(P+`9wN&f)PlU@B&_JFLSUc97k&RBaLjU`zW@^JapbK*?lr`UYJ;gdHp&`7jXR@1 z?+4W?K4YxXpX9bYJsu(@4PuNpPGPJOz}trnAZUEFc*GOU@}L|qTohcuBYFh-5N~F< z;Lhj3o;JWi=OFIre)~Qs)}pS3UE6~??jT)q4cnU!u)Tq;y^tX|=y2EWVTZcu2chJL zF%ZUTQB_6^K;#o1Mf2IAg5`8mkKo;X2c+F{sS?a(1%{O4_+X2=LuPFzX=tXYz;hhNJlNKq!j{jWphrP9*pso)QY59O zrrVQoohgbs1`m;Bg*`bE-V07Gzu8D+DbgZWz_QS-SElJhn)R}ida_n8_vsbcSzTYT z4M$zB-mb1*unMaeD_jrqV6vTQ@Rh37ixjSvIMwiGP0jXl)?{?1BM6^@aROc(8*b9B zVhTPbk;f4p`AomtvholrVPK`j{j!i zxC1_~!EQ7ATl$-B39QfPcn8lP5O2t7gDp53cBP;_^>PT9@bPqIpg#w;32d~t0Z+A+ z4gHWAk0T8A>Me&s^ej7JbP7~c4L$eCVv}z|?875#3~^f?1m>s+IQ+x1a#(jlp(;7V zr$OQ1Q!6m3vnGOd)3q50a?0gU+yJW}RJ4~inH~g_SDPuCfBgP0Fc@93u7o1p?Y$5H zeHw4vLu4I%i}kZ^u5mRTdm5=8>E$g$+M{~{0))Q$Qo9$t(V49*P{o zj$jo@S$=|XYO}an1OAL(3tLW$D9|mEO9;j4`lVu9E{%DKqON}pym!L|t7tCM~PYV{qI+KN~ z82ked+&l2P^Bh|LZ+#HQ3BhjA1J+zUgm-{0_y*7i5FO;0Rne^}C(?3tkNe?u`S7jN zDbkdC4`Y`vH!-me=&j5!A^NH%go4lD!HF)mv>0Y=cWx+j3IG>~Ar(A_lPK;gHT^xC zhFS$5Ei!Q$#dZ(Q45{(nMXsCU>^fUQGMztc>1OGxj5|@LyPhm zLrXZp>tW$L7;dASEqD8jVXVgsVJ@V$vuqP<R5^3D7uM< zro%c4*LxQ~lRXZfaXf5$vYueq9ono&yVj@}W5@s$tGt1IdT$NSmUma38zakNiSB_j zDPCKG*OXw$U~TEFDc#cqT2b~cS-MxKy6WTD>7dRCI~rfq43kY?0B7&0pBcaf?tT1 z!*6#t{>^bUHT=H&Ri54K_CD^;{_%-IPT<+o&E7T5o92;VVzM6%cDTFuxw9V*wls75 z`45cU&o)zry^G+;Zue<-@TmI?aoQNHZZ0~@pD~^$x;@QbZaHlX9O9{IpUx+!aoek1 zrF6|7GLsP%p2i`r?8Tyk`m>7T%0LTU)S$1{*NqFQ(t}wqs@501|DyXCaaK{ZR}V)) z;r&rI)mWzuflR}f;3%dgppyy2?&4TpFtrUsyIN%ae-{vG4+NTyDOesmnlFuRtX@PS?`YZC3r#Xd`>eJ`AS9-YsWTv4$vIk*P4D;Ta4(S!D-IfElm{fm5{v0GbJ+;dNhhn%4GQLm&fBIzR$yhx|<0 z09t0=5_(oaC#Gj9scUp%0;on>WF|UmrVLMoqSwvz?DP%XePAB5ltrclXaeLOlA&5N zfZ}qi);klBDFw6-g!y;Svl4cAedYj2sY*qSFM1YxPS0Y)3*P2UVf~^TV-BY$18?MNy@2XS5Zvoo7 z=d=;%BtiJE2u1JHsM8FM&YwVrzpvS>1j)IL3Xu7R87??p4fVefWAXtD1gdt_JAfM6 zZe9?dorO(nhPlA$E!BgGfz@4=qn04hvt}p@HiX;DLroWB4lBo@EuqL}rfuoeHRxm7 zmhe<49hpA0*KSH+m_#@+1IHmC955|7(>61Mu@<}1ieZc0N}x1?u%tp!C>3LSF2i6m zWH7PCuGHf8?_kDui%gY^EP3u?Dd}SY9q;Vy1pS5`8Me4@ozXue_`ok93C>fC!2jB3 zX59|X#M7468Z0c>R@qk;AJbIW=kB-#Ur7tJG@D2=&}77zzmJ6?>`VMl@z0dSD*y*N z#6;o~G7!Jdg|l4HC63nK=M^h*@mr^;R*e=`*CxaFjtZ-;dE||R+X5d%0>N;>;;2cH zQ8RwAS#HSKFax5?Pr@pH>Pb#^9^OC!9SuQfqq$%{yk`YxJgJ#!kr?H;mRd}W2mPZW zpI3+n-7Io3oDg#;WCP`yRK(L4`pX_$COP+$xSYQXAV9$O8*MgGIZU+DKhDRD*nq(zjOYqm33leCm-d zjqC+vMOa%s42=cKX_Ab5PZ=;ZBsCa$DL9OOi?qXOsO@) zAsCJi?Mcu>O&#bsdbl$s?=S3B0A3p=j-9^ zc$+mDEmpUK?#B@u65!EL2Hz>$G?z^JQmFXcZAAW$g*FvxHp+T>h^WxWDAQt#vI?R_ zG1tIWNTL@d3yz5~%1XBXyHH9&TmoK(nt4rz#MsN2@JW>Pz7VHOhB#u(H90Ol#&Nd{ zir}3hEYWGfRZ@(*N!(LzB&JgNbCrFzaa0@=$D=Si?4c>aIXyg#WOkZqVz1k$wy|#h zVnhhT%%SiakoETR(eR!yEC3;V&oE6jCddLOY(cD52Ctxl1;C02dKWvr_YmQciR&fF zNlTW2KkuCWD7CO#4x29zLiFU(+DZgT8Cve-reog#3d0z2Oa#4%gKeH-t65LME)aWV zT-PuSc$5>uIr3V6oZIp%EsokOXkZtZGiygIu!khIa)tRId?{;>xU-Mx1+lK3!}dPD z)k@%<^yu}V%|&!CoD{kGc+;8_@g*jr=!ZG$Z(dJs@>~VyfBSUU_kfrO40ER$jt(xG zKL2&HGy%0IqN=NuTpJHV3g{VZ>%YIA;*YM3KWAS>ds?gD-M||7Y9pL3F>z#EWpr-# z4sT8|D#ZcNvS`IA6_EtnFx=XwRoEuNBJF7vcopMX)|*WF<0^Nq4y!+G3WD;-)Hz8D z_+lp0uOJy0G8?4zt9l2BAf|ymX11iR=;RL@=|y}Myz$%1n$2#bu42IdiEui#96oh+ zg>>DZ^Le7vYG;doSXV&GJ-Ja4_nitwyZdHth3}+fr@xn_pxs6`gEu6C(TsY9Y(FXF zFvYMhL&>U6tn()~d2Rd?(?JMNZL{0b4F#TaRwsJgUlvX#9T7_35l~f=sqH^ZDcCc* ztzoc$$w4_PxIhO$On4elruwhHxxO8~4+FO6Ny+wUNp;_2bw$a9Kv8xmhnTj+*j;*4T z03Th#!YFhv)=xnENp~zdx!rBTM{}`$=RS44b^^@9X^{zF{5Fs%Ee!1=P?_1aYWl?pvebzBV(ji? z_rbemMVkXK$x)UKPE<~yP3DV}W+)#-xD3P}!MT0Rkb%wbUY=u%-A;ry;{(zcC#l;L zP{GF2Nplh0$Wj}6UZn(qq5DuChP7Z~ z7cPRRJXlQpLJgkNc2oBO69AkEKx#Yy+cG+rD-!Js%eA`+RIATD~zEuW2@?!blN>s+_b zkJNISd>LL-kKtRCc5 zE^^eI8FQ81Te%fU*l_@N`fS zmd@E*tE`0`NAPO4mydxV$RNfTN?y8#PjoDU(F5->LDDTKEW^x7g>@b{_SaWVLU@8*dC~Te+-G1EJnVd^kk;H^F#9u#gpb zB`1V>6+j|22;PPjZ5q^8(j{n3P!nrnBb5k9x=B^p2g^O7K2ptA2jbOMxNi-lM7T+K zgm>gvY;)9QJLK^7L8sbHYDYoZf(WYQm=I?*S>TmqI$D*FT{38F4}rvun;}VdY#tV0 z6})FN`c4AKvvNT2sI{JQb!P;uf}sqSaW5cg0SOghh{&&WI;-cmV$dFNVC(+5yPh|R z&vGKTB!Ud$e(JXA;e=8}DEw@==Yfh9ED0Vi-tmeVA2HOuS=WboB= znwLS)38H5Im$x^Mi|R=ChwGePfums;1(VaQEsf%&S&U%x=Yb&Lk{LwBH8X%VqLbVq zj)|J<-05z;&>*=3ZDs^V@9pl`5t%Rn+!rPd8q@@5)R|}&ogk68WJ7~S1N3>nbxwmz z=DnZy_s@$~pHp>edFrXBp4y)0Da#gTn~@lP#<=c^Fy5xRto&Lrz#4wasG;IOaOVYu z(FZ!9z$qW|)B8x|?d zm0S*LEZf~7C$5L$#q+7QI(ttHe@pE*|}Ktt1c1 zzbv;Pe3~+E{BptOt#}#pLtC3*dD$W)^KOl*S)+7l)VUhQQXkS-kNwCHY)$4CjBsl- zxf<3|&*T$8oRi6Z(KXcFFWX>+$P>NzTN>m0FuJ&{7*xs0;#6bcl*24Vyj#iHl*940S^30+uSXfnQGQJue>vzvX_(`KdsS7*uFYcJ=~<2YdZ9OLhmKi{%8e^IhvU(SW!oy1I-!38xaZ3Rynd`r1# znAY+PEN#JJk$6Vp$&E6MTx!!jId`_`nknYkorkn%l!kC7-?_HCcWEvQ-lR=u11$?e z3fUkC*pZA7D2)Jtx$H2Zh_|s^Iy)R+&$CZF_uE3A%_!4tLV&TlzYX*-Dt%(>}x#fhDrYtIa8Q3G&b73nDX!DO{= zG$`;lYJdzBUz^5p5g_(XXZYJkGObmyA17ufay(xxKKD(1F|Z9Hab%rNz2m~N{Sr&RoYFJ4z4MMpjz z6kR`i!MgGP=v)`_n*Oy{)s2K3-c=C#((tNvUNue%-@(Rca9P+-ra|l&^=VMZ6&`~9 zc0r6`#4;IX)Zn%*W=91UB_pl><^9MaCm&k z7+pjkDaa8|cR^^2w&4jGFPCr-W*m8gr->qfeE`%-ZOfafMj*Nw^x4=#no>zlq7rRN4w zXObmfcb2S;2`pLd1v5QR`kWhvma#Hm!3jaN3d$iDP=QfUt(#RrN2-}s=CW#hJ@_ zEaK*?H}##Dy=PaXp`+k>2Tqka8+m46yj=!I$gSxI=vdZDQmqMTJ~R&&?M)n=C}%6; zbbuR({uiU!n5~!#ae?NyAZ9_j|HxtnmLORos8J%RoleZ_6jQ%1si#YZJ(5>BXL!kL z)Vo3Xa+kSnId7Gud`^{jpb3sbldL13U(;OOwO~cl@92%8dqbx75Y1Cl$L!92B(IjFJt;K)7 z_GO2Lq|UWDZ@7Zc7cZ5KWHYCe$hQJK^B61fU6uw(?eoJr&cvLuY!7yvzGrhXRoR;o zF-GneTa;%M=LpfgBF+d$c&hLt>z2Yer zYpxuN4Z_YE#;P`??5j3B%V)`>pHeYOX}vz4tjE0eFDE0iBVVjP+W7X7R`5l*Ou-qP@SnNoYP(kz&3P+ z1NKoWb_+92FcBYZpKSbkioSFhIhJH{r@hW%Q-bcjYMJv||1dzSsa2fPmK=8CRUQUv zZKssG<37YVV4qtQ#kP+ptG8B3{Jp}9WzzwBwv7cflS1%!O63Ylndr?RgzS^05JHKTmxED-1V$=;AxU9vpL~6$F&7|gv{njDf8SVC? z4UFMa+O=dlXfdaX_FIJ~?;+tKU4`q6+WfK79+HB+XQM7?LrK-z)%x1GHFNXsUpDI6 z*e6bg2f6zD(eHmNE!v7Ao&?8Q0J`5Vi_jlJm7Wf(uqSPQO#dkxM5cNVS>ZrqLg)1QT#0yhip7jTtW zJK8P1(_vykY{at|VI^??4p$22fcqod*T>OLF@zk!`#Cs5`llCHA>HppG0J&ox=>7n zYY4|)bJLe%12boi=Ut_4_vg4@GIs0mgkMob7o#F_jaZt>5M7p!TaJKiU>*CDcuOoK z<^}>?ptOI|y`n|zv_N5oB>F^=xrj~QMX;%f*O{!Rg6aP0&szfN(DvVqZX?Y(o6Wka zlOsA~kZ|1QF!=O(?D1rbb8EU6|6Drf(4C~28(B@)Q@VeX(~Y=##h;$a@n*9zZP30c zvUTW+`njtJSp=z{jI7^3;W{EV9TD4{ce|HJ_oL!d9UF59Ld8YnSqRQZe(IZ|q+7j1 z{*F;<&5);P6blw4mBXDEgpAlXpxa?s@N?^|{nZtNw?WLhN>P?;Brzuh6!R*Ixd#}mWBX%H;KL#<4SiV-^%oA~CKS}~ zh6;aC4!Dhg7**QO#mSSD!OuCfl}#^+t^X#vekmHV$lNFTT`$tQexy2sjrtZv&={`Q zGlRtLW7Y2vE}R}pk9DQ35VLG!(w2)tdT`#=h^#KQeK*lv=xc!qAoK6gDv=8aHlEWV z!t;}#Tl@NAY{(Jkyx|ZJ!c|HVdZ0iltfgAL!7l_}D#Z6XZOmzGh~X*>DRNa+M$w+x zhQAWsmwg;X3ZmwW%t1@j-sy`| zwojxj3mC9Y%_yr4ZNZk6p@?xd_F}DP_!Wagk+idYoFq-8l%i-{@eq^ko~83Y+yg-6Kh%{UIqh@%TM16ly0F56(XBu`euygPglIb^ov=;ibMf zg>D<&lcqUL!4o~|IBW=v+cZ%M#PRaDH}z6D_Z=v3a`-SQT%?F#~Ad>UxMH6W_0;|n1-^Hcee!Ib~5IACLw9y#a?8!NCCd!ujF#l{TV~2 zDTXT==h?MQnSHM2E~ptjX;5h+XQ_4PDa$spv4z83ZN8>9Uz^Kf7)^V(`LkS1vWV_| z8sQWsD11k7N5AXMuBJ(S+-Spq=Izy)uon*X(5C%J^}1)I#1mXizNRMl-|$3Hf5Lc* zjUzs8dkbqgc#q0F6VCzZ$r|LR!n0rU#~A1{<`d68Jh%$OzI(dpKCrJyJpuoB)%!eQ zL^leUsVszF&49sl*ZBs=fq(U+V?#J>eg(^RzpzP(C4pTVxrkZ`r#r?!h<0ryY{TQ7 zZmdDx@pa|%YEvQKad#@KPb1OQ6SYBUIKvHv{KCsQze?yjDIzIEtFRa=cWtP?VeMX~ zs^8@fB-gDi3inUR87OvKRvVI369XaJJ1r=Bo!tddt0n#IIIqZ65S+|J>w}WAw%!ho z^NzP;$2EIsFBHHPIRd#)x_`#B)7la4qq0yKC-45LEGK9^h%VwZ+#lPq-Yi+?L{Qbbs^}uesk4v(o~Yh^^hW%R zZ8bW*ZUjC>>ya4ox1&|5SBh4JXxol_%Rw;v#g_th*F@M@vO7v0t>+@KcBLgVF9l4{ zLsepTl&Ne=#Ihy3qm0Wcc1MkwGi!Ggn>m@_w3@h`uk4P3IqUViqk;;ZB`a&#(qkmk zMBctZk2xd%J!4~e)vn+zvtqV5T1{Dh((InV#BX-AmdvWfs;VxaW~3WCl?4%ySbMvD z_6poZhiEJ7wOQlYLg!e-Ta9@A*#TJc;x3o;f{5qUTqNd}_?!Jk%oca6Y1^MPS;%vy zyR~F{z5D(C?7#7#yCmKut7s$tc0$edI>O9hfSn=F%FpC-!| zLzuzgEZG*7P?j3$a4x4YQxLLZ8&H)-N~s8h!}-d#sBsSG`fX9X!})6(MMu6oENF~hFpi1hBQ*_&g^b6ZVido)>bOnf#7wqil< zd;N=4X*0x}`J3pDwhAbTUf|G0E}5CGBza@S=e6x2WcCW1GinW*tWKL{q)oO4O}1{$ z$$soXM<;pyB0jH%$YcBx!(T*f9>p)Q6^t^sh&J7*2}zbZ-g8WB2VT$%a@Kh(-?HgO z1g*QIjn}rT0OE+L+V}ux`KD5qG^h0a%8gQIH%26=Vd6r#h7WC1P@qx7k$pa%Hm^W0awA)586s82D!2N4CjuXw3d*|R_r!Rrx>2XCWMcvz90`&rq!Yz=MG7-)V}{Y0G3=zkPQrFr zb;hyQ;AtYt7+cai-2^AcZEmn2ZjBb`ta5vg9Qh(T?2A!BdbedfweCXMw8Oo5J017w z@e$H+L1%(ue(+>S_q1to-bB|Oso>lA*3=JciS{5a03<=ksVMLJ-nU}ZJGFLgo>nYZ z>SwslE<_(Tzyf_Vs#!`uBZ1118#em zboORvvB({#4S|kPQx_7xYu@QkXvJY!k}Wcvr0ToVd>B`-90S~LBdLGWa92ba#V|e7 z8_MIH*mMqgd}yfk=Yb2XDwRk-&1XIENc!6%!UoeDrutm1A{Sr}EQRDmC@8;^uw2pd#Bx+L z9ym40=Xjn;Se=RqZ%Nd{VxPi#U&H~czL=n{wOTt{uApc#C;RM)b?KN7m=k?=wn+Pg zU0+#Ohk0y$ox6}ReQD%BC z;dL7kPHiRv2Uv`t7v4`Zn?yZK!`>4iT2>E83{U&qyNKE3gCKwF9Wkbld)_m`XI&{e zoSP-8vEHI(*J`aj^eG=gcFO0@o+bszbsDTfS@bqfqrz10jh%8ASOy%Zp&XaK_lmM@ zkr#XJP&$+CC!ycPrs1spNF}pRqJIf~^nVnC8JK4T!S_a62oK}7H6b`w;Ej#d9e12= z8#U21-VL1t-jK!{>6*wENAT;2BNodYoG5Lp8CF^6`cf2Xpo8GG#BF_aq9)NnKi1Bk zB{*|+Nie}SA^H$9K}~U{KT>+bPmMNjgQSzN1aSd7o&OAC_B@H2=n9+-}FUQz0-+6NEOb z01q#ij}5E8W+#Wu;-XO_BgZh1Ur5+Xqh{kK1v+M=;?5md8PVsZ4{-WRVP_OmXT?Mt zUSbkXi!n-kmyY=fiIUpg7Rrn}gw0t@vut`L%=?t3-hyN-x^rDF#~xPJhL?}sGe0gl zE~ESROJYZ;_4iha>V ztCDluq6%51!}%@7cT(ZO6d$+Z)S6BjZ*Pm#aBJi&-D6cakM_)5a!Ow}zeVLKSYp>B z2@Ln+vQR0F9%;(-w>jIkKYU=!sL;n{80S~m%IDMiqRlvC`HGrkdwAJM%^;X|Wp+kZ zO^?~PIGxpUEcQpzohKy(Aig7%iLsZB)N;B0IyLJRZF=Q-z3O`5y*0SU3OfT!Xs1G4 z2~V2AnD+GQMqujO6n&~PCDE9h8XgBA%EwYX$$SFws}G80hk=(&j@T1xlDE|WFEwLN zrhXM|FHdf6i*mC{PKyendKI6Z9|n}1l~FS4VU!rE6nZ_II93Un+>Dg@oglho1WCrA@z{9>Mav2ULFe7w*^0B&ob-xf0wh7@rcDshgsMR^h==5B|enw~XeEQ#Ds^v(c3&i5!L4%(%`nR8_^1r}3V;(1#{y}d9C zQ{U!ZfdsOdLc&`fvaa!96zI?4`)gv@aXkIQH zCl`h?FV7Jd&t06h^59S-uTLyaUb(HOMqfO3+cP(!*V)>lHYC@DJitu_3z>UL{zd3E>XJbU$pdIGZ_ZtosN>1C0k%%M|3X$VR>wfefX zHEFo?eC@j0sJi*BXCd=aUhRooQZwImMzmKW)A@_nqNKe0_afgS=uoXE5yca}BqhVB z2kB(Uyb$d|`-(j|J3K2YaImjn64L#_kNXM3(mt+~`*?d0S>v>nU|*waey(0osAnPk zPhj_b;X!6%P+ObA_D(-$;Vq1%BiLhDQn{LQ$nA_II6CLscys6c@kRUsFQkyah-hzM zjx?FC&4)pxKUj3S@w!}=ukM_u?w+s+S9AC{`7$S{Wbcd1nCPewn4%^J-CW zT(=GUGXVQr4FeKCTZ84`h|Gm#4Q^$RT659|an5yzsC5qO7cdU(T(5D`-LmFZ9=FxM zD{>1#&4XUdxz<5*qjctA$YrIWUF24(f55yGDa?mO?qK^}*>i^R)QMayL{I(6J%19p z$(i4Z1Tk?XIb+@{;!Zy$mjx3X>-AhRf*-5lJ&2wnW3@GQ17vFWtm-a z7Ts+kw@v+-NF$?DuGj3b{>wDn?)DEw8AQW-B6l(Kyx7_(N~N0NzlJKz32Kj$W8jX+ zZq(s>^=YxyBbVbjCB|sf?}@E0*>CO;V@5zBy>+LYiRTju@R(R+gssKaS~T zg5rZP5#<(cu)@%Lklnh*d2(Hiic_z$;+D*)Eq~-R+kfv|zje(_vfheubtXhBRs|auL<<40l)Y;PQ{lU}$x z)93t-2#4gksrByzQ2E3>*HMgZ0R=azHi`?VT~uqVP1%!uczx}m!}h~9?rdZ2soIYm z*-?({k$wXuTI<(z8t5*jYux`Bz?n+xmm;^svk^toy0r}Gvq#F~iuDM!!IymsGMgRA zn7kBoX@9}(QbbaI&MwqQd)oHGjaU833X^`UQ;-v=~`%AJzyCdY}piCq30A(ur}%EB|59<^?R}m1W`jOP+Fr{ zcZ#lG44A5t0i7v1&0EV<*kFwWZQ)m)UqrLECwwRR{dU>k1HUvevLjDBo#zp?veG}# zgGA{XhTHC$#BlY7NlXkb3gEUIJ|Suj6@hAKcM{`vGM*$R?Urc!Gp$jL(l4@1CsQ>_ z>%9Ae{^a>P}NAXUcOTzG|&5 zbHLSh-Nug8Jr664D8Kns3?dkVa9v$qI*m)$)1Uzw_t^p0LBx&HrT_17tyAd!Z-txG zhgf?rx!U+mAN#X-tJn!!GYTZL&*SeBheMqJ&K z1GGegT%tpU4z?H9MoQ2b>5c)-R_cRcQXd>8R@BN}u5JStg(XAfcA95^EgcFWgj!HQ zzFas}EXnY;Yr)e{>bOzgV-trP+5G-@oVKxi6Aqm(Y2EMN#lBOAeY<{^4FQu={!S%# zaYd308)YZoh*J{NonB0lkvwaZ*5>@QY}6Cjm2x{j^?U_pajBHS*!d;iE_=QdqxF*= zA5sQ%lP<6*UfsN@vDbj*m)s_=vo%pheeB4QdWa1@2QC6}-}*hq=8sY8!R@MABbbO} z%jKB@K#R)5n0)!B>dUwRs`|x#nf27t_ODAB639+*-Sf3DxMnqSmRS8hZm2ImY(3|5 z<@ZFv!tJXLhMbxk`NIHm zS~pTQOat8ve-zy1n)iO-j__(%f6eKlnSsdB@y@5^X%0-rk@-k1FuHr>2z4}xywE>U z9l1iAu&p1r|Nb2p2Ol5Z)A0`q3=j=q+BE>8`gi?xr;Db*bm^YcElh*Ta8oQArGfmm zJy1Q zot4HPQJju-_jK?;PQX(jXer!ZfTu-3+Bw?lYkm3l^FekfkX2cla^B#p?7?~WMvuF| zjcX6#;<%gR4h&bnLUw9n0@WZ>ZY1{um_N*?mBx{*XW7zUkpx#S#3-gbGkIS`LbnJd za44b)&rySqf>7O#k`k_nSxKzgOcG|?pwUJoeEN8_^bxa`#2_`=@R}X<(Weg&WKZrRwlEV&y$4qAIJ8pc?xFx4AQi&mv0X_a_r!~Q3aR# zz-R$!etwgX8Jzfcr3@@?c56B)B04tOoA!&S)sX`S_l+oMq_+qRMfb-IBu#&o;yz89 z-WHEYFvODr2q*t2?v#v#r|%X#eHR_)l!EpnHGZzErw*L`hIXbK)LX1TzB$h7vlnR4 z$BMajF=6aoPR&o+T8j0|ti1XQrUg#=2^UbW`@=VBqwXd|(;QDL@pD)K)$iOr;-ye{ zjLMwc;G9~TPpuM!PJN5I+c=%w?&lSfhI7nStvb$CJO%rO=v^MwTF&7 z5IL@N)VR#2xS8CMapPjt8K4aA2QV`b#!XCWK{21G8RVMEy$?FMJ7yxq{<9bQ=>yutTsN3)q?l#q`gPuoThD(iYp#M68}71 z#;O`Od6;CZs{L41J_u3*t6Wq&gQ`EkDta5_CKtiwn54bwjT-2cTs__{1vN zNB{p&4=KwBu=#nNwduzoR@aL-i>}@yK@ni7kN~6?rQDP8Y;}tpU#oVDmlBcZAuVEgabb0 z#*EWqClgtvvao55=S&tedpsA@nE=71f4$SA;7oAI{}<_|%5ewxhNZk6BI*iN%=P#Kxw?V|T+edF*&Qj=L{?9`l`K+dpyHWS zKGv^01gjsYbUCX#C~o{te%nvcfRKHD^t6bHFpwby9rZtt_@9UUQT{4|ts{x_a|P=~ zE~s0w1ZHPv>n&wtZO;+wWgM!NIXd!`!I~`lxoEGC$Oh#&7cP$J6(B9=v<%`>l1913`a0ww77r;a ze+gTNsY+02sbz9=>*ESoINTH^VZ7I^%I;g7VQ^W}UDwfzZZnoqiv4-DZ+`J~DD zC^7F+#48{`1x@zNu2?N+U4;B9Hqq>ELd1u$IgMpoJG+11U**StGtNe=&9dGfrQfan z)>$HsVIIdjuE^Ph6Aa8$Xt&34l&4xEQrd2LqHCepyocgw8LJ`*CYfGmBj=-c2o@VZH6trjrFU9D8WK8a{17RA{CY%(jC*X# zWG*V^KJ6@aS8S@PdcX%}SsfswuQDUujhlA)${A_*@8g-)gSD?rHk2->z6%{OtRV%s z&2ZUpFT&-+t$>>kw+t>BE(Oj6Hx+IUTn=0b+*-Kxa2w%Z0$_S29FBLUkA*YB#lywG z@o?dAQE*B)EgT0I42Sw-We~qU_7IynjbIe8_$`%NKN3rmh&8icoe1mqVyTJ#s-Gs- z4@F1~;8z__tp5;8$J1YR9I?9Zl*SV4c~L!%SpRarbS#0=qk0Un{!J{^(O*o!tbY|t zpQOL)(FBq+rP1_PJ&IU6#L_7Gs~$nDABd$9^j95DFuIh6(qBkDSx<|lI3hePs)rMZ z*kHpJzv>`jJt<;EgKskzoqzkSyV&v>Nm9Nx{b8z_(j!q|4yrpUsPT98m&5h=?K072FSu`?b-aK z5Q@HF0;Y;11^l)L5?#m8cT*B$eOD~SicNQFD6j;9k=HR%(jAv@$XbIx=98%5F^k_4 zA;sYeuXIjM=_!iR6S@|R>J8FUov5Bftj!b|V55|((j_{0OQNbYi4Fvb4g`q~hErr% z|Bplm<0&$%Qzbh1qeNAIl&EUEL{-}*s!EmUAXTD+6p0Q}Bs!QZ(ZOVi4xW+d;2D_? z^zZz3P&z`Q3%!fbQpzN%DwA?6m2xW;b^m!)itmsWG}_d_deQ3KEFqyzT=~P zWWI!(`4VpCNw}FO;pVoF_L18@+DC5rDAc!nw2$=oXdmhE(LVAmmf(8VXZuSHvfOsAQ(w6|rxLUf#H z&3!D|=c4UTaGNV*HNhQ;1p=4Q(N^lfzitVT&RXyLZ(1;Ej~<=A1z>uXvMu`v`h%K>Gu1qKYOf% zO``Rz9Mt|a(UpqUn-?F=;os%t8?U#=65W4@)>yhUdZ-G&_J9AV{VAebCt5#wEd4LV z7w<_a+QB`4C0a*3mVP-VEuTpdFtX^1P{3mlE=7cQr3jf2R{ptYeS+>lKLkN8BK-D| zAllc%+lKfcrB^yAfDaDRYmpBsE4mpXXOt4ElZnpk!=R}XupJ~926PnoGId1vtY~x5 zMM@2uiE%dN0nvf(7yEF?g5OM3ZjrAY1IHp?CiuZmh6sThMdv2tT@S`NU5*dk7{7E> z`I!$~9>3OtFQg($5jNXbiqT+;Yj2UQQ#=v4GW#9kL~3CGFU4y{W%gouC9@UwwwJ*D)DPr(wt zBg%DK#I*wP8$Hht1{18u@)xvKCAoJprlhomdqZ6}#HJf!{4w+Fp*XJV;<^96er5la z{KkD}=rKVGd+T#?W@t}RaHD^mk^>Vj_W1ofP9o$UD+TxT>=VQg90l}zN9TO^S+%4T zk-~aqTjg>roUcFZU7gYC_r}G2kht)WdM7(kk=ZG7id22JE~Ry*BIVqJGjkjrma535 zP+4tb&R3r4L%tU;Hqgw(BLhWq3z>Vu9&yr3)OJ zkzfyZVX?;WDJcrXNs#9gsKt`%l6IB5v#l!U;sr%_|CEUydM6Ia93+DG@)tcOvh&*&Y-ZO;4V33Bu{9plgu+)Wbm z$?5gAcJrw|+7|&E00T&d(*z>ut!8O`BbbFyA%9aiR545qJtxOqbgye$t&p-!N(Y5{wFA;U2 za@Fa2G-%U!oZ94L8IB4K`t@zFg+y_mM&|yHm~DvMtnzsKvJLjJttV?eb`2H9t0evj|Jlw*{XU=U zM}qEseN>Rp`jS|a5*M&VAD3d-Pa6+q>Q+#+CF&`AUitZGb8}y!e)x{CL^h-2I2V?f zo`Dd}xmBO^dKgM%O&CX};Lzo^I9-!46!& zcEhFn*<)(Q6l$5G(&09JXk-f2$yIPM7!(>5<{moVmMp;BO?{?Nt8i%9^iYLG(ifan z6jUS>wZT?=3(^?c#O(2l$0LiDz#Z2c6lbW}_)KcA&V?PvNho`XhYXbs;~mQ(42U{X zK?1?s`#M`a?83Q!yLRP2J8vEEmBQvR#iSlxMiTXfFrw@|>mSzPgBISyo*uu)Zp=&R z_k1X=^^rd!0{?eEY#G|XlSAfRYZ#gi$RR5`xtK>==?#A?m9tRmq5Wx*Ommfq5N)JW zi}{cFQ6A>5#zQpj`nQR&xrqpMdx&tXo(Mc#PxlYgdp`eRI@bt&2`fqH@nIXP36~Ns z54TD;CEJ!qKp-;RNzN!PvorVFmPdN_5bF$a&++o4Iog?HV1dZi8eUFKQrcRBTfY_u zl;t7K&iwOkGH1AXyO=!}qH;6GWT$P(n3ll6BsjRK5tub$qc?Zr^PWkFW58Zz~pmJ&4gw*?`8d7s(N1V&+ zYifl;%{|ZO{r+K##9dFl=O_-=2PzzatVJJ!R&yAGx9j!Av=_i6mG<*NlT;Kpz*Ab2 z&!%T;b~Uikr%&&yIt58SZCiFgm6uBL!KP8Q$JdrEse}czC|2Ik8NL_IwmzFOBkv>Z zFxxURJhnb_Cc&z}VC%!GK<e|%eg;_GF;RTx_L|DK( z6v63=P`BcVHU(@MQzI-yiU4CZ5Wvi-=bMj*3mts-7^XcHSwe4z=98`%jwFEMF%Uc( z`_l4!xlWS1f}}0P3%htg)A7fRg%PDdnRvr0A})p*c8JY5`5{%SB68% z-IBooP(TUmCb`H1n#GDR3Z?utiOG>C6iRg{2ub64OUykU<($RmRS;LRXlU(+Ab>*= z(yR!!DMD!-YeO1qdG~mR$QEZ%$Njwfea_Osdm?dWo1*FOy!l|iYnZQTn6J(KAD#npdrvNgesn-HtA$;xHOS;4 zD?*la4DwmCA|US-<%r_Um;0%?-}Rb>D^=!c1dGWv$_#E)$K>@_OFWw}q~=Xwo1H4p z??qfAc4@rp_CV8j18wfV8ybiDjrngPN7aZdmgGxyFJJc=$E??skAcuEER=UbR!Y&m zSDeO{K22<=!~;eahV`0R#Tu5ig|n8UA*hYzs3qvAwVwCcwU@N6zYaA06%pKq-F|@DSQchlQKz~hI8xx6) z^aae8rUp9Si(?jjhnm~z=F*-Jhn9xv2YC(Tl4V{)<&q^{qtDi~X_d`dm0PREbc+Uh z*P_&(18uGYhH`&HAWlulAsx0!9ocMEO`0Q{wq8vLHVyHt z)h>+IE}F3T^SBA^gv5Ow_uWKTV8e%8h%M>aoMroRk}P?Wer772NTx`$$&lEvVAs@v zrl~0Dl-VYigs+Jch;GXj$XWAaXjABaNz4&+5Y?jX4`B=>gjELPozA7>zm<4vf^=qN zR3zLJBfHeLF`CM3zh2}Wv5XyF-7D7ZMONhj_Ibd%wct(}8;q5a6lhxoBX@MpF?mg} ze=_YpX5Ju!v%4@9cV0Gqfmz6L!+Jk5NXn+jz4xGNsUYpJ0-Un7GD-3P#vHW!8#0aR zB!wSH=pX-#$2F0mmli?g20+vWIGnKg4pS%JR@t^%WP+hIeOioLlv+Gfnghf`KB{;> z^em7U*&L{(-@omDk?vH~X)*2(oj*d@hGh)V^FyWsjJ)a<{BuJ|;PFphu zG0T~v~f~(-l>T26((x+_|-&cP| zgX03QAB$(Iv^3Pp)=X;{9yffS{0>`QXn4pn00J5pJrQ#vz^%02nXZMC`u`x@9a$%ez|fbeZy%y*f{<8@Y$o z-KBZSFvY>HP`N%uVN8t;Q&35y^3>7+k>CPrTAcReh8OUJDf6UjLy%k-UD*_33XBXE zR8btuDVkHXSZ-5T;&4gpJ6Cn@c7lUS8N~)r1?w8ENnVAbIr0|y)SrtRZ&NgqwSd`+ z{RE0b=!8imDxEC5ck|#LNGdDgp2eBFvaxr15(!}@lSG!_y{IT8gdqKT&^R|2`X~&v zgH93hHu|Kq>xbzIq9FZZzxWm6^uP&lUm@-#I03@m|G+bf;>$`3hC^B_KwqTd*wmu9 zSK~_K{xI`^VZRUex9szAM?CmhZN|@Q-Ftmpg=eo1$CUB35$r=YMkNof5*)NaI#HeQ z53wNPv!WTp@oAAF-yA&mtk@2L$RY1vMHs1qZ?Fl?gPxBXr743<>r#y*6_tlZfo%35ZFF_%5#P8Bo`~@zKwhzf@JO< zT8;!t%G|lT#o{!)r>f>kYGA8Ws}kof>MVFuObtbFZV|!nBK3t=#JS(y&XM<7V7K_6 zxP?&4VeSqwK_a}xin-hU=fA4Cf1)L)suH$|xzZJM#R`-dqt2J1mGu|qqfHq>nuk;R zIe#8WYPGm2T6#)jrgivtSQ1+tJQgMxFZ>@sd!V_wf1#=}i&P7{pP&1>uXs{qBJ> zDs%m#@h=XB+aHa8ZZN#&(fA)o;WlHS459>g`(WHdkLKYW3_tZ~9!CblKYBEL-(dLl zN5lU-7=G{3{OhD}n~~n+GKiNq{c&+Y1Fi>t5WaILT;9QXC0-hQ3Ao=-cL@Z;?Ox_M4$^BYyPlRq30}NXdaRQ3}J${;-h`h2gv(ZD=#ndyog? zt@MXQKNMEz4~uyy>;-?==!e2^-Y@0%B*F&qH_spT)I(uE^@maV8!UIGKTP*fSO(}E zMs@=qqUnU`5OGKeGx)?7I-8M+9ra5{rQu^d{c^ZO(`m_&rN~Y;_aW?z0umK|n9_bi z!!x??KNfB^N-(tGZbLoA>DP3QHCPYb(6=#<<2&YFY)W!<&$;onFnV=&LtOPA&OuqT z%HCL`t$Z^ThKdtzp2GwmGK|;H#YLrRO{vg*G{xa+Z&|&Dw$B;t!?q|4eWFyJj-+im zS5ib$l*QrvJbtkZLPIAsXFKo}4GWeYIHxWsSA*Jt0LtJB8%G}U%OmG?| zWyqH3&CePmQdImGVa6HRW<)kMg{3T5^a}k-^Suc+jAuu#sV5A}4{}$pGTjQxWXRn_ zmFadE@t5C`%lAkO`>tNe-@@D7L?wS4PrnTG3yNv%M3oxrL>0E|=H$QVJ)<_mp63GS zarum>^<`TX#_KMV+K(@c%wc^?G4x-Ftuu|8~-s(8$Xi1kUU3@`_{VN&jU z!IM`EqaU^;tx~Nq!+5(kc7>)`F&p053j`s2M>4*u$XIGltfZuxBn$cLtQ%kv8Fh&a zS7Ml*7hJ4bA3??l`ID`@Gu)Z$wX0^WCVGL?xejCo*&|4z;C$1%2l*izXOfkS6D*c$ z@{C}zTgxTe%18_-8!AqL;VJRwjWav#M3Hl^!s#GRzlP+a(m=WgK11mm8*ct^hAu0WY55Z6wny{c0kjZqH%WJyY zM|52TCGeY=ygJqYLJ2{Gl&~RU%YxXenh{sSHCJ_`dj{!Y#8su{YRKrG!Z0!+sc-?A zut0Ma6Ji1YQ1IxU$Xz0u((;#x|C^?ac)Te=ga4u}k0gz_s@7bUWbX$nJXl-JRT!rk z1cKH(jl?FY(3lXcowcc~xmPgd&vHz$Pf5*W$*dZneAZS7tOsQjDPhdof9nDQqV3Rm zMSYMyXmf>L)`A#nKy46I9rBE#p9o%kLzyTy3pud)mh>8wF~V#-u=#2tMGaa55&;sw zF|D=yI;13tC(`c=FniW9qU!=$0b zAZpxe6MuQxKPwX3p2LkX%>g8O&&B9~Ytj0=Ed!8}Ac+A?*_gjKAAd9Q)BXvy(e?^= z+blBKcn24zOT6E&6T6emgo%?{8!n1kFIKz>jpT~MZWL_K3zW8FDDHqa8c7ebuS}U- zb7yoVNK)&?ce z)iKIFhe7Q6tSGKxZ*vf-INdylwii4jGgY+2xD2 zM-4c-zCGWm3lbTW1suTlZrM%N##9bP$Uq853VD`Dyha5e{$yrsU54Yf+ziYTmEOQLHU6m5az;EpFM ze<@jj0w#9`)#BtUx;}4?@AUxnU8zA)1|5;lC}D5wzBDRJ_2T&z63(RT5ND9Dr8_^G zm5w`la1Yto;_y;jgBqbeU>s)qy=I(NgL^s@#Hr_V-zyF(y6}uITbZ|ZK*l4|{f4C} zaU3rtZC3+MDRHorIIuy34daK?t7-bNQhFUR>1}|AKF|A~ST;-kHvh9reiqtHiSCJN z8E%XLw*@JjH|1j!ga1z8`FwrbQ~x52m%<>={KW|kk5NqTLLP}OT5*&^lv4N@T!Ygz zy2r#fnWiTUmhsTHYWl63lgFK7Zcc;#De;K6yZGO#cwN45TR;&c*Og;TvtT@S?i3by zs}?Xz^ug;;V9rk(pq!5Lb`^q!mv; z!Iyp`4gw+95IH@Cdj;x2StsS4l3%LF z*1>wPK}pAc{YW)t3#8D+Q`}eQ?wa;!<`+r<{@W~2w&R%}!=KqR1b=jr3_}{>7uZb6 zHh!~v$|QcQtzsw~njTOn+X`F)qquW&Fn(ns7Y61sQL#gj=+yC+eC!%p?g^GnUi~Rh zlGI;JW43Yu@md%d0L4}4(Pk(oajVIaZ?Xr+2XG30>sFd3&MQ%$l!gnqki<|$wtSnD z$OWTR$f#d1Gu$Xapus}LR@_zMmhb3T;C&rBlr4(9h>=vCNJscyVMiNCnPHbIVg6Yw)q2J zMMf!Fq=f@VG^KZ$65E{4UNSZ$XP(XJ<`*7$qM}}ZTr8WSN<8jcIE9(Uk_jQ$4CEB* z*N_bAuu(boww!xH$A^}^UW;%Cmxyv$9Exgr{HKuJ2nSD=r89q-@%-?^^=9{_3l^tfmt<@-^FY z*( zB>)YVL!3Exyc29WFYvMZBPtdIeOfk&i`^eU(XgPM=HD`mH+Y5IE+JjQgCWFwg5u$% zgohIp4;cPWPGO#x@GzDyO(6^Svg&8B3nyHvgJNt}GYfq+E_5>VXIXwckK+g6>S^F3 z$a2(6f&>8wh!V&GSI!b1UX!;v2en5?k_%qGvD(zf=bY_z9_w;;&^q>*?wtLK){(}^ za9ukZvE*pb)P>J-*Nz6Xb@-MXmEgwm@2J=LY?t#-ZO}07>FGWDi4BrL7x#uONeVi$ zFe&ijUJZ;`E=dAj8iGI%UK~a&ai2}{3bSkrlR_76)zbX+uB=4$#6V0zSQ0dzQy_0n zF;P)@1GLI1xd?s+?Ii;3B6MuvEtU5wIaV{c{* ziN{HzmlkMuQT4vF5^=(dHV6>-&T7*)JR%CyBsxn9>CCy)c-dycK`Y`oTo?TyT%;hJ z1qhS6gas7uot?dn3v8W9{KCCKFv3=rqyll^B?o98(8XMu9>iuO;SzX z&*H`OXjK~JsvO3_rv>*eW*uhnA^_+>iZL`$2C9eLOVcIN`v`P5d4GuD@S?1AC$lY) zO$QU%>zx=dEeHqJ@wlDGi@FKU&ad!ea z^|qE_7n4*Mw?^)64ijd1b6)Urky%sNLMO@J?*+|1A1I`IvHIXfWhF9Ppfkx!Mhaw% z3re1XP%Y?rywJg}Um{eDcn?vk#B&=|uPa;For*jIWudsrBBxh~{E*41%9q&@ZTBjP zHEni5CyoX-OEkEr%VO#kYTM|MUd|m;oDKapc7HgS$DXoDL9zR_j?-WsrD%y^;u|UccJ7gYuneFWG z3Ol+4@RwT3E1dDRo?1Tka9Blc(A2Wjz}UkYaF&W%;Qfq(Obg*_y{4(WaJq}4p@X8q z2{bJ8^U%{W50%gWegQmikKw_&i{fGTBY4;?;UO*rDn5_$&_tPsrhtcTn?iZ$n1^_1 zphX%@1hf>m6?o`ko+75PI;U!ohe|_?=_a4!?XCJ#R~48?eMqP2j`vfWsoqb;7mq|N zsSkQ~;S}!T5z70Q)Jt%;D9+Y9$uiZ=8252Z|kcPlKWEw&U+CfV@7pMoF3q!F?Lv$SeQlcTm z$#BuMde^lhVKOBJUOS?ZC<%QAx7|KOM|3Ry_`z6A=?G)-kLc*IG#1y|8iEccsSa+9 z+y*{4)0?xDa=cX5?Icc*#0LYw2f_Wgk(3VxRDlnoBY+QbgM5&qd=SLe3AwOf@rUVE z9}$7tD5kFD0ug8recVsaU8o!S4qZR0dwI5p2z1)@_;(ZHS{{n;rSCXz^!oFs?^SRm zD4Ui??a5I$m>;z(colBYPtPi;qp;HWRIZM?LB9aohKsbm>79Ofh^23OiP$IAiPnXt zp-&1YeIJBZ3ip>iSPu$24X5x^xam8Empb}R;ijPTZeP9Zf_3X339#`TM_p8%%Hl@V@vo5$tfg;5y*24=u#QWx!4S zKSapK^AOxUxcCIbgR4v?Ld+y0tblt1?kwECXNXV(3xA+vA$T$olHu~xIK+xsVN447Ur;3)c@IR%~=W=Pq@xy zM96so<-x7^1>(Xf^X2>(;n`7u_=U&^t`07K1>%{B@DI57B01i-LIj$QhXVx!%MW@T z;Nahr+2^kv-U81SUyo+16_g6Ba(`Wl8{X>{8tGhoMjl{E4V0@ z5t8AG;Vf_`;7%#<4bG@UINT1n>sq`AFv32#MS+a)4>)fqBYXt6EDUkN8KFeS2)o8G zf)h_Ko{PpJ4ct{YVH_h=!WoVK4}0$)7gd%2kKcReCvepnKt#Ztdj%cQwqY~{v-QqM zh(hnh5fRPa%TR;l>aH2B*4j3Vr6bbrI9dYP`!h2&NhBMRTZppFj7DU*i)5{p6`Hix zT8)GSh}`e<+!?F)d*AQJ_xs=X@qK*X=yRUup5Nzne%y1q5VZ$t1Xah!P(?apj zXu)+GEfg7$b{6ttM4Z4S>_V)}L7a2pz5wRiY2p5PG};y|7_w>MJdh3ho+9L>6!BW% z4m1M$a2+m2zE;x0HUR4*LL+b%NMA(@`G9^k+yKoQlnFSn8R&m*7U!AtN9-F^Bn za2;(L<^b|=e;>*KXlO_~g(qNt3GDd{eh^3CABc}(gu%;@A^hmR zf~N%iV?1WJ%gx^Yq0wcaRS}&tN9*s zKwMV<9nvvCj%$^$AA_6#r--}($C0lpiV;Q;<{aETh*P6xgcpD(Vi@5vV2EXe4S*(& z5sFy20UO3K!g-*3JR@Xl7-4NZ{3S9%*A&DB2)7__K;cwINah%!jfbCUjKHQdf_(-f zr0d}hs52R%7NBM^!dc+ZY{UWRZiSyLMkof(18a?pFn12zfs?=$Vje`eYmATvWCO*( z6Tms3^g9N!V1zzk=zHX22zdqq06UDhfqb9^NE<;u?v@GZzXau%dVFy%|%Y-2y_dc1h50Kw469T|On@lLJ zkO@bCAzRaNi~qx`4~SN8X(>p=USB0So~Pp91~}GqAxW6I{8gpnq8=tUU}_0AYe7z)_iy*baYy z{uttV19=CMgEAo-7&?XU;C&(ZdrKxi0yY4LfRn%#Kz$DWfPA3%L&Vbu zS$-lD*iYdXD8jY;0%Y@d4gehQlz+jAApkn1hEf5|j7mCNr zh3*M*p-U?l)CuqhqyvM%zC^jePLvB(fD;G+8y3MHI0tA1xo|&FW|9j-z*@6hI0=jb zrHkdl5g-ht<;sN?VD4RVp%5qos(?elC17hF!Y%;=ZNQXdz zz#*UyV1FSOvVjc%RRl9o2ZVvzvAFS2|WJc0mL7gDZg%?o|pFti7 z;{kO4KpKGI3*;S4T}B%L4gf8{S>Q4-3LJtT^*>RkU!t9W^RFNuU!hHY12a$s902+N zeHdj1@~b( zP*arVDCR`qD*;+iD51ga&$JK&zVa7ZP=c$D(1Hpq5P#qRu4BOz{KbLwU=}bAB16RI*IWG7tcpSJ4{wB#ODmO?AGg;`vc#Re^!ByZY@DcFC;KbKy!32NV z9kgHuCm*MU-@<;hoffu$YvH~X+znm~cS9R3K zAp^YjaYmR9ZamEhGr(OAM$m&d4KTt?aQ=2i$OO-Rf)Qqc8^N=|2cBevTfwd!jPNt? z{W}@qHgN5;n1_Hj)G$I8IJbcjjNlgV9PnJYYrw)TM$m!>!SUeQ=NTaZd>r8t!Mfdy zFcG|U4S2MMj7NhheV-Z>wVj6*&C`$RC_o&j>N#N^mT=3(SLcPWVTCmCl1daMk;WFA?o7 z8})$eAul7`3GO+M_)ve@IglH!sRfW1coTRY>R)pQBg_Y{1#93>zYy`^dfT0h@Jq1% z=cr$B7g!HYT!eBWd?9!$xKTiT!oJ7^x#9XGI29})T^8|eGDA+_9J+)`HZjv+y|Zr z_p?h8FZjqZ$PGMNfObi)J&f>ka9bhTC)jg0v*42X4U_4u4y5P3mEE zid-P=pcYKx*)SF3DYyrmphLbV%7uyGE4*At0w0+q7bb(ZCCh~ra53yt!N(`#UIMO7 zkqaESCsi)+;1&*JF!FIgCl}1%FnBRI7xv-la)G8$$1@|`l_?h}8QM-37!H9uBYe&n z;nFz~ZoC7GKh3NNyP{0pj%x<8nHS;vXGh#;&j%yEtxctfdNhyfRupnkyTe<>GY!Bt34fjrfLX&v(RCgK5i1ra~E7}pB02CM`h z??8ND>Mw`~TnLUO_TU(B`Wtc~4tzhD1$)5bz~=&TVLZ656ZcJUI^v%Ic7ZkEWVmai z93SOL;8FNb2D2f|1Hj!U<-#-l3mI;_10lA&noE3l-A% zk$8tfSOkCJ9ECs%(wD6e#v|Wn5pDvQO-20ZzXtGq;3BXLya}uTyTCEv7H};1GI$)h zp05zJ&eX2sxf!BhkfwzIv!Ngn5oCQ7r zo&yepZwDJVg^&$C3C;lzffs;tdB_dC)u<56U>B|zgS)`F;LG5xrq2VM&90WSxK!4|L~T_LOl7lTW{wcu6YL*P>I74T~C>=j_O9`z0`1jm7E!Q}oF0Mp5k|4f7j?*q%gXTfst6>#zP>x(wr7+I9K21f(y;rm$O}SWy1A2ht8xii;u-iln0pJpl zz8Uk)t#Aj@AHkX+;CdEoT|gf&`vBa50MHGb2NphubyJ`ZIPxD@K2QcY0SsUN`#yb);yPMbl zmCuc%grDNSy8nOe`s^Ec5A*+H{Ipq+1L)Gw2ByN2@GViE66Lfgr$#v?%9EpvVL}Qw zDauJvo)~2eGm?8kl;fkUjWXJu(<92;eF-zM(3?MbYPGP$o4 zdoph#jN7Edm|9BAL>bd7=^BI^0n~g_ls(EqlyyTx|3OVT_vlZloFoH{r;1cV=mtju?Gz2CEC5+(ID3}xkCkK+?6zb3p zvV#S10IUP|fk|+399cBD7!58)gNr2i|Ni~21pZe7c+T-$TlCfqNxwC|l@91|&ccjJ zEqz_|P}IiokN>2-T2{*W;GS=jWz&-r=}-Tg;1R`}&^7Daxhr-CH-BXYi3|Co3nmhSx5Qq98|)HlTL zrs}_t*l}vz5|sYda42ea#USvE}JyEZno<0^NrtaxD9$0 z90?5eTqd26TmK=J-R~=_Ftz+vTec-ow$9U2p^0wb9 z$7e#1#dFIb!S4CMNgYO3Vd@a+;t!Cp}(8M@F#HOyUwSxC9Yso!Tkv{tKdC`fnKSfXJ3R|`!!|KcA0 z(fyl3Q`Wz@fBmETSB0jTH*>@EUny*(o0)#a-JT!LQt9s!@oA;4OT>BO8C@cjar@sA zZPI`L`=afAF+=*_|DNc7Pqe*t+2ag%=iTEFH zqxw&hU%&L5A^rBBAU3uW;$%ez`GI0MwTOGm$b`budNzW*V9-bC@iE0Y-#M>$2} zz>$84qnyM+Y@}a*NSw^rLecNUGCnJ;{&Ea*bgGwB##d8fS`IF5Dxbjdkfe_i9kfLM ztbYwfk^Ny5u8ICw?T82+3t1!3h?+w$We_l#N%=VGj8-z0JSehRtc87O`M09>TQQl2 zZN36OOSDYh&&jBCP|GM6QratU%U8g*Gn-iD&8IYpfszNu^_=l6za$o{#JMSY5_u$W zJcG{>aP@jT163qA_C?Pia6D0e11qJT(xnGVd@((}p5^a}yH{qtI+iW_A#ehNBWiK= zRsyqQ3YB#TZU~&f zCi4!8AIncO89m=~--ged-0WBS32e()3IJ! zdwtQ_-PadYV%5LpWE=RU=G%8=2KMJ9T-30-Uavj(PJtXV?AgI z*5(SZPWB6|A+5l=+A4IUd+s~h9{a8x=}YJ4Q_`AAf%DAUJK$CkO>r!TEt@02_Av-{Lk0bk+!=Z>#LiZ7-3 zP%@5N-R<1(zN(iavUqQ=c=%oM#(1`y-H5nwD`m&?E7sr!>pd&-E6TXP5_f(@1y1H? zyZIFxa5g{t9KT{S_YOkwE4J$8`gjuX6g>T2`h9|X8|E76*M(F2`4!JdzX!OtVD?GB zja(-9E#{t{Ewf;bL5;T(jv}yMjFqMcj>6rHq;ycIsVn~D}%r4RE{%L#%@X$u=w@2d|6}^{l#uffCu16zrZ5Ioo zaXIfp8^9W!Ax$FL4#k9i5v-PjnDcSLLlW&Ya zdazl=c7H5GL7cF1Cbzxrdn=LcE_zSbH%87g(eW(-hZbKu2Y4;ia1#N$ai|ch&XZG( z2kmVx&&wY78fFruJgGnX;*{Cv6@-$Oy%LQ ziodL#&U+e}+7GL5 zg|H*77Dw=sZ+9W<8Kk)I;NVLkumhF6I*W~+Z`5+U*sRtwb!L=u2ij4yIx+{?dO#Fi zIJ2LGO_svq<3ByZ4jx*MqvEO)#fDd*RmQ1y@eX%vR^~B$8h{CGT~o_3ms9UL=J`o` zQvXZZb0TTWL|<28H1WJ2(HtR5SnbbNU_x4xu3E>aIcf`)w z6CTqY3*gAex)^6WGJ1I@pSGG%*DmSCvP$wDH4kpIY)$dpwgL61>RJ~*w>tNy> zT|vjnN7q5e;&E;qqix>B8ibK07x_FNTH&mrm#2)q3# zIcLBtQL3|b8CB8tc{AHVXAD7QR9b3{8^=*VtNWYjJxw@%Q-=(^UiSr$5BYgM_h#Mv zG>@K_4beaQVTh6O$z-UWf;o~OSwU_A zzjI#~B53#(#tUFxHO>!c4Qhmwy8bZkQZVAKH6nW75D$MZ>Kr<^hYDe+uRnDP>bpbv zxS&tHBN^$Cnu!{jkXjb?AS-ZI9PO6k#Bl*2 zbY==_OlR>GM?aI=z&tP7h{MF;cBrm#qL?KY z$C~NZpcWRk^LWgI5ykH(-G`bNl;Sc*;tCn z?_t#>=RUMPoPJRc$wbO_0cXW;Y7H7fLEX$?&Y7hbR$nc*YBpQ7{;=2zmECc0?uUlY zpn&G!?|_}AX9=ut8?}&^{zhrK#)~$_DtY|ni@BWffND9<1B^l)Grl;dV9xFH3xc0y*AZ-SIO*u{W2Tdu$#T{RqPJ3fJ~*HYI=EdEVVhGa%~H2 z`s?;oXEWQfHL#_lKbmP>O$dFV#v39M-ct9~X8N`eH)T`3p_z7@CfNFJ=Fu12@T0uV z*6|kWg#Hh1%6dZvRH91*F{IECBH1Q6OKrq(?C83dT5rd2d{psNY~J@o?Rm5={I5pp zBI8BKWU5phwhyHAYSs@gdh`JRJkLwtln>?w?6)kl?p3Dq8`>At^`95xDzdJLff8-G zHOa8jULMqC=Apl2&LHzMynQ@w{-KNAWVxd=Wv2W-+U9kR1ANu z?U`ZH{Y=MO6T*{sk zpKJTzej)56%I#p(O(S-fgEOy2E@oc9Wtn6@Gl=6LieQ|sGjbZyn>q$e6? zn8I^#WIz=Pm3<+ctF>?mx^!LTRWlb)rc-@YITtKkqLG`(TPH!30#tqnAGlhC$yQO7 zk(-23X=yMVuKHo!3P=57IS4wE4FcS?sdFFzYSFa!U;QTgDsQ5VrkLytX4811DKHB3LNTF$1m+2@0qyXG0Zv1X z6v;9TT`(-tLEua?5GvZToSZ81@>t(>$x~6*E2IXcIRFubG{>}$*gq9C`TTZxeIH^ znO2xAk*?t+mkcW;(%0C-U?}H$BB+P4Urj z4qA4Rjvb(5eAZNlRqvx22TfnJrVUu9_^h`K(CUk{s+U%VXhkb6cUW~kn%eO;l%*uA zE)#V>J{8OpJx+sT3FT1HK9$nG17_NxV(d@Cz&KPg`x7w894fheI}CD%N?~`vpm1=B zQb46orE+iyl3C?bsU2LrWLEoBF%Hx=i9E)qiglimjIlmdoP*Oy<~W~tV1=< zry5Ttl}pAsFGzOdeX0r0pk$oj<0h8vG+`LBV+_JbveRVWp(A6+I#ZcVhatnT%2ZUW z!!V*-ViFeX%+_=>muRt0!&ryWM39ENaw~7NW}v}^=SpMIG@ZlBg>Tm)n`jS_feMus zo~La*gAvg#ja+7Qm29}jd!)k_NA7x|wHwh^q1eV&c)rC2!7PI7d74Y9vnH zIvsIFqH}YTd|Wa{M!nX|O-3tq!C%nBnJipNIV`5>TywQ96Dfm(OGP&{W5|;(&DP1T zY;950oZ{xveB2a-wnuGJT??WC&DJ#6BCSWV4_`I8ey)YKA<}8@)DBo@^nHe|rgtsW zqW7AuQ+nRjnYmkBcWBXvEu1cJLWk~%;N{#@oLCd~nvfsQ^EzRV37K*2)fJ(KqcGbc zJLGWU0LQznx41bDML|d8t;r7SM4p@G;L=@XRpFv4HaOedo4lXTXgCSwSnmWLtv!wZ~dIvYd$K3)a$$pAGjL3B8CO&Q|;=`En z!~FwA!zkt8l6=;waZZOdX}X%}%o3YbHY@J(ZrrPv{-=AjGzScE8ZtXF%%pR)OS#oq z{yX3o&pW1#*IAiU?$fX9i=`Gge0YYLQ}OCoP%(rxgXbgbS$8t$jQ`3= zW=-ZwB{m{#yO_F4w^GATq-H$cl#)ImEuIa{9A zIb`&n7sbt<6jw=$PeJW$kZ)9UVlE1e=~vi%=!kdywgm(1D%h(!b78;pnJdy`s|9(N zQx+x7W^b9uC>K+eNlBff5723o*rZkSX;z6F=DiHNe@7-BaZ$(is%GWR`SNDk_Oa;T zD0dg_wo+&Ug}e4A&n|p>e{yc&%>8v6Q@3Np2Z-k3Ypx+eo^M|aLNJ85L8wlwLrLGmE=l(PG`x|IPG z71|uRdDnw^5OK3oUrq#H1sOl3?382xNo@Hulh-cdKbwT34}Umk@5PC8Sash@?Q`my z=Nn_$R9BOIKT-8TwYaKkjLVYoEK)%7WBTgt zE#Ye;_0)Ck`ZsXxew%JOcJLUTTK{41(Q$Z+im{gsE}3^U`fd$*j3M#IkoZ3n^R$$q z23jw1x)X|A)ZqvWIRYP($eoCs{?duKalXojAB{L)@4y-q-SF}L4xI1U#=z&%Q(ihO!dv z+Y1Z(PmDyb@jA9*n%qX-3ZUXcp0te6hzrv=@@FS<+X+3-I13!B;zVk-?ahpEL}wcn zcaTj_&>rBF?P7#nS9qVcfbYrGvg(34%jU$@FEcl*QL(4hooWh8Rju!gw#C()ZMk6T zYtr?e9(`%ty=;p|?y>A`R>ajix<=oxhe8vQr>T*29iBilv!qeYrs8OEM22*uE?CaN`tamUD7O-#syhhteC zUEp-JncQZo)l9ouu0gR$tC?||W%V?wqkunH_ZJjaYI{CUVvW0Q=J^<+(RxrH&nCz5 zy1MP8Zl!Y=(S9(3_j;0V#p#)iF*W<@Vrq`Nz6|KT4tx=}KLrvZX9dOG8du=_d);{= zLaJpGo{ddZa7--lwVsgoLvML}?J4I&wN6iC;H8IHnP=MGX#Jx-r20P<3tlbog-*(G z8YY{-GM;JMrFafS;>njCFE-u4wu5FlUS+?(4DYu)@DZslV^r+UBza`X>CaNbFr3g~ z_e4_77&Ip`c?wwi&xyhF$Vb7ey&k2%O?+wdQiezp`Kx2L4V@oG4rXN>hwiQbn|yF) z%wcjUJzg~c(2m4YVRhz7YNSn?-c9y zI-i$(;(Lb|beNoB-sZ4sF@fuUL3~Q-*}1nv1)nu5@s8g4YW4{%rpYD$Shuihjn)J_ z+*mbu{^|FMo^^ZIugro{X`G`9Z>MD$ABk}*OD2kkcR|P*hs0+ZsNln7--ev5`lXN& z3-vNTegcY^(E&dlvXFv@7w{N5D#k8c|mFJQ@2Rt20$k6WGnYY#iT%i$4WEkAG8= zr+m}jbu44sEf!d3O#GRFD2Ig#cMR*UMu)53;d#SkcRIpNShud(eeft5%*ngO)xg{p_z>b?|`39r1vaK8`#gjp;jh&d3FNfy!(aU*Bq>GZi z&>|*fDsf;ZhAxQwv^?V#F)2lX=0`)ZdZdBE519`{qkmoOWZ~D3`u0Y0=>HY+x0=S? z183OF?^ZzPq}=~o@%>XH%Fo4YI%)AJ-XOEFQor)jH;162{(_OTZWasCb8Q79ra#@d zm(k089w*OFYVxwFm@;8Sl}*jqfi=*%sALQ$Ezyzo@UvsSU=b{k*AK^722a&IH?E`= zA?CIQi~4^pKJy`sd2BV7U+1Fh5?LK0(cs<8E09jof+QproQv6+ln`uU6O?zOxDIYw zDp6gls+`&CaW>N_$7~)kX;}hfL$kAOk7H1eM;=p}AoC{iJPzVUpom2*n`V0q`MG9z za`3y#KWm&G=VdBEpq}yWj5*l70xdEL>NiOyVsU@SaEK*MW1a6{&WJ?QqKT#>r>(&a z8TDdPEE`EPV=K~!kT!JCw&%t37@LS(pg4^TNxwyUUmKn@eOK9z^q_3@W`Zx5d>a); z#=nd2KT3DTA)CP>1Vh@kN5zuZvCczCJDT+n()<|p{-um~IM@H7STgd@yywv0*d*mih_$GHJ2uvR-mE~@(f*#sgCCm^xw&E-#Z(v* zVZ0s2be+=GdFm#2A5C@Qh41|AuylhW_s%ZdV=t5YY>*Lz!DZzkOnj6=cL0rL^DB0t zXfR{u$mTq%+_MF%3}UKn_)ITZn2us9VoMT z5u0eXnhs;+Mx&g~`q>eS)ok$$tyyld3U@QC!Xd{q5^Zpt+Cp-fSH1o z7Q>q=Gh!!r_%q?D1Z{hNmiEEn7++7wff7!7$PBXH~EnBu_ z&BtbLsf9By`#SY5te;yr)3B^Q;pnuN<~*`^*NQLh``{t7)y#*4RYw@*v(l@LoAYzb zZKh9SFr~4@j5zSTQck-fb9WhL6Ej6;0=pE77TNLaAKCs5-?39V$#)5=%JdHP_iDAh zB^|e#)~@jHez)cJH7x;o(gsC~Gq6srn(iceE!nt+%^3Jwmr$-vgPYzo*{eA=?z;_% zhHg(+8Z}9vI=q2nn$zQ3PVent?YmoW#{1i&B}2mpb55o!g0GmdL2^2JQOSCYMQNCA zW&BAzj%h+`FwOr*@pvW~Z%;G*F7eQ#WGDy)(=uG*f%Z@+jl5*WeWZ4TvyL{)^_aY3 z&?L{83FJ;PubMG>Mi+QVlKyMMW>4QT$=p9UOm-(>TpS#>gt9vnY#Mn9xJGOZ75hB3 zt?y*BX-(e#)uPYS*wlLSvQ%8q>hqjTX_73Ao|FBn#FROFFwGn+#@opgmrl$4JH+l~ zk!MWfi7xZWOEdOfLWw$JGrSlV#*D#YHeGnov}sFNvjtmEMm0@#O!UYgNXCs({=}tn zPhZN59V%T&*I$kM5p+F|HZv*5FvLMtNtq+fvXs{_+{3(ncvi0QM0Uj!%_e^IR)sOR zY5np_?8_>jPKI(NRnm@oNFP!l)2`pa|97pSu8^m%IZo4U&)A0auE8DSw=@XD!Zrlq5aXQ$+ehEXY>tcF{90NzN~{Wr{7`; z75B-hyD@E>-yoMn;gm1%JM>c*w4SE%#0Uil#uLR3&*;v*{UjnHcF4~Cm%8FKON*xC=#%GlKYMC=#MTZ#5=IgwrD*Y(d5lNO*6 z6?e$`ep7*%xCcAjeW5gxT{>f6xHIzP8Zs8}77FtS2?&k`n4)uo{`gt_|ve$IB0@TweVhDN8lSoMOFGM|DhY!;H%Q|%#@KQ5^ zC?zk56@L1ciX}B8d6yz{gC=hWhB<#S>SYM?f!32qxPKB!xRpfg#JxY|7$yj-Q4iNT zH6(S!t@1C%^&o_Uh)EQP*OrTV|2CTTrnhu9csVry_eive!%PxZc8aZ@7a%@#{@{lG z6=Kq(VUzwk($UK?x?;kHVeZ!0Lrwo_{#N^?Ue5Ek5XDK7^OUgfO>`66#WAVdN@9%8 zW&BGqo%*LFM$#)b`15i7WwXlv{a8|syjhv?{n(*cgvK-y15S*XMcwQG{@}7m@NzS*N3=~@n%KJF;X{Xr2lC|hKl~laQ`Hd zHB3m4p*{BtaQ`^sPG)Kux8fQCF2cO*bgXSQ`prj>1q7VZ6v-~ejYmI}0)#w)j##AO zUkG`8VC1q52Kk};kUW_KXN1QN;l@O!z!`rVJCx#kGmSiHKvvOto+N^_lw+_v4Vgz) zPRPC^#@{wpyDTzzR=+mFhtiyCJOE=E4Yi4Ju_SY>1JAi=&I4nIU%cMTpdy-LhFhS@7QC80K1753V@& zB|6(*#+=><>qbmpi_5@ zE~+$@=Q0+&X2`7weX3V=pvfcNkf#g{TVIXnva)3b#|-%oo6VF#xMnufhJ2IR%oxow z?A1N?X=AnR73jPvg3QVQ)my`h?gy`r$k5?!tf{DO5*PleSzX9JQr-X1FdOq&Y})RI zgAJY7AV}6r>jS3^*z59oJ$glls(z0xI99g@#u)!gW8MSU)||#>ln#6A#k4qo;~2gy zz+w}NsZ0shu+rje2gkBL6S)f_R{ni58cTm}8Dqo_H8bNg)5s-vUSv05$d>o7Ad6nV zvb`|Iox=+nV(GU?RvFKaWz8CCR`Js)tdu|iAEjt{lYlg)Fv)O@#;YqvF~|Ieglscip&+(Uyw%mP!sykL$1S(_;w7gcViaae7+ znK4U(JMpPr5s@`I>;H3E`|F5)Auoj{X|}3OD@gN1+r+qD$Ufj*y{G?P(gKRx%QxR_ z0qbtI0D1pDG@S>p4liFKT9=3w$%$y3iXR$hv$8{>M5CsyygYYPCE8H=bcpalG-R|(c_C{n zCb_!5-GSG6Xqu_V$m{Stsa?u#yGgsWRw@hlGUvmNyQnhzHOF0anbYLBiz&YgufKlM zF69wfVcAvIPQ-gmD1F!h@fKaPK)j_U%T4hf`?Ois|0HCUjCN=MwttekSTIkZi0oWd zPbnT$h|B*pY#I`;#MCL8RqhXB-7{zJs_w%c|t2N^=}*FE{{dpZpJLB?fQQ= zrbpsva2@nomUOrWv)&g??~BkYWH7!b%yAg_z)VTO&_gK0BhfxZ-v6sD-o~O*d-c0x zXaQ2++LQ6~AN$su|9#)``gf1jc}d^ue`w76CK_xSYvYH#p)urd^B6Zi+P5;eNd6ui z!|o8$+0c8YN>;W_V?3=h(j32J6HoKLw>BA<(fl%oy`%rvW8C{9reEk+8B?Tw<=;5Q zy(_luAy)mVl9g@4SXR;Srh~el^tH!-=xhC1!`1(1Y~#(o_B1wlx=CM)>_(0DHHS4e z<8i64`PX5zMPE}#``Z7|7|_?0|EaI>+{FL;fekw|{8qFe%)zTEQ|q_ca^E!arrRmc z`t6u+adPCnw&BUznr4wJKNyEOyEWT$dEe$V`lNyGNy$sL4VqP4IxEqsV1YS`DTFN}{>|K>IJ*kso@lv$tVxDT=Bydj* zr8ME&5s%%>XP%~eeQKnAy$MlaWA1dsLA22Qun(7JST)oEwR$`$$7-I%o>%Mz?h2<3 zJ3JI(fZb1WSoU9Yc%CKxjGi8n#fG_f?~Vx~QfRn6loVy)h0ur)T7!?{Rzcf3&>nu1hE}ZcABXXm#Hi~(Hq`2Q zy8SS_!55rkG#NIVvdT?He>-gd7_rUiKRU#{{k<=^2yNXtD(}S6aWN zpu77XqE6AL#w*~3ZZ+dj%Y3Fg9i~NY)6eh8MP7Zuc{L5#@DZ1b{(z0&xRB$OJ}%UpSFZC!Hsq~9a?OHB+u$qOzS3VcYSU)Yyf)RiT*fbFpf%5^ zoy;$n^V($NawWf9!D~~pz5H^O{&0?I=5lV|_vkBnJZPXuy`Dg{K>wxl5;cO^q&!|y z9zHbTW`SnkEYPhE(`|0k&yc592D`)2yd}A}h3}bj55^S~j}K1ACm>6~Iv*;J7~y3O zhM3B}?89blVvfnEO)xJQRnc=Ph{#^n>TD!*^0vt=QC zWHBxCSz?Uj z1P!I_UF=21=EEGVkxN)g=VWD{!FK4J<=I!4aybuXE&V<}m@Qjs%D;frms*>Z$Q@}2 z)c>510GSsB<)`uOHmhFy&cgL(ZvYK?pV@0q$;B5IHTxtrqm!W;?)NFFhDu)^ z9-?N{hu2J-5}tgz@1B=G*gmzkQt|BLmhsCMT>FK8^S8fV_~f6~9b5N#%=&p&+znaT zV=}{iI>#A$LFwkZD9sAb0}AZjd-p3((G%s~H#|9}Rr6xV=5h;E3PCfhWJ=(zt2rD( zQTMQ?=wVM~71Z0it^aPZ{<7R!w&x!rZ!KPq*B`3%_L*ois&dR$3qhe#WcUctje%(TG?c zQd+owFXw*g=E^Mj3(NEGbm#xvm%pf!Y@so7_a1tP=hkA+b9Q8VbMLkP);C_QlD${u z$U}B!2{z!R^6+2L`<0tp<^EvIZC$0L;m%uEp#-;LKMTt2}h2l-a7PR2oCw>(}8`PtnuW8WVZ7lPxP+ zW7_nHp=gWY(F(lnF|4S@n;*kN)mU;c%rO~Ol9xQZg)1t+=EfsDx6;U!lyk*yZUt|> z$7r>dTT4UM<*n8=caFa?j%BQihch2sZz)w&stWiuB^GPBg|u?CD=m6JQ?^P+UhX^~z1(?3 ziUe&iId_R4FvvBuVtX2eZTT3n0dl2b!6Uwd2Z^(??8jE#J=il*iXT^e# zM@TENaK%P$bpwnj%u0k=-@T@uG$8ICH!0$Ba#dnHA-EBivly+b*B@*6y5!9d%efT} zuDC3_%9zWP86Gy~(q-BBrR>>Nh{%|$v=d8(omk3U#9OS3*u=Pqjhe_WS9Y(=m^;Bh z9LEOtbUaiQFV z*4#-Kb5nbBry6r_=^=im^bkL37)vAjH=etJ(Ls9mZ0ovV@dP@5hJ|W2Rio9}s&9C1 z54^tuZH){N^V5|{->R@Ji@H;8un(5MV8<4Sov*3zqM-gp=OoJYrpe{X?d#S$g30IK z-bi<_K0RfB*6w=%TQ5h~)rAZ2il%?fkP?St&7SZWtvMcWiGlWW1=dFOhwon=M@-^Jx3<@OuTw3BTp zWV^{LH4ii&%ZRqfL5z`Gf zSZs_f+}4|^!09!Z?l&^s3!s=0heXEb#ImtD@h{05`8H!}(@XrpV+k)AcVKL(UKl2i zC0%&=h3}P@%}L#|YJUTHzA;hf6RQ6b#+fco_2CahXKBdu8$2~RnQk0qj5wX~IqIBv zeE2KN=AFjWIXV3NHaf>h>LwEQm9Y06684l7_79P;2(n9-!~7V8F_z;EniS?KM$a5D z)-m#8)ET66{@?;gY4EB27$Epk*o}Osk84f-#RuYHG z3d!m3aN4LSRg}DWJud;Lw47HsRl#RPXJs>VCg^%Smq;0SOembY_>#|VWGlMoVYeAY zk`@zra>IOhN^4@)kIl1!cIT}-Ev za>|GYOBkQH!^1|&Ln`qg-z9U#@7zb{{E)pRuhKcB%|V_{l7FY#P#368E?F(@!gEQx z@Scj~(J4EhTzw}IHzF;SBF#gjjZB@)nb5tgp26Uc=2ait$k$EVB{heJhI)P%?!*-J zVziuz)w9Fi8zhD$QVjPahVFzsIZ|h1(3GB2JJq$x^XtCr9?q)!2D`Yioh5q?CJcyV zY0NHpKA&yGw>~`by_7UC(!LU_Cq;{Dl;YeIiBop7L?phU?xCzFZpJq)5?{8uTedVl zN4`}3W2}t%hc<{DF}UNW@>n(34VIKjFUXM|K0m@+Uv(aXDGGK{=$ZM+@)91dw4oW<^lV0#ZX)s>dQj>U-Z7D_!;FYL zc*i+gPMTU;=AJs$-i{|7*t8#SugCWT73xo<&C}}5QW);%-yBAbFg_2y;1@_UVb~gn z-i%WV)R?F7d;;cYBn=ubT(qMU<;UL%{2?FJw|(OsL2U*{&}t2A96JSJs)xj#ZY68n zfi_Q7U&Doh_fY&YirWWi@%-9oe4k^kDm;aAH8kIo{>;7jjgx64>qC3+`GR`ejkNO( zZN20J-j0~J>b?yQ!m`&Ro~naf?0r>#pDb^9_M-GmpZ}$vss37IWAw&=j;dEj<0t!M z%{(GjezP#s$#9pD$6s{Nx{wZ;tUa}D$YG`&X4+w99A;U+qkJD*iA+q=g#b!C0yCns0JQA0pP@RA&E0da-|D*@Y) zL`o60Be5bn?K316MBC0Nwbik9hQt=5;=B-Txzx@iQ3_(2LUa@_bV78{D!z}Utykz+ zT3WSet$?)^IPZ6#;H@*i=kt62c>8HE+4sHn+H3E<_FCV)H*%}od6?J?Z=RtGrl#0o zHl@p?67>c+Z9DbeilnbI`e4B7Jmrl!%9h-OW@hu_piQ%|QE%{M(z;AxW8y$#^DDYc zktb6O8%mPrQpVSub_!4;^g>5wR<~cf^JZ@D`@lMm%CI` z>?H95s!Z=ako09qA6Ibn6o3Z!bV40QqbmsSVd`XpdtXRSglv9%4#{~z$Y<=x=;5?? z;fDL53zX2`2lX4I51F*(9nX z;U8zMoQ$(Z==yY+j8!1B6*=_6sW^!~9#KEVGs8Eh15{|w0&yi`YCA& zbhlDxBGVV$UhuPSQ>i2T*?FC`n|8g&mopDG4QROaYZQc$sJvekG}8BqN_&LSNn1`` zcfCEVpQssvvnWoCuG1Mhlv0~*;~;!TQCKbCWcNWb6qdAEfJ)I^HW_rzVD$qsP*^Jx|8$~ zWxRB+jCuYtaB9{ES68Bp6ujLFNudqsLs<{A2c;XKlduolUK>lnUYNhKQ=$m#*6XbV z8pgGV6pR~9vJf$1Qx?C1krl^(R`61HXZrAY%wHB-?{Egd>Ji=9cu>I95j+ne4P>EW zz=rHrc`M;RhFip45)^@@RFCrfvxcG!DDTAzo)@iiM#gCDJ^B(l_=0Jh^RlD82arG& z`dCLW<@uL!_60uvfW`F!tO* z+L6n4ghig)OY3qYb-B^L+!#-8tRpwdKU#l5Zyy?NDj9A133MLBXBZ#wrZwt1wh0)b z8$%=fL)r%3Y`V>X;C@m!R+cd`P}a5>(iCG>R#oOb7*zI-x9K|9i0^!iPDl(}z1xBk zQ@rI@xH5c4_yS71{uU^&i^Tu;Xro6v`ceOFeC~|2gC1!|`~S0cEcv%~%s@L@um`?~ z&zZMD4>M)H-0Rviq>;4#$UQt)gDIv43^`T4@$bLRHeYY*5^XjUbWbpkTUF|(3x z5xMK9kp|$IEK4}kKSKi1P9jGR_WIY#4MRi_lfx2OEa%A~fw4U#4m!FG4MLsfd9b5) z@+~ZzejdL^ca480uK$(MTBvzHgv2VPc!9E;=EEl&Vudw+QXT^UQq@x0r7{Od%W+3 z{|RnpfrnJ5JdOX*dQYgmhrNfIzm8b$2@YtiM|4PFy(-@0{6MSHs8#jedOH*MUf3LF zd< zR8m%=UY*F7r7L#q<+t-xZ!z%mut#UGpAN$ZeY?{Geq&GkIP)tg`kE0Ii|=H7J>P3+ zH#-f~Y`VqS14Gw}PiQ)1<&{hb zeuRW>3c#N_+R?z3RV(16#gE3hXjcfwRqft zk15a(Jo6nor4U&$hpklhPA*QZ&xZ)#d9&?tL>Pl*c468d4V!{OrK9s!D^{*nhpriA z6NaXhP20RFaE)zNsCP|}?fo%%untdGq&=l-y#iR&e(y1bae*xDX~S$>g zm505XH)?9nkv)> zREgs$Mvs&BP(aV8~>pU7aRUAr*O{%^Pa->^{{z)10OD{cYFzu{jz zZ{uvN^ChV5-!=%zO)>UI49=kTT(oPL4Nt>9N??npi6hnDJ{C&y+ml1Ltbjvnud;UbdCzaK7&$MYz~Wl4(npE60uh2rtp zrQW9AVHof)J1k3l-it4Jd3lT8lbXLCUNS8&NnupV(*9!DaWMNuZvHch`Og{(#){`B zsc=kgepFm+IxM^Pvj_gE1no*6yI^ zL@$ZfU;n~8EJ;F#p^y|-Wq+i;puK9S`GBj;KA}FZy(U^3b8TgrNuiF@8;O z==$@RfN2Xhz(^n>9lE!I@C6cxn9!6l#^3;O8pLH*y>#n4mQ@{Fcoj^ltbcEM< zH6~d{vsZnq7xSz$Pu{MC#j2}fSidCM5x~%KOG?ON3{<6D`}wsB$7qdEV?2t@K(|bU0)9Cfm#iw%{es0uzDC@=^}+Z5Bt~b_G>)1!&D-~&+{;Y zo;y{ZfBm*!|8VS@D;9I7g|=%jll)=-xaMO0VYv*$hw^3ZaA=#axh7y=i`4!Y{}Cu* zq(00OA;H8XeVlw#Z63}Q>uGniKGTG0@|-+$TVUuenN1XG5r!^n9%TuZSr-rI6)N&x zFtis~ME>=|A_}XEET1$yf3vq~(lA8P#=|n_ng> zoOT1!;lMKsafPNQ6a$a()mwJFtbKFX@FoG4E)=F^D9js%^U{ep zn++ovh2ho^%&qlG^Y=sZle}q|gwq9s3$!m@bDhC371Dh1I+iYdS>;xtCLA)=-(7wz5Te2T=CkP-Lxd0!~`BLYwtdEr0n%>oGWt1 zNy^f@OGDu3SeDiO)C~IgzNkBbpH{ED+5ZE6{A1jKneVT|brnZdh zK0b3w%-CN>0M+vrnqGaF98eDZP(+6`rin_EOP>K5w~pQs52(;1iBXz~QJ0y^MwFd)E2Ux%5n90ykIyb>S z-Ub~whQ@oX`*P_9U;FUoe{2AEoO_%O-7|cyS&{)Iu=QUY<|z(n*z~h1&C7AYWEjXE zzlBzh`3}><&FVd73Vq9tzBW}pA~Kr=<>Q9z5%c7&p+l-VZ&|&9QPw_gg4c=q$srx9 zfSeRlb-~W_-m)&mxg+A@dT+(%C$T3H=Da)%j0Ls*s;hTsL?**O2B|6ahO4e`NEnL= z2=+Nhrv&2U`j9NmaSyfKJL~KKt2H^P0Xq+0XP!0F*Ffb0}92B+Lvw3H8V4b}79oZb5e7+-- zmFG~uzR~8Cp@hnyYIn1|njoW0tlx7W6%Y*6$wSNp9ucK_`^ENy0fBa}S5zST1Xw1H zG`&+VY)^`?$5!?+j$)gap*L-h+vTS<#^0x6?2NoQ0G?(j44^8B%}zk9Oe7F1e9;Z0 zJf~CS_-L>|c9yg=Kvn0gleedm(^(%=1zpG{$Nln-snAR}v{Wa8PVPPFYYsfm)Sq%T zcyZ|29dO`r5hFhi50>yYjtjK&MSf<(ZVc*{pSN?<_IqX8d@2WDX5v9K?Y!)Md9p{# zBX}JJ0T)o-|Io%GFJpajQ8AaW^+YqRBcsU(|6pV%DV9Yycl1b0+0&@z*kT7LioUv`6pg(H+=)_g8Y8| zJLH-xP1Wv$vy{oDMN{6#dbiDEkc&6$< zj<26wcGN65s%cqB{s38i?S5cQ9#08_bU4cD3E$Mt=X3>?ZGWB+U;T&OHqx zfPo+n#;^e#1Cq_T&4}%`#oHI}O4g5u*M_)@eW2p=>YsHR)3AJ#%kJ*Yt#r7ZvWir7?RfIgMU%om`!Ee^F%41y z0EO9Cf(xXurTla`sN%UsWp~!e095eO{Ig(XH9L@)TX<` z{Cwt1oLrF_;-Amh^B06Ez?Ln9G|-3)r`-?<|7=UNM1kNq3(Suedv(jV^P6#l4 z(7C=1XbhWQzOr%izZ(Cy?c&Gv?>F9XGvkg!wo0$9xiX5GaP3;{uOMiz5@V5d?=PzS z81r)3_)*nGjI3GOAiMQZ6jmAFRYxldorRM2=@Irtm3xpT8tzcYEfIQd{`2~Ck6 zUIooaE}av)(a>20H2{W=pnWiCuX6@iTIc8GI&;PCk44y%D{u0gn#$VD6DI^`kTXhj z56J>g%>+haaz-m|=ZYbDP38$EXMm%1ei`5P3@8;ARepycv>tg`p8%O+_qOJL!NDg7 zo_45^xy`C4#%*WSlOC)~;KKmMP8JbQb70~nTjICw>K2Dna1J6f;N;1JOrZT*Re`Jv zRWjS0z%U4CPa*B>W43ABn5Ubnqg!OkrZ|wVU0fL8{ze6>K448#8-=sF>?U8 z;vx0s^6rWW(SRx@?L!CQ!uJ^*q23^tM{s34nvmawI2qc+my7660Pn(V@g2=2m^#>P z;2AvVYD2*1X@u9m5I;w=z6931m;GlhYi?qX;yd25V2|b|%!RJl+-NzLz|cL?+bwj$ z+&Jtn8YI!u+eOE6$#3@g5cc`84bo`IZMS>7KV&ldyb7-EB7{KwlQ6g5#hU-dnm_0f zBINOVAv;;~t{NI4ihCiIthuU2aNF(riiCvMv*xX=`OonOhhuDFinXsb8gR0%ojMf=aOFu(Z!gxrDzYC+kllp<^24>v=;$2 zfixAo-gDv6M)#b5q|rU+2ycw!LlvaeHS7Fs^t9%pnwlN>B?DziBOp-Tfeb>GdGP&S z%g6Ye2Y>9IDjv6@X%c|$dY<5NRxpxvTvIrHML)p}u4wx`M>UNjLNsA+bn`&dSk6D~ zAWshrFu_eqPB${`uslcaA7Gy+Q*Po-+`Nz}8~yiz+-)AU2MhYngt?0`Uwifrm?A?k zYNqEyOp#;Zfo6JsELqw;2%oHr#Lvk9>V)j%^EVCX-vSe+Y}eN$%uONrKN!$OBYzX> z)kTy1I)DDZA$+p#`N_IygrEgP3)hoKn0d)3CC}hEg)<**WV3b7(o|jhSD8vxy3-gn z%V?ROATnCAjqH5s^UoQ55QA?(P=ax>3PYF?iHsdw-GEUYpD=f}$Ecp-_D!4ZGeS6~ zdyXaayoZ>_+`c@cCDf>%o-o&F8HYGUda>tNZgdSI(~K6iQEf0krnBf9;7$X($Eav0;wGn5>(r{0 zdL27IQESjy=IhvOSUX#?+ZX7Sqf*ln`zGvS6`PLw?INw-dHk!v` z6o{~Ckj!@VR1atz%$uw^Uj4}+xQ~Pz%~SHL22AG3%vhrt$lAdsbI9WIc@k4wR7p0q zR;DNrti*=?ZB-RckSp^z4VKti z6R;-#d)``qUPo&}8J|5l!Va@oKDW&rQi8K7IuNbnEb2IvQ<_oKy1s29wN+Ho#X;+V zmXM=`za`E*5ndKxWEN)tI^tihXY;N3jxVp!YBNtJjfvR`jEJaz&waq(7R9}Vei;^e z(v3~!I3qU*fIeeUPeK9h1-91QHuAQhO&xDhPu@6v>Df6b{{mP$?{2gpf;vZ&*8N^WJkI=APR?|*Y)!JEn~vpqD+QW&~% zx^$U79iHIFda;&9FXUizfK?tduy{aI9=A>7f`);-5RqFG;-A>iJP|tO!tpg2Yb@9) ze<}wc4q~K>oMe8jhwI$pZE-uXS8-8R!)=Fb+;h+caT~|8)?eM8AU{(TM68ReU0$Lj zTK`j7ePUz1qO97lPjdTmfqZq5bBM>8oZO=EldW2R9;D8d`7jRga)DMQYoJjt zx!hO)*S2Waj_v$>WR0RXrMe%A!*c;q!kvH zT0a1Uqr8QRv?ob3j26nE>tVwAd)Y{6J~X22UQT0d5EG52JhXc3+HebCyPm?O^|)o@ zShMUllX+%M5W)3XOG>PitiQ9;o(Od>FrV=I50VDD=0mPf)It}=pcFW33&){Bv2W8E znUwm+0X#a1WNT?Avm}KYDYS2ZvH#D7dX#_lIl1HS&}}i~*+sYVFP50Z4rdz5e_c+N zC5&p#YXgj=MZ!kvEzX!Is3D{49#T;TWkHz~Uemt6lsZ!)~v_{P_+a+@fitAo+ z8z&b#@pn>j-D#nJL0L*`^jeV$$rHrd%|XX+@DM%BCgI_kZh#0 zp~>nGAN15tg{D!3uJw2F3KLfrkilF|bY1G_dhn_h(IS`Quh>^hJi;{MQjZ2|7M3L{ zEeW21@slqkLR~+Ap+x3fdi~cJ(Yy=*Op(GchB|+u;K^#|07g8CB+H};g4tuP^#h5I zB|@!@AaZ?2ZGS*e{c(U9e+EFr zVQJJR!Yb}q%JBhLT$Sjo8o95vErSlkO;2{v6N~EwFv_g1cGD9qE?Iq*o1PS2K-C9r zezm@;YMfg**&%$8MmPad7iol#q!CSah#sU7O_*ax644|K5z0X+$AR={JT_Qxq7+7I zI3{5)QjlkKW{TRUMXbGC1Uh-jHqp6_;LTFj5>%u{sc=@?d@dj3?oX~|!F zOa4mss6w(w?fLZp)gRtBmH!H9C?JOJTQ#tb!0;Brab&fK_m_twCnNN@&qT+Ccy& z4y4r2t|l8QmjZsTWWoH!fJ1GvsOO?_4$C~!K8xjPoPuheykECZmY+a=r1(fvW_z%L zqs`G%NSF@mwIvh_IEm7kXZFMmbf_1Ylz-J(ShBieYhY1dQ0kmq@>`?HGC=3Q#_5$g zM4IWPuJ&PlB!4lc0mO)Z9`Nfgc=n%o)2m+(O-BX;Q?rDnpl0D_S!6FH?1?L8 zKcnhJoxvJB2FtQUs!fC|1oX%|2T_oH^^Y?P@xdIh_I=qzY~WxBXVZ*ppcBvZr(Nzx zIi$W!e;U|_=PXrfuY742`hDS@c8CaKY3wY1#aZ`?ji7M=wD^9c%_v5U+bFUbC5T6i zQTkA103Ru{8RaB%B;_^+J`_8Ok7aDe(IZ*MJQNwkM=ESa`%kuYEu93tl0 zfP-s0%t3!j;=ci{Y%oKp9BSLopDi??n+%^Tysm}%c#s2mL1x|2$;M-o;bP0kUJSTc z=ax?nOmfc>oaDcyyVC`S_-}R)H;}FH0}p>VmZILqg#{z-r=%9NnY%OA(&aWEl zRk%?hGHoF=F{i3MhkbDaZfm^Wc3+)lku%EN~(0-(iU{&*@<}WNOUg$&}#sz@2x`T8p((%i*2$$vk zr;-Y6=P_uRpd-=qsaBJx9oe!no0AR0&##aYPgIgAfdBY3R@nKd`jMs>PZ%g+Db1n7 z@fu!F$SP?(NwAsa)3;$feE6VTqmtGRa^_uMCQfV2l)y669Yr3Z#=T4Nwn#?woP1Tt zmrw1UlqpSYTodO3+@8#A?i>n&%84|jcbotlZ z+Ssz{Mzj=`g(Tn)IOie2wT|4)A?&i0f-Ribe}7L<9e|hlD!=YAn0g934W6{i?z+1G z_y<~Azwc(Uh0c97GV#z z+HaEuxv?YCn*XKiE@TVU1XD?P{0t!-gIO4){+lf*2AQ`dFcaUJ(w#BEOLVj%bZ1aT z2n2;9Cd^cNr9eX-RxZ%fZF8xNXOW&B!^As7K#H7wH2rp8<-p#CdKwA$zMn{i!)1!(H z2Q}_h>1c)+1MgI6d%p3Qq#YQ1=9Xxz_K#VB(2?*lL^Rxj-Uh18wXqib;Xk+<0)Tbyat( z3{#$1tHOC-(6MV9l6)Kl$;-|Q(u``offs=nPi+uJ>>Hsc+G-6zju8_bUUmRZ8^#v6 zyB5MJPea$~AQGp_+h^tYhH)Fvsbge@!C`XGZWr;{n6PAhAKI9scQCyDcL>b*ap zsvQB2FxnO-!4AHnSzH|FMRE7a-p#4&kw!++h;3og|B$Acew|*ig;8#t7P%w3PROt; zHg9~4M#9sQp4a-(oT=hm>57GmrMbct`O9H4hCK)t-jtx1=p_q6XGu%lx)6#Pm#S+M zfL^cDhqYVGz&sb67Iz7mNy`O2#Kj~hUKA1YAe1#z`F9Z9duYl-p>cxf9}w8NqKod9 z&@)O%`uYD@y<iQ5EUMrU7^9;Ey4Edr3Hzj18$1H5Q@9ZPGdAOBSpvY6##vEoCOf391bF*HGtH zz=(_5loVBb$63skskpL;4|c-=dyWg#kutyg(Xc7I=Ns;hp?Aq^fJ!I%0hHhERQxE& z{~8$Z;`WQsNfj5bhCO?&{@_DRdWIr132o{F9qzY@jEe!I609sO!lG>#&pwE%p^(7FU*ou+`3urr&zA7`5f`1EVLjdR2CDHAkmSDFy%oC z=2y$LxH8I-2mZ#gTzfww^DF2uraThzy9}1(eW-MBgcesuIayM^eB3X`#LR-pz!VEs z(J8iv3frWOKFj5t6#eGWz@AUJ!F5|~n;z7Aorl{-VlIbBe1p z49d6cR@Ik1920#K;hmc?-{H?n#_-^nI>Cf1u&%FdK2U z(UPPU7QQ{gE(!As@bfXQcU^AK6x;p4NkF;SB#1uBwf{8Ze&}`aCP7at(DnU&_Ve%? z_j`?b%=7Snt|R}$|6E7Uk$j6^euYd&+0AxkA3@Dy-%ZF+_*nd@1(_o{15nge{;Wvk$QU?Q11)( zLrJ|g@Bge``@{9d2`~!@O&5rkEEpL#_(L(1Qi7s)bG@k%8%9_QL7RelYQd-7LP&%u zNxb-wqy*v8=-!xRVE*bJuqnZ{L+NCOk1lnf5@y^A3z568)0Wndse&$vyEV+y8gg39 z{4Op#&K&LLx?q(n?~=TryB{+t#a!bg;qd`ok}VIypH4AH|CLWK?UI~&B)sNbKE0$1 zcqfVn1?kL^o_9#hW)X=AdL$;l8Zo`sNQCl1M2fkm65*XIx@o1&7rgT9wtI1#%+VEy z$<0)L{LTQedl$5D9O+|OEN?)fwBwPcQ?@I4v{?Z#mZ zRhgqValM-#gkU6k zHbQ@(=uEX+BkY^34vD~St*E0*E^tIT%#&-f^DJIXxy3{zmc4wQ5UzX#%nvwDpoh`y zUxbqsr8b@*NJN1oQwT{CNj(W8B*FX2c_tDsF>=MtM59w9co?;{c5E6CG^hjDo7 zG=Vy-Itb)x6X1R&=mCAq)ctuF33>kLJgiyC<%EmpJeY`2Zwku)J(qJ)xaEUk04EpQ)IxXpt6fUC~St4CIIN&XA>XD#^hp-KDctGrH5b1Ud_-kVWI*kZk5)%@Ox^Ucyk}lvDiD_ z%g-GA5Bbaed*yOqG|1Qhs?-r--&0kP3m@KzH;e5~_0%DFnc7aI#oL+j5gNb=V1j;S z<;!)&4Edbvn82Ewed<|Xxu6>W%BW4V1g8mn1Ew;;(ICggtOw@^*LZ)P{Of({>0i0v zr2254@PE%E!r7k2rxNWvh>sT^F@A3(?Y2@zU%x4Y)^c}~$I9@mb@JHJ@P^ZgWRKrY zo*qVK)#G0V;`x@& zU{Nqhy~mQ(qd?p5cmoI2Ac)Luj1DO&bfspLNi)3dTQyoq|n5d3;Y6 zZ&ujwYJ^Z=lL&lHA^#K4AksDo?J$e*6K7$Yf$llfS7`{91Fir}L^(IB3gVP7p+EsX zrv%R~Huu@#DWl%Q?nzqX_+KS3(CDTEEFy`vkz3WsWgi@5h&O*|cmQgOiKitnbQaR> z;kY|32+wunrA%5f(h{k_MoUMUA*F4!jQ>vCjt>ERqBG2Pd>H@Y(WH&!9}Vom3APX( zRzu^jX6HBdUCDkw-sa?Zgf9GB5I+faP<%Yvi4=cBORr?Nud@k-xDUmD<(nY`ZWkTD zT@g%6&T_gF!x*9ck#t)mrA__ZW#iTg0oPR&n^-U@E$>4WDa5xcfO#EyGP~g=`IT(2 ze|MGy;sJsY7++Zu7-E7dum<{DpGMdq@n3JTy8_@@z(h3eS54UJ+ZBiGFUgUTd6E5q z%iq&iG+!o-x zJ$q0`uRRjX2w?%Lesa(hBGM^S7j09+2+)*j+9hAKEs$uN*0v!rRa&X;?IKg~G0;T4 zitE*h8I4EHZc=UteMXPhhkSS6di`CgJ(=ZsyDrx-*C$m zJHoA&&*Ap%M+=d3>>~I+Sie=f$lDt3lR=<#O+{aP6tC@qoPg|s5&~swpZUDC=fMN0 zyCy@0VGSKTqYF~a@@8eaMT&W{nDAihoX=Y?p?GKppql8|r6T1=dgId>mQ9Bf!u|5B zX`i=#%&Rc$g`};-b;wE&s@R+H8eTIx@n$DvR4!!1h(8ecsD+M+RPT=z$0Wr_LMUtE z=dE5+1o8h9cI?ul2npHnyKZqzY4nyp+{9aN-1RvLSZnm=zSdq2Q;iX(R-W7mv_CiC z2a}w8RPNbS!G>#X;9hOS=PuI6rh4MXw`(rCNMxvk$SDJ~P*hCtlpB{kAg+bn@`7Hy=(I+{2^ z>as*eTB4(c{C5OOSz4ruRIphRfEjAhP(kT7Mz%kRZktNM8Q4hETZMs9WE^$0B#yG~ zzN)PzUB41Y}gDxFIv~#Wpiint0p{v zPlES}uScj(dW8+Wfnwpl6Zv+Xz*^SL0QuzOMSV66c~%SNnS?ipvWt$0eLD98$Mu4j_2tkRnkhVZpb_>O4a>Ss zupfwi23oh$_}rbH;!Ke{Y61DRS+k(sNNSua#+8EMCKuP2l?BZo^UtULPM6RE7)H!b z$91ujNL-_E9`#J**9%1v>Bd>}OiHmiyW6M~nX)NU40(*i6ul7F>F8PLAyMd7QEvSE z14VNBl!saq`Sw$SLP2OgR2OJIo%qGe?->}tWqJkZQ? z^E+Io5(!oMJTum0WH4{CpYCdX7g%X6qjK{bL>;bYk(cQ)8KpiP+9flH`;X5kGYRJz zjdE&XWZuFBX_*F-F~DdHe9a><{;UTKaOS1VlcWpC1cw(1lJc1YAIdB@8kyHTOcwKE z$uY{P1f4|2Y~0gur!2sI~2%-K^+p z{VmYl8bpN!E#eN>yP%&X2ySBHWe0-IvaZ(Lha#PbG#TZRQuqwgU9H)O!io>jxDHo6 zqI`7V9?z6^CabNC)U)dH7w9^AgoeR8H20Ln-{g7;n%s;gcZwcuGU4r?wRy)be*Hi@ zzwT^(Y@{i$z3XsKM1}4k%Ayq4?hi75-q|`8u`S}lf)4j2MCFKnc>F5~E-ue^Hi!!) ztuY*li7)w#GaUNDO)E1+#;B*z9uqySntasOG$BiP>GTDLPlo;cLdL<>`N%k|?`%DVSbiK_ zU1S{I_{+!$E$DrbJ#KOnwg42bJ$#wuK&{JyjGLjdzIff`H4t_j!`F!Iw7 zaS+|J=Bm3cef%Z-LgA`T@Suo9QQ2T~0GYHNAFOHFzwI=f8`g_8{dJK{Fl3J|eeO&0 zRi6w)?l33Tty{UWU)z3ZjefoL7FWCm7JyD%X9@ul!uu4jn*IgAh@@`0(x%C16H|C^ zz;zXO8f0^_>X-hwa0zd=!w{Is{-W4lV~+$AP?Yhnkusvc@F0y81)acC%5J#=gM&%8 zRtonGWSHM}i(4yheRFv2GO|tBg#2s!OKY(a!;KHA2wG+yO#d;g)*5l%dn%R{A~=6H zf4vicb4DOOP$Q4{1+txbdLHeLr2US8&4MT7jtJUyo3lDDskaZ;jt_M8bG75gxca!- zst~}+0AfHR0g#}~wHMz?urVbUFZ_)N)(G4vk^3Z;o?D=#p}z62Q>w<*TI+D{sb?8j z-iG(7U%P}&3SfKCG2E)U{z`6Q@f}zLe;L6V0P6o-#>CE=$M2D>moMY^NtTv{NLHH4 z%Av<+oqU(5XE26l|JliU_A;hLF4_YzzsUf>o4u55xQoQ|UXsUrBMMwo^yIwIjEN@k zJP6OX$4+odXy#3z1lHo+bS;&AotwV|4jN7f?1dRRig^>;hk_MP++He&^rM-Cwq=le zt9tO%qT@IRgNxAR0xT&lQs%{)8@Jl4ix=XZ-<1nhk_akd;cIIOUOAufJxA@2Y{mPF zCJ}{sxAGMg^VXWbOJP`8f+3)aD}tE(`HNNM$(Jzy;MFL0#La?BBLLqj!Y@EY;;7@w z)+maO7q2Yqzx{_W*B^geS#h(v+7X~Ah?5sD3S!2WEmR>Lth?5{6$Y7vZQI{2wGIv8 zPLalyXU(6%2e{{v7G+bR!ZBAuLr0JCNa(rJm4_9bbF7>3Xxv)aX+cr!i(Nv(iz9mi z5%vT^vL^tH;ds9D6B0@^r1Q)r$kjS&i?};J(PbK}GMuK7uF~+Fe8+6p|GL!r`B0s_ zg}$<)qvlXU03XvnRuW3&>k;{t(D(m0j(*Fogj!#`3|WfD#w{@~o)#p2Le|<0T(^pW z`ib2M3E(T=5vN^usr4iDrXfJTw1w`dA(&zstOEXX4{V>wz^o^1$bXyA^Luaw0GeTT z5na;Cy(`4qv&`&_k2(L{H`%}UtDO6o?YMALB^YX_g)zsTvIR5G7jF(qv#SgnuR~qo z2#Jzlu@1lyk2#jcDq@Ury&m>tu_~?q_Ug#&2|ucgH?y8JiWCJ=V~cG;ObBw4Y&(aL z4SyL;@_gDZdOdPeK6#<1ihbX3>T^Y_(OaYB#l~o2?#An z(e$SwVzKz%3`}_}%7Z4g^P=ne51I6Y_X!x^MBw#^C_EUNMHvDwlZA^w^!Oj0AosgO zd|<}*+(2QkB1ti}D;jfF-Vv4{(gb;!JyoV)G+4kd17days z00z@Zt9M<52@EKQKc>0uXn;n@R7co030bHFd}mN~30@4TtP(;OqJn+Vi8IA)8A9y< z?W7zZoxzn*#i7q9-h7{wX{9W|)VuTw3j=LkS<$xH0$fCPKCj+#(RGJZ(oM`6oXeqc zMn#q8c>!Ak7%}7Eu~FP7&*1FQAU>cQ)gahpAX@1GuF`BbGz%h5eIx*)>fF-f5%cD@ zACFiuH{o~$T@pz}oDV%fo!d|2f)35IrBejsWUFd_{QB;b+>VXc8fvGnY#DWWbc3kM zd;v<8=yz^i$v$tWG+#@B6n@Iq7W>6_1r*mNH}O1OSvR z%?ho#g~0YF%hJ8D^ddmShy{&i8|(%mtixbl%Zy(#>p5BC;%%x;+m;K~6%{X3bjFxx zUUa>W-DlI=08keDoYx^2-v!RH1aH;*$;4DPNDk;_4T7rd{4aqc^9YSBpwT-t4y-(x z;Ab1rwe@`QvK?H1&ACT0W$%uK2c|8Wa`JfcA^>ut zSc2V}q|z;+rc{G`GY+mliDYy3zMp?!TH+ieOLPc@K7jrq*$$P@pQSyBstWQZsS;CE zDe^hhPXywu!Avg!LGg$W#l-ORY|l!b79hcsIQzeA8{`nBH^9(<1!3>oCY=9VL(CWW z^YLe&$MN6SVqXAW$0nO;j%}th!YN*h?9|Xs9AEMaXy9hxznTIX$`dO3t+D*8hgAMs zVd#QKP;`E>%>Jt4&<9Yk-lUwpnQx5?sVWqK0%*9nM#fme{-!05?*!5}**wcuJW@#kqiz z0SQ`&dCr^PjnIp4gVr@t*2Ra)dgI^9YUkEpMOkHWR#KMY-^)r|&A1JJzL4xu0w(S_ zr?J2(gKyVcM806z3Le;tMzyRZ6mw>f#dD zC_r2LW7>Wk0lc`+g5_RViUu||MY)1RQ<+9$To`qaz$njfmDuyA>6~fCGBza2ka0oZ zXBX8G0Ot4&>wPM_f(;fV>b-CPXTlgd5kM9qWO#r%l(TT*Lj9>9XSRW7{+sZPnVP|_ zKbB@v%vs1f1F;w_($OX-qfWfQNHgh|=(?zRQk1@10OxLKOHyOgj2_irwGc*W>1E~r z3bOPp|>bvI|VJ0km&?h0^C)`nF z27P>(%ZfbH;Zglso7Uw$(^Yn+!<#o1UFu{rrLMnona{v|^n#YayNjsvT4waT(U{Y& zjU4W!U>{r?F|JP9^gefI34|>Wxzs*a@Z~Yo6+m*im4f;ki&B-R{(j()u$e90Qkw1w z5ga(=@1f^z=^LbnHMJhWb9BdPRo+WwY^dmRw->;k?ID=>OKv!h3c7QoWr?fJFK}={ zxSd2xKH(gp8eM4YR8eY*BQ&l$$q_Ra8$?~f*!E+vtN)PG6KGiCD22ioIap0pd$&gF z!UQoj+2BOEm`t7!eNAp%?m>cxz-F7gRKUzJbeuq!P~cIx}eYRlZ=QOO<}AZ7JCV-L|-soI10Cx6l2 z2dqpJkCkac7yb_3iA@@#5xXvtUd=<$ex4U3(UeQgd4m1pGNw-4l);@};>tjRBLLuZ z2Mg-=9@rkUf++kn!NvuG)a@0H)nLQwbo|Iv&JM;L*GWK>ahT%C`;6_~cCqUyta_WK zp^S5o1F-a)t&EGZJwvUCirqF&6C4+!2@Yi`qlL!Qi;n>nGa%7ZLS{#n5IF(6EPZg! z%eSp}hmi-+^>DVPEzbzlw})-VRVsTK8wNV(;bL2C$(4>w^@xqdD_7$R!^@pm&&v_G zw>V&uJ;*U(@l`-r)exS4l8l9c!u;N^Q(9-8cM)snCRifo`rM(UshVco zAK!s;Z69!K4$ZbPwgO6*BQ)lSOgUmaO&WMw+@rq5pRo<9^Li1Fp{Ct-?m0O;AY6xl zZcBT7ME{@>L0725Y{DinRR`;6zr8Ekm~B5t&gSC8#(wPE)1Y}GSfjaOQ?wT6Z+|~* zzJ6V<(3mT-zJ3m?8qV=rqQ zaLz8WX^4(IZb97AIAL6H+|IbYD8gXU(*Rwnzqv#ZA8<Q0`j9$d>p!?VD_SH~0%+=;2e1fK3S6IX&Jt&#%pEEXT_>uIRU*}Xq=IUq zY&XjJ2U0mgr4_YPDkbfUn?pOdU_V$Fv+kN_H0+kk4mb8(nsB5SH&sB4jpym>r-k`5 zz+-77?GBCD?F5ezJ8z=@;{}oW&2Mn21wzLL&s1;t2HM~M(diIv@+pNKO3^6~1awSz zbpfu=yI}ruM{=HM*S7EC?Ydom_RpKBp3lFxmY#*v1Qd2ms!gK?pAvooZyFTmAl7n4 zbsI)s{>lxM8;Kva;q z^K7er$^P^#HbyA$mt5{bpKAljDWa0cF2ci4hFNFz zBG-?@y2vM*E^*M02?5o3)^H;4k|mW1yO96eHXkwmsi z0E(8a1;{A0kvX5;&iE9A0UDFO=?%;qAav}m9K+tTu2$UXG>yiF$LFd9-xxkP+ZxDU zdE=S~SJ)k{zao?oc|xQIB7@YmXIq7sw9q>6s9=oc}eIl)8s`vMc6s*Nei^4ox=bmB#twJH!hV}q?sD9p zNPX74OLmzbl}~+_bM7*z;t7Hukz+GSyggFGmXi~dx6GyhxHRh&011zEf?$3hBcuVV zCzcH`vWn_a5QkVSi9A#$+BW#FR*ShK;Gv)JIfy&+eSXZr&~A~2g_4JWAm^S1s4do1 z{K;+ofkUUPw~13zoXq>(h?c;19hh$gFxuG;pH zY?b%%mq+H0x#H^w^6{;&=ZYQ{k0$ts_dhHibrwop|Cydup^h5M9vJsuu+kv&&AfLzaCqF6L- zs-AYu1?P%TrjezbsVZZX&K*tzz~1NNz)P9n9%EDjz7bFWh;uYL7XHnJU(Xf)kD`X! zx0{zG*7cu}cW{7chc)(|{0Kpuxc$eOH|zK`t9A@#Zz8S(7^cG7ryi3sW7D48fbI1> z@s3w*p)@0otyJ1Vg-mFo-CLZq0q>C`@;Qk)|1-)LWS6)iuyc8$=^B^VPA1sv^4@iJ z33Jk>A)6)gyEDA}tIx>ECZK5pjyFEnuOa@}MYL{_F!}l((1jcEQR_v+*7&$jf6O0`CZ5e zf0_#i(V5Km(4EjIi7kZAp7ELM)=+F^vMofIT&dNF`CWtNJ^1LK=Z=^(Y|R-?Yv5pL zofxmsW^l1dtVVpV%nWQ&GsWnrG3tq?CccjZGamQkz*od;k7(rxPr?5L)-|YAlwUlG#wp5Kdq0L?C6V7Fj3ehC-z zvbEUT6vc+L2rf&hoNMBuXsYO(+#Ndu@z&SBe_ielrD0sKxxR(2nfpB}piT>kaTb8T z*$!NkJkcfM?YySSVa|igs`vA=zW+azy$gI(RklB#(ulIj{|M`sC45a`12C z$ad%Fy4AMcQoX6r;M7?29U=AP`O3P>jiw8Xakh!~zH-yMe63V%`aox4ro!Z$MCJ}V zIiSp5bp~bYc^r2|Jg4+EpUBkvwN?%+^pwLzyE&bQi~YT&LD}=39$npD&)LAK0?zfm zyd%N&-$w7BVz)&EHC{n)CS1(*24E!IYUU`Qu_tl!k+oPU6Y*W}Knwm^fqy0{mBySt ztLiUFyBRC08k7vPx=fb;Iw3Y^J5q5KI0<9JA7V2^Gx@v7=cMKDZl*Ot8NrE$j!D z;?|t7x<{hZA{xeu`>4*H{s1(aztKtc^ztD`*d)KEVzz$aT;e`~zY_PqWU-^gEyElo zByf&b{e>@3c*o-Z7BDIwH!@&Ms3;c4_e`7Ro|nP9M|$_>AV=-DwV}9?wXw#l z?d&*GK3<7kDUre!6IT7jnz}ON9?l-XAV>EcBQ$}$fbad2Kw!2k|ZHeyiEu^E=zF0(i!#CXN*3fW;xJA!q5gjjnB-nTM z$iJH&3q*|jrNNUMcIB}XBiUqH*`mayMJUUPKf}~tP<_8&9xLBk(?_nRp0zmcTU^pe z{><5;|JG>6+CBl3utUw8GYKJ^7qTdDYi)i)zRkTRtf{MOuf zc;Dw8-*(1e{`%f#ay&xMZpO7ZYCkD{jXi{YgY)6`zEPea!DHk(@z+ax3E8OtoJp=D z^X+;_3?k>=nic(SF+K3zhUjJcf%m}$liRqJ%{-B0c!B(T=bHG z0&iwT^B-<)n9?_^gEI*gA>k!4W#qV12X?#=(<$8DD<~jIce+jcZkXZ}^8(`?l+v{C zmcxOoA@Ii)hg)IVcP-*ZG?gOOjIW{G#@6GM`Z}QMbt?Yuf3NxjaluFk(-(Bs7{#{L zv6DpPM{c(6zb3{j^3|A=Wp@X{#ck9s|9ZlY$?0MCFZmi|gOPCZ^8J!uR$+;>2R|k; zl5HeLQg{O#3v|x%&ko{wTZK=u9gH~|e?jJmlLC`8nMlHB=}472TY-RO1Opp$Z~2rk zvR)G7MvmKoa!v%(J`GYjCXUV(}k-LG_t+@ykMdArg z-5zxJfbX9*k?X(~5H-X}`|bjQA2%k zBf<~gMS{QVfed{Xf+j=|8#l&F%nJ3Ee~}-uG1daLAechHt1X;l4p;*j6Z>1d#; zwZ02C11B_r%#oqwA>rgsJcT#eL=mX0~RXQEOIJJrT7Z=RbSQqf#~N8y8v@kk_S z=rOCZ?!r74u$aYo-Ke+OCq~tG9qaK!=2e;witM)ZV?AyPX*+I5Qqgbcd))EE-0mT6 z%H(#8aZ?~I1U3Fo-0LK!LXr&FRcg(*$pJ{l{gBc3}O zM<+7j*~D4f4aB{h#kPrC;_$S}`_} zVbfbsv&5~YtL|ezQX?XthSZaKz8gLBX$nbV6SxyMf#VdFdd9(d$Gm(wkzni>QGEc! zk-`mpPOxruS)f>1T~srY*T(S$T7-EQD12Lv6L@scU538wNbq{+px-}){=#vJNSv}U zZr6E(@4lNUnVJiRlv{g07;*fAq&E-IC&$;u?k{`4$fVN#?JkouZVf1ql4&jr6etJ- zyl`C7S8vn41e#qW`0MWm)?T{K&Ug1s>{=~t@g3h*Ba*8!I+N+%WNNEY)W%_7ZPf=d zN7ofKmL2{Ts@!8=i4H|Rjy`rD<{<~6^rT3yGG6zyd91r+BaSF8N|Ca&@D8EmmpW7r+Z7 z9WV%V(G;)pQp2VzO)iy(QWvELff5@g^{vxtJ0o$xe zvmm9$h5Ovl-V3@q<#gLtt*BSA_liX-k5lb+4s$s5)vozSH;NPY#fNq$w8gY=7$ANN zyE0IMc-i>Q677PNtIMNJ;5S>f>~OT=b?R6B(BDv;xI1AhcV&4aH{U$nhPK*ZaRZ@QVlH(fZmuS|@F9I^(;teEqUZ!DAQvL!SQSCeqK|1k%HuG+=3r z-{Bm_rpe<66}(a>jhxiUd^37z(;#=!*W)h%GKD(-3*c_I4UtNoEJ#Ut2xpBAH@-~L zS@kMUff}JX>;!9po~6762>p-4`}4<5pDc+L`5anwIQa9 zFy4CXF%-(q$WKv}O=$gH8B9%!3*@UE*G-49H!F*xWv4xKf+q}6nXhir%w53KMDPjEQDb3J82R1-YYhNFUu^EDY zaNj#O`f%{f=L58f2qeDSL4@omk8AC*j06=T9wRD5BkN)xf~^vWqeUU^-4!YX04LSN zYL*Z%HAxezc}%rt93p~Q6z2Dx>3ffk4gI4pXGiwhSW>qgKUw=%5}G5L=rdNI;_D`L z#f4$)6G*l~fX}xzhfg$jmJI1C>G8U-97+CfyE!gcgeQ25-*kSO_VBC8*g z$fMkF@;a+_6evB#2#*b^l*pBNmf@xxdpPFxQ8a5>^PoahDK3wj0<~3Lpa6qh&iJ_} zj?#RUxvkU_M{B+^)_#TXa?MvGYD2VE1?*T5^y!DpG;Am`8iM7DbCo8Qs){#jfO!yGM`0QZ_~T(w$iXfQ zwq6ezW7s%$n`tWDl?#Q?6oDmV$0JiBylqMxuxtbh0CqWf26?RulnldTGaWDvGetC_ zX^dw&jbXW#A3~cZC`S^u;`y=CfSw`SEhmn`(-zT*CIW|W+pgm}LX@2Y%5h&$QZW!Q zIJ2RyP3eKnjN{vJ1PKJc#IkaaU3bv*&U?9{L%~;;HW#xp$s5|{xSeW?IrnRR2C&V6N_@H7-$|~vWXQZ#e_Cv-v z+lEWm<<30)osDt5c+{AEy@-kSNV(Jh)9RdwmeJT6+_NtAcyK@m4pGYPDZb%{f{&hu zWiaCg5#<8O^T0UCHI}}k{pmaXzk$B6>Zl(_aco^ONS;)n@xy48^de$TCKag3L$zoo zF)qHlu0LKM(B_`p+IVHdvtI}YcO8EAi}kI;_BQF>+>UDr5%C#t<_h0(0jMhfU zw3EZthKSbDsm-kcEKpuY%5NGkd@=y=gfTv%M#}R3`)kIcqwYDwi&OwC#B{<1eia

&q#~oJMc+xNI%dMes#EXDJ>{QFvY<<@^AP%w)IMS zi18L+)scg+zHvu^3^|#)1PuBi9Z(k8WkQfXD0xanVS!3aQ2CzgZlc!JcMa*WlA?^( zJhcra!>#R%HC4V`4*|f3nphxq-vF_*pTabt$QZK@0qTJX_a#iY88Rvid@Co1X3Hv` zGjOp-0dYBLRI1|Bc%)-Xed2d`2LM=}0rSNp;g3A0@+pow;AH^_27k_v-kmjzX8je< z8(cpeL3>3EX)m33aH>H~M%$cg0B(D`&2vZG18q7udhq+*1oQF1RHk{MoHTxe0Cuz7 zLL=iA7ZvY#IT#jn=+0WAba2|mH!r%5A8Ak_=Zf?V(n)%p4;JI7U<$kV`b8XNDP@>B zriF=ctw#viVMaL8cuZT)XG4D}3|_<)HO#0WUhewgV$NIx*DSw`!QyR1&J21#+Wz-a z`{sf6|M@?(AAP@9dfz$le%(*LFRj&rI8;^35it(yR#yoaL(uM^&td8G{N>iZqul(>YviPw-u z*S{9hd!+`poV@qM5s&nqONsZe@@|e9)adOt8_ByR|8txD^ICjLn%6%n2Ie*Ar{;D0 z{ZC~&{9)jI=TE&~0=Fi)Y#zhlDV3F?@V=F!Q&uBF!HR=t$`RCbvr#+;s3*E92wsWt zgKrl|d%`O33G4>&C3eQ3X%6g(4l>WN@@{ZQI}Bj+z?*0f>oKD&x*VgA;1RMe3GF26 z;<@i$Qcs~`9lYrL2~{XLHRMu;w5|}R3?&;wE-I94;*-aOpeVRh{0S?JFZ>5#u)cPg39)R01%~`imKLuNcKN;?^F*yS z0kzu5=92O85(Rg$9XKN01i_3#3aQ~{@(6(c0yygF3Iq;ws5FOd30g{K zI`@CI|M$7OPPC&HNp4CFhnlHyGqDZ9>!9PRFR~%ZCSXi9Ms6KEdbWkY~dq-+gvz?T2jqzrI$Kzowcp2B)#wS7C=2azbcjuQ+i62HEK>0=Mv zIeilQP4?73p2I|%Xd;wAs;;*#TI$;|C}J%0sr|&ln6RhNp0rnjKiyvcJAT4D)&J8w z(mwV?iT4+oc-WM;mzRv4@T!xD*tKMNix>x%m+>*rTH1pMAq_ zop$SstGC8HsfDjS=HuXL;%omG@wE$I0V|qSSW(9$6{N6ZDgye`H3l{|{K}m53om_x z`brnep|9bZC2?BrnUeV$$Gimhyb-Hjb^S-1V_H7@s$<$T-zR-ergNIJbK0cNX;ayu z;cXKoS>ltotGnao$L$R@}Qv@)u_EC8U0>pJR2XeyMXD(K*sm z!+RIuJ5gK|Lblho`q#ItzbFcSbR1WSc~6Q0U;jGp;Cdqc>5FGduDCMdmq`^5)ESC= zo5E)FTdec+mTi5#)9luH!?IRe=Ox-0e%cgks)N1fn-aKPq3pjEL3|H%dg2^7Q)0uw z3$3Zv&b%MQE%8n2g)MUJV{uCYzD15T`HhVcwhz`d49qLvic+^~I#kxPB5W2PM`P53>woFJ~Um zd5<&Ru|I=&rr4BI>eKLckJS1OpF#!5XZtU3`1lk%?ti(!L0lxfS|N9}<<}RBU1*Xy!JN37{)oz|(VFsBMT1w~KlQ&9=ZE}4e1f5fTR#70_QDmX@6%6GPQJgIs(Q&9 z<7(Z#W(v+xh4q9Asdc$OcbrgJ>FYb+wpb%|RA}5=FwIp2mD6uq7i?-}aUCW51j(M% zoF$1{LlhnYmxhFj?eADq7lhyvrtmI|zr5?#=`*WJvobd&J=l_j=8shhrLscWs;;-thaDTvg;k|7T5X43OCOwGItDSPkk zRi(r8yv&(x^Y~zWIgM7=t*%st#M-b})hY1avE#)9Iosbpu>0_dzO!E-Wd!etwIQ)8 zOdgu*Um?#<4OPb}NF#ftM%JxHGo+EKuvmM3DB9>1_`}5eCbiV_T?N>Z#EX-*s?b;D zc3W*jKW*;~)_0}~*S^C`*dn0XJIJ|&CCz+Y)h_#L-i^{rVVTrQu1U_i2c(UDhw}mS z<96Ku{c`dJxZ$%`h>3BWa5(8KT~2$C)84TUplP0&^sMgnWV0``HTcvw(L*g|XEYH| zs93kgTL2G_q!QHG~; z^#zN|)h{p}NJ8~h*O1no>*^rj3Fj7lQ>jlm$v#=5BpJR+_!WpNast8`ti$y{Xe}$i z9bjh6%1<~s|7wBLN!tL&;adkd2pghbza#we+zo84?E3^KWm$Z#- zv*qNs5(UX`kvEU9OX&^7gpubzZo+d!s~zGjd|fF9K&6j3+HdrjI(<(hb)$ez4M))4fv zbmU#~_Ij^L1Hepy`?15c-IMV`1B1!QkH~Ri*?N$$5PJ?}Wl7*D7Bc!niR}nRA|}KY zj=SujT{f!fIcw^B4XTt;0D`QkZ#Ss22yc=gFm$27cq)Km6Imx*GTwbdDB?KPVMDrL zQ^Bo^EY*KNpD@$n?nMYIG9!p84WD<8<0<>9PJ`KCg37EiaZ2L_92h1SWjv46A|4JD zHqOMU8W<>^)^-xCW6J%5#BVUf)i-cl^dA&%+FqJi;1(25GNq|nE65)|#vO08e2!ey z6@G{wZwF9FoM4IGvG+o7L=uLfwgcjKK}<)&Fc3U}l_pPs5fT)MbLn%!(_Hs;Lp7J8 z=9>*U(*@Y~>IQ8Qje>q%S1(xhA9_JoPC1&hy<_7WXuc#Kt%*mKUZH;F$_`2_8P=r1 z`^rd(zU%UZh*3YC>l`0f7Y(BT``1wcV_an1x-gT2q)8e%E7g?z6LhfUy9;)MH^$?qm7FItuFluEVPCN0Ei660^$2`5 zN*PxwJCl@rlA<>;x9pq#Hxw826&DP6udLahP(&?JmZeqdo%b#=PPhD?Yuw;SM_W=$ zw8Cv1#?m&*F%{7bZ%F&mk|;6L9r6ggfOD^$D|z|)>3RC%i8hLR_E3nL)B2g8DA?u? zh;j;GY!3OC%TI@>MUoCYS&Y{g7vfme33L=R{u41MVUPAUS`h72U~bPHh^0P;k1xbxgjaDgKYtVci?8&0?3L|sv}Ma7Ba zXIy?==BXl@`}{y~{24&IZGiI;M!?$fD_P}7_(Fj$B=AbT%O zifkvPmD%LVJ!H*`wMjQt6FG*z;Aj7h#8nbL2)g(R313xI3NQydQ~~XmRr514??K5V zRDJ*2H{lQ>ny2&TT`iE;WD0bd^Ah*U@VcjRR@f z?*yC1eUvGh3K0+z#u2^0@<7sAO*y@A;R+&3_d>p5`;-$uxp(Xv_|r?x#Hf;fpuA86 zG+2wOuN`SYjIcp{U^fQQq6DfYVhhv2o9(6XgyNvHBkMZkVf1hNs5Qg-|1KS+2?whyVkS<_PaHX9Uar-V3W zoM?uQontaR&!W5>$wwhPq`(2ntFI+pL1h9(7RqRbz=(B%eoYgkO~HHu8ojmP6QB+LSV(IuS;zZ&eCIx< zYSfF&HH_)m*xGS*u}GXA7eZY?c$;+M)N9D)7S*nulf`3{sMA$#ZvCwjKE8bcaairl4?N^`z$CTEX zO|7}ssXgMz>gWi)fRVX90$sY#D%<1XQ9YKIX1Tjl;F)HK#1rEe~0vUM4iK% zpKrjP86Fl07|S1noSM7y{SBM<2fzNRI);r6WM-$#;7b(57Yv=hKmn0B`97k`A@;PG z@~Cq?1+*tk;mKHlbH%T;I_KJGau+3m9mY!|Bs-SuH(9@JZ6cRDNI0m=w;wFyWPI#3 zoFNr!1xH$eO$*Upsl=LM&vR!#ZqSs$l>wI|Q+5m;R5Pp^LkfQQ6&q_Ol`TBE-53}2 zOPEQUpY|3jp$3m#Ac>Y6er44Up4?~*)F*7Lny5-1@cpq6b+PI*S=JpwKi=GnD29O( z%bI$)1@Tx;?SGdHQU3n?>LA_QeN@FWH@ICNZ`&_;z+Uzx}OJ4sNVNT`hCM{yS zVVv+KB--0c-wGV1{QB0Xy)jhM>vU2Fvpj2mu>328*(>(4N&{ zK;%F}yxQXzM8+;o)6}U+WQYbfD66Sfdh>4i_1@`JtvN(@v((AI+ejQ<>Y+6_kD$cj zgLmu^sq60A;nuv1Hg$-xTT|Qnna+tf9BGI8r$+QeuKZ&%w`$H$FW+$W^b-Bj_jvPL zMX?R48l|*7G0hj~YGtE7Nyk(@N~+3cqwE!bRAqIZw=(vV8zF{1T10q0H){&Gr)r(N zSljWprDvaw${!j%x!&&Y*K&5BGuB4oN*GL%`+A@7wxMcD=}7ao**M#${t6{BVyvmF z?Nbn%L^yLPOjv9{Y(~k1g_eysFm0km%Y8Xg9>m`gmO z5&d0AAeY=o`-Sw&U0t5`F~ow5G2H7!(32x=2MZ%n0YJWF+3j^RDRY#4oM6E7>KwH5#S;;hE$y$2l;#lRdJ(Lz~Rlk!X!2@8qpxMa@!6&VM>jc~J8c-vJTO*dE4R#?bD zU6|Hgj)@C|Fk%2TYDbEb(Ezxt}kt_24m$p8a)7A?3Mq-P8{KkW`L49Leqi^5dU_#eV z9}I)fE7V}izmYZZv3S zzLh?cbvTW`NO~F`H$XdsGh|{4Bya@w8u>}|yIX$VP#hBdT_k93)pt;NPx?TZe5Ye#4UM^y0WiPN)1+P>jfOZWD= z81^0@oNZ8C#MhLV+7O}=^O{Y3fs#+yTdm}amHrsiugC|IUL6xm`Vz`2oL7R5eNt9a z*S|_hfZVtxHZ@0~{ylYu$(>9LgG$A^1ZW#Th;Pd#J}qcL(yWyG|ZV zs%C9U-{s3$f1m8Mp;EM@Il^|Y(Sz~8IoM8m+z0R@OT8RMSQM6ko&Ng&Z#$h*TOMi| zY^P@=JYXM1@E*xXf1Vih_rajw`CCiwp!Xyj9S3~b8cG2JJ&@aDl^_Fa>L=2cm2AVb zPx=+xs6O=JWt^?qlLa7d!a)yZceg7GC$b)9Q_>oR2kMcaAa_8L>Vm_M|d*$P_qT&6vZ(lJgi)p z=Xt$xl50L!c9}0371F1Q!VxEn4v{}=f)TxWVZFg) zObL{X=JjLAmwmy`QOdw5BzUJU{LnzYITiF6M^~IO^v31##xdlZ3&Hgl47*y$X+TDp z?8*28h8Hp>lOdJS=~d^wCA1i?BzgPsOe9{@8?We$R|Vo}K3+{4s1I5*;>aI6g5=+= z(!Wmyd+H6RcNo^U8qgc~#00|ZMiB*+-UK$yh|NY5XIQ-EyqQqNWCB$T(BQ}?Tx#wt(K8=O|V>fxnTaYW^{Lml$OsHLj)k|R!LJkjQ3ENeEKA?Hg-(155 zg7q*oT!93I|4NN7kbo#mWzB{_0#o@`r@;GtXTJy~P$*rfsMps7fno>7;C7?l1Wo4{ zWh6nZ*rBi3VF)MC{-B~y4@~~hzYSQf-uT?=w|4C#=Q*2PgfM}Puo2wpl_*?GL&jMq zN^G4%OpSaOSRQjkgaWduanNn`A-25b9$=4m%%S?uIRr}BEl->mH7`~-Z{;8l>R;LF z>P%pG)Hl4K|K_dgtDOm&$_R{Tp}y#dpy49e4~*Y}P=0<8g)s1EYdG*D+0 z)2M!n_!UkWdM+6JhcSy?`w8Dw`-+$VnM2N?IWY1Z&XGA7q$%LJBW*Q2XMe(}1d5k4 zpgDvYA$wQJc@OiVBlzhO&J(O(`sfl@K`utunVA|( z4%1+#43>Khdx+dy@Sr>|GOnmDdGGh~S>dNFi3cQC#22+os;P*!E0Fp8j8S2M0nZVS zY%>fF^53&jtt$HawD0@vE}#nm`fHvl;HU%JCYh+|vxF5elEzlEZ~^WxnVxIAiPmwi)EDV~3wH6X$qw9k4TfV=< zb?k?Fn{CBf`e`(XUf?lg6JhO#1jYJyHi9A0DbA+&ILRoPB*rI`3m(XKBp?xn4$(7- zcLYOsq&?@(U4TjxJ0y#Y;9I-)TRtOB5Xs;W)0ay)1-4~`vN!1-rWXn;y4yU|Z@PcC zARV@hJ3cXls8*M zl1$q{utVqreu|}FYV%sVb^0ZQHL{tO>ircJ^m;!Dzl4=`JHT(SnQ(Ws-NZrda#Fin zE}`O1whirCwQ#^>p=~kdS!>K6#ObSQ+iSO5hV2o}|EHP~kf43lnmHX*g4b0gZqdlg zLwJz;>m@=O8<&%dm<4XdekgurbmLP5)Xj)$`Si0o^05Wx5>ia)!cB|=c4a~);6ynT zh3sFaT388`PR* zP%fS)Z??(1h-e}`XeMg+f^Qy^##|PSQ(+v?JMtKA>V6y+etO|+1NN_Z6 zfvfxa#{)Y&myBma`u={iusmiKYGER~iGe!n9Xnvm!o01+9eo5IuGT-Rdot$aIQCu# zOxhTU9{n~gj2{Wpt48Tfhygfg0JxAm%>Xrb=kGUc-W~kvbkqS577}Fm-;4SULdD9b zyv1;UE4;;2fX)pR(18p^AaenJ>dl>NQ;SA9=5RdlRE!^RYu*r>TIyT!0stSjruKUQ zBpGF4`)OS&*wn7>eGaNHDS=u3``y8hPCGRb0g(bEWq1{qmBnRAJkoD~Vk7HXJfK|M z*Bz$*91{Mr{q1L7-EylNuqkLK=>Te*W)P+eYzxal++2PcT74UQa(lf&T+7+-`gLjt zWxuh9JFw3RO*%~hoInx+!)3Gp1jaHqp^_r<6$n%?h_3P;-apW;<>+^W_nk6UV|iyE zQ0+jf0;W5Rd6@LFJr7U?COyG6h%pbgCj3N)gk*FCAmrqh!JBo0%*@a9@6{p#$4G9c z5fCM^W%s=_f{8wb<(=<{@IygYl~v#!DtkD*sy59N{1kxXLRV zp~9JmR<7gSP6U}DuT|-wDYp~(ofJ~u9pVrVr7Uo`^I#0YwSizYN)+SVdB|6x>O}-m zR&{lDVngB)Ke7oXDXJuztvJnR1A`^o|-jyu*4xKK%4`+p=UFoGao;+US+$Rcr znK~4#Clac#{uQ~os>y7UCvRhj-k32;)$(()@4f0XRbO*MC7JALWJmCEU8_I+GP*vXU3xSod6SGWY|3hSoh7NLGZ& zpYN{AgPImeP&$3kbfDls+3DFqlpUx%&LgtA6V=NR*qX8r6L)Gcbw}EZ1nYz^ZNhi3 zoxHhp&RoIrN*D?<$WiaP@4}wl)@h9=I<_9Q>TktQU|#-99gofgsi3S>Ryl)5${NimvC6$b09sr@@(E6 zF$`q?>AsWo@**nb9Qd^}UF=P15(y za0m8ogCY89JHLCC6!dpO@5z8`K?)xf|J^I_QP;xhFDgjfpPJO@TdHP9SzD&u71YJA<&V*t+ylQQTJlN|QQ; zP5*m0w9dknG2nROg;+gf6dZK~b3FqW$F`0DtPOheM#=lJgg8DBl=vgBhukpYJW#73 z>iAfq-~I~x9heE`04)d(4-)CvxqFr5@vxD;tf^a@)C3nLXn-W(q=2#niHf)oc+tqq(|@iAYvcJR}`^8I!%iEX(7XSyOI zS?Bvt>0>h{H@as(bV$NGOQXC~#}Uo25zkIe_FY0a4B?+q1N@^fmWP9F*O1Ki&?U3G zxuIoeMS#VBK*k{ZssKF}`Tp~M;KtoFwc zzUq_4Cd()8kzVLUIZgpcBD9$RZ7*D{;EyOp?WUvxn#b8nJDfUhe{**Y;CFJNg&}MJ z&Mm%1^hjV>)-?FWEVt?9U`N5@Dbvmo(z+3eYZ+vSW zj0m0E>mi?~wqD45ZscC*yhRA%kOQevI#OzbPaO6Df|9F`qRQRrHRMDa#D6Q~ zm+$H4KdAo3tIffgWbHrx4r||j=h|Do|5iSG{S>#j8HuKrz2B8)>ajD49h5m#Odf;d zEPL{LCjwoN`a2yCNea>u{#GTyjBps3N)n7;erws=Vo1j!3RuSxd!}$jvLmA8=?#J4 z*@MeH%@$(8P@4n1xdKIC10|$bv!4=8cN4zVhD?SqkPwuC_4!dBqi#dMn6y=27i@~z zYQ&kK;Y$(;UMx2d-w=b}he{IhKI$_8+CLb_wvvM*v1?g3e%YXDih*QU*1cr8N2p)A zs1w)cBq=?@8%q}jk`y8GXK3jnZ;~QR{(N_79!?G3nCO9(U$1wVhuyZ0afHA;UM3mG zo(Kt<^OOwtD6L+lrBgYfqEx@E)BwwV;RS<7Ink@UFQB|X`eluNVGX{V>{U+Ul~bZ$ z`t=L_`0^JK;I)c+=mQu; z#SUfX(3dJ&l@+Iy7!a)WWv2``2@X_F!E+4_*E@Dh6QZTzB|uy<;&P?f^b~f~n$b{O zRCb5JL#rtWwPrN21>thaA;x)v*SuqYUf@{jAvlM4iat-mKt(Zz{UOk7SXNoFEU-(c zsX!$#FRp5GDoQn9i@|H5WM022L=#yZQ6!snv%b}WC zl?R0i=BGoIQ%0elmM7y41?!hIZ-2+rY-j*Rvt?TM60S2|5r{_t3%WO6Js4B8HG|=-sc}DIIIM4v zgdUP}29YD{2!YX+SS>HsaX?*$rcZ#a4p?s`Rt?8q$y<#`=loW#)EwZSr#ZV|74$dQkQP;miS1jz$9w} zgV637vSxtaw#mQUIq+Ltal6>oUBrm#k6{fE_U;?nI;&WmC9@+rnXUTg~ z->@+xIgkRpDi+`Hh=oBRM}};`8XVYVFItAC`{H_G^MoCna8mi&d^-M!d|=L&1V479x|lSUdI* zMRS1^4P2**I&cwUIN-ny(VIdAO23j%-b);~s3AozAgJBV9oX~#;q|oAn`$Xbvjm-4 zQ*TA-r{Fp++B84q356~t(Uv=O5mQB6r;{#uYmYVW7l5ijR4JrWCYP1AvuAFzla>Aj z_z9#{OCCDHQxiTUL9e*O4?(YlCuw`ux{PENw`CGfiYFrx8_G@R3ia!IaONLTm8LW9 zgfYUF^+g1zbEgl*z9^#FP{0$W8w1mgd?eQ*I#OQ7-wygr?O&bnE2B0aiB*$>=>a+x zAULz1Pk`(3d!&5>2}bms4y+OeBkPcd`*lcJf3$48*sq6K1;*<9g%#=-^>ZvLbnF0% zbUHU$sWVl(EjKW zSHu1Od?Y4kMr`)3f#Eb`4*juvmSq>Qe_XTo0H$?PkarM*P)ERsd;cPsF0vn&kCuHCape_}yzjddNjHLa!Nf(}-MowG?7=+s$Kc+!7 ztFSpF{D*sX2EljdS=0V(UG#!w&j-@{euUpXNO(fdamw1`!GP3-g=b;{Nn@7x9(j5M zDVtPHvBSOjg@MefFl~okRH=kUGz!{lH8diCNr6nO^f5qB@+&h&jNP#HgW%=Qs$-h8 zB!+hzBQEyGl7JoDu!|VACt+C9Ys{?0hCA|h zzT5r3=k4H^59?k}8dC;y9{Ek1K~nS`O>vU)c%sq7*jqs&x45epu(l}-al;}*PHZ+f z>BUXwEXQ}l=qRV4mwCsogE!@$P@NH9j%h4iR8B#`gI~03`?)2^f^p+Y2RRD{xO}<| zurEo0fyqS}at_$@Cv);XyKo!d-nkp*4q}@Qf>->cQZD$1H;>0BRtxiKYA!-{5&brO z2*QUQX|4R!c|Q@~wf92*enBxyNWxqV&IrJSmMyzWM`Tx1VQo$zb9Ks}8fXH?VeiUD z>_BK1iS~w$fYo^$$S2;A!r}MH-=w@(pI&+c<;LUtQlKAI9IL-&if3($57Qs zjHrg>uzG}wrH^`wmH1^b}#NsTux z*!rFv&Me~-B=unV_|I^FM1+_Il)$r-Z2AE8Ir~JQKpUX`9Y94n>a?{$V-@(xc}?_| z>T@+E(=++l(6nWnx*}mv{OKH?pGHuG07p~ zII0ZMm4$zzxu5NBi1pK>nkCgI6+;2`JLAki5FDK?tZ=7Gip8CJ%|DuCy$1PCgX9V~ z@j^f-MIT7UK$QgA-lV+k3G&77CP6=Dg;h{Mp~P6woi*@uHOy1F3ump!FsoW7N9%aX)vBtcbYn=`yBioJ9K%-ve`w4+Keuhfx_V#Rp+M>j zsBka5zpMG+p^6>D-m|Mv25Sa7r|oCI04^7!_?ynp71lFeDrePK3m-FhU=oyiIHgBBr%CDI zR36frr$psRP6yEIajD9%TlpG}>{rf72Xavn9V>+|u%k^_D<^ILwIj`ekJVftmxTa# zl89GF8i{!Qb=C|#KtsS|a@EU91xr$sQw=cczvbv+uhyOiO(i}9DMPfKTNSp^g;SK0 zN&}9U?a5Aw_pPa~OWzD&SbaMQ^A3(t#G1I)o=01=B;Lgh&2(1XR;F3H=@GVWi21A_%^4$|;!%YndIpnLQF@V1TFqhQqtTp@9kgvEHgUDB{LVT3S zS9~Y#8T6e1%)7ObPYt$~k=@yxpM(Gwe(IO}R748cVaQDVA~5wUeri{dI(Ya5oC@rd zkhCf2i`bTMEIh1B&pihofzdR8AWQR>W2^y`e}2KS|$KeN>TVt=~}e2uvlBI_6j^yrj;wI=L68#{!f7F5??5j z4$#oDoE!aWZ}99&cpBm*yxp(H(jZ=+EDgcmZ#$PELoqfheWq%oyj%`M;Y3%?fz8jR zTAg?j+;{?KMan8ffl{cZiL7l6kk06{D)OvJ6MYJrJfI^eMVDppNy0SOTo~+Vkt61^ z9z<~hg~BB?!$DTg0QN(cGC{h^2`_oaN&_aJ`-2GN@mf-MLdBQ0X$P(_6dun9kR+oX z#@BWRuc2t+ThClDnV9C+`UbEmPV9C)-z?FZ9J~p7$=0C6IdR}ttiqE_(mIr=Bis#h zz!?&V4zjb@LocYxw=t+Afy-Gvc?F)l1!WAB!vTMP8SttCPeuS^mS83uvt|hFmj$g` z$Z7k2bj@-2=M}i~78I$8W=W0+5<39P1%jZ!ogV!)P7VB~Utc@3Ly|2A?>Li|FC#p& zjPQ)CX(#Q|lgz`yl9|nZ^}<3ZY_WB9;FrRJVbzRh&myo&^>lU=C`-76op*9vHS)@( zZ@mJAFWFJTGpp;!q$1;pdfucVL%T~+N5Ta^Wy0gEm=~*PBr(sS&lq-i;}mb+BZP3V z3b0%qlkzfN+gE@dSjEomgknj^Ni1W$AQuUX@a8R$0XRY_bO2&SDbp6@H+Nm$p}JQNz^^7b|0a5hE1xACF&vzgS6zi9U1AW{4|B@yImlb zpTRi?O+Y^CpoT%BhZBZ1P=}6Goc^++=TZe2sBp5Hr|ql0URG}KB7)_JDrKIR!%oMk z=jBx1v_Cgc-V&8JIo<10A=%bDmY4V+=ZhT73!@mWVTb)eOxZ-+yTfM0dP)kw#E|gE zlm${XYo!0Fi30GupO}@T$N0WD2fL=iB=}V(t-C7Dq@69yO{#`x2;M zuC=>xIbg1#3}Of6dk~)wVm`_2Jj)K>@V9dnyndPAP|mCm2z4GL9@fJL@)_LYIB8Yt1Ie=(SZ9F?%z1dRO;P2LzQ$doh9!4f>p7J(rHUBpLqad z+g89`*9*<7%_1_dx!*bKlUk?X$<$2Do@Be?)6=mwRRO>&*xUXiQ! zGeF=g@=|ec1S}=3qUvlBQt$wDSes~g|=NO|_Y;ert19 zt!5|WV}Hj(K(eX6qubd7$ZUW=@19w?Z=$`ew86~Die`akJh^l75mM&{Ipp1a-2Uye zX202(SWC{fSee+k4LH$q?=E7P;Tv+z${K`TxTf!DCgrpmC{)Y}{tTm%H70lk@rJ}_ zB^`Y($GL@%zUfz^$BcNbAborDb3;MCD1uqt>@^MYh*d5J>P{mBT08ShY!EcNK zGf8~8hU5wOUfdr192MxLxZJFh5yYYGCVD}|1Ucil!Bgd$aEx8lFd^+ck<*D9bs+g?A{Q%a=ZM@8Q9D=UhKkxkksBszi}>X6 zt=%HWhPb-|E{b>2YUKBZINU>h7w@7_C)%q~pB(O04lNx^v#*n5@N2J&^15i>!4Dg# zauiaOP>+d~KCs=hI=`>BV8f~H&1+Dv40lK@Y0^Z3+ri9!pG1`oV$_^MY(iUX!Bh~& zNwZT)3b;E@)27+-MIZS){a@1MS>O>Lw>|hmKRMY2GJXj{!ZZdYfd`G6P%ss=oqVsg zSZR6vLkTw`8WQdSJ4_mZy!E;JxSeM!CcNpVz!wlc(Db!xf4oTBAv-KJAEKILMy6_w z0p>&N6n2F0@)9@cGt_rZGhiN&kWnl-qV)H+pXQmJuJ=vzssuX(shHPNlpTaR{S;sE%drY}+Ve;tY~a zvIIo610MZ6tTPqpOvjWa)uspQO$D0m?}kyYa^+cL+XqpRCo8^0CVlx0yjDo|c0GNo zOp-}2`eUj`kkAmFIAV-ggyIqQ)&pXUOT_Mrag&lN3NeP0J~`kkDtNvct0=}W5w)F2 ztQd7jTO>=YFp*(IXnBYX>z7*)TBjhS!rWaR7ljJ$2$Bg)GE8*AvZp;U>XR)V$gGT^ z>}z-fUqQ2;u4_>$QofQud$cSfha`9)4M>4UJCQ&HTC0bnJjug79PQEG>kE9~;TVru z5jX}+<36b_-#wKZ0wr4LzT$yfC_QjjwNE&w#?7P~AOZjOeslha&j+IR7u7MH$)jQZlk~{gt@=sE z>izqYJIvTTYPP*<>B|6)wjszwmr(mMuG|b@+7Fhr9v+I2N<-& ztPG*OJu?I8hyvsHOsmxMdz_U!Q5Y{S_pj!OcSrcl& zH#BA)@T-hhaR2VF;C&Y;&4yS-x`Ud zjC}l)>HfeeqwWJ7{RAl+8MOh+WZeb|{)T_vg!XA@$FeCR27ILmG6!G z~B%;m!=KJI3m&l*U@dIRs?&?Cc06D<7+|RVSYOhSzHNeOFOe<6Se|KrcQ{ zc#~$?Q&jqzJ^&p!XPf9Ys_RYZ`z;>a*Sz?%zEOF9np=ABJJEB&u<+8ta?T`F;BxhG zV?mQ?ajN{uiUxK1ulpX-vEsXvRclJ|v5CgCe2?8cv_ikqTo;G3_AmIKR`T(R)A#BXR8B?qTiMz7S{)Ouj{8X)EZg?q_p-7*Had&+pDIE&(dU|2s%KI9r+9@SQ zFnyWYlaU2&o>ecQ2+vzyYi$12P4G6{_mNjgMXQxh*@h=QdY9$D8k?s_AAsp!Es>et zXuauIRaNuBigjzJRjXRk6n+yvit@)bCWYUT)TrTKsaW^)v`wm(yA}DPz!z1G!6yk{ z+)Mc4)s^52GQF;s`c``DhNB`}lsNX*2kRFb&*Hv@2fIGNY`fQyKez11pC>;hbLsle zKFdOB;_RF#uV}z2WN}D?i>G1QgeO=UvQfb%5H&uHtN{-$DgUA6bBQcc9<-0#A(#!F zsqDYto|1WEQ1Kw15{(<8sC&@|L91gG~aS7H=^$G zF?Hk4R*nPA-r5mt2k^V05m!ar6mk0YxTNAoJ5u*M7wBIPe|% zytP~Dgz09ahrabqy2%X*FjG- z?a#=5I7*++j7HVj_Vv*gU2Lei)1r>gUnw37-JHgw(bTYy*>qlq(tw%CV5`5wamE>g z9}EJUsC`i1rf*%gGqv^3aGEMK;wK|!JnpT#^^=z2jP^XRqZ@&u*cio0KIhMyy=jn0 z?R-%jDojMwgm6EhqpdxpX>Vj7=4M5^wAs%9DWrey*z*JdM@zu@H6{d{3diYkMyyBU zcIo7fz^@1{k21JCto$6KHwZR$`kNYlPMvizQ!%w>%|ouu&Nsg4&?eO1r)yo@)RE-h z&@?{%m#7SF|3@We+pvE}V8hi#x-AcV*O;q~v_A=Dqxjce9SBsN-F65JXwLSG_L)&@ zJ8b3lSPr*cXVb*@qRai6$D`m&YH4sHAr8z0tRSowT^6Beh$D#+3(3mq};Nd@SCJc!s%4qTTV;yHSC- zOAEda>$_BaLR+LljzwYPD|N|&U2oF}t(O*8dXqi+d(OMCK8;Y9b(8orJg}VYOSTP7 z6q%)KaUIswG7^)g*Pi*&b=T2Yc^Yu$#tVHK{9N#Q#u+Ofhs*ekppd`PZ5haa#`LmJ zevGM!6VE(K2O>Rd&fLvjBi>&94O~0o&oE~?C$g}F8+hc*aeAa%*WMf*xI6Vmy1Tt8 z`bc~ie{x~BwtalGu!Q+D6l#PS{j}vo6!STxMklW`MGC&@&hQGpeScLfGYdi=j+%W3 z$(`LgbM2mgUFloDsS*Zkw#fF1=-ZDaE&olM4jgi_&@o&Au99W>go&#qXhvQpr=B$NhT}gopM{348g4^xtBCXg(6)h6PDS)b1 z1<81M-6D9$p%jZhZ>)-gKl9CxJ$uL5G~;}F6&yh}Jz6S)!s@N+S73L`g1L=~Z7J1T zk&HUhnTgn{8z4VoKqV233=!fmv(VEcEvGZpWU^D|8xVS?F7TiRgnWug+{VhU2Agx9@q5{bsHOUt0gQ zav0gz;tLpEqP?e{l2`AG|Eid;?2HQEM7c&Btx3EvHCi{57h0k@xqQpBQDI?}fqZU! zwD2G^9rtfzBcYY@TUxYm?{&Y4V|v`Qwr+hFqKB7B?degk#OR7X8-$MV^lw+Yv^c*Q zLXkxQaNW8U%b6ji+uOr{HsQ z!GF02@1c9LKSc*`DZG8py#yR|u;~jGGSCne8|BZrcTdmPQK@r#p!6yTnez$=e5go) z9p>0vLWLbk#;b>n*W}8;Om}spwk{5)sphSvcofJ%-ny}8NzilLfN79n4XR%iwi~a9 z+%)$_nujL)t*ekfh!Jyc?RMN#FLc8oTLqcp?faAFKjuyKKuBE_d*<*}`Y?aSnS)o& zTCt3sW~q7mo;+FviFu*lusKQ(Zx0w~;#q9skMyssZWQ10el+LaRXzWX60BFovvs^i zJOe>iqVV=_lGZNm(BBq^rNnC{t>r7nf|b{e`w0JX*1GM1N#ENwTZUfoPLG711k@Lo z!RJl#YJ&~(DpA|9(Zyvb`}LELu!GJ@J&GN=G&Vu-`xm%xe;LNEx~xPyVwJ_zsr#3R z?>n;|ZBZjvQ4~FX6|Ok5mgFA(TA8=l|8jO`HM<)iNEzD=;_DJ`&Ad$p|{p!Jj1YQc4K7TI7J9dj1e|1R~JY=%&x zXnL^yC{u@Ec!g;aL{>dFk2Y3H-5z)mg7}u#E)yDkp`a0GUG@_88%ealW5QsV2DI_U zlq;2=M7dnZ8nHP9s4gSSU7}{iqnl9`m8LN>HVr*#6K7ix9`E?|OW@~(WXfQNz!1P} z9-MpdDtSAc;CCYk_cYmb;H6711(wr{)?r3_&M4OG-weF7;nBHy#>Mx01#so# zjL+$5?RJu4Y5Aupz}z|$?~SDgRMDF0{9VP_0_?3*|I2S%*>4S1Z0$;6N~|4nwh-Ss z4$w@DR#lKr*{4CF6;Yh~>Q$wRTR%v%Q)vEsUkcRF{C`gK?^EWVQ~yMcx4o{27fuk= zxmU2B*9X?L@}AgUE&&jY=Qy^Rq-*8e$+t*sLI3EHAp~=2rQDMNSbRduCYT;(357zOzJeAD-Hx8mBF zxM<-JhP~iX{o2{8m-dt(G2`$%XgdX)laed%J9u@)iUnW&_LT4enBMZ20urs#LaRKa ztdipjJXh{W#{a+%QzYf_06C)Z_)SZFhYnH4wuI~jA5%y##`_hG zM>@b$q~GpAFy>kDey1SX+Doar}6h-&)t8G)>L+AjOnR3wLBFHR_*geAu}uTE%R&Ti#(ez;GQ4~04|~wb z1+`1iGcc7yxB9xI2a?E+B%qOCt#xRiB*lHx2if<={VsTyiYO0d-EEm;T!ofvTs#UMpm zXHr}+DRKXYt#7zA;Utj-Ef!(Fn-@fb(=>Tz1S6<(Zt&1h_~S zwgr}w$d139k-&&bTog4qsWdO=a4ui-)m$Do>gMt-zX$Bn0F|be%#ZNDZ_?F*buNf}1)yJKDCveZUZlNPSk~eD2hww3pT-%2m;*9e-${IOy*T?R=fCFBQ zF*Q|;LoAI$T+`rlBx2ix!?{}Qw@ZZ&Xnz_s;%h24o_$s0tGjbo(4|?us;~{NW+6C| zP~aJKX5@ea;k=uD?x8>eG>-UiMQ2lJF>mwp*m9elgW#xqxGN5OZx^ulEN$gx5HEjK zhHp4654|GM9uoSen0{eR(wZcALJ+B8jThqz)~@ndhqj@pxo@P6_B9Uorv_8G)_)-6 zW;n+}YQ`U;xI;gr7-;@?;f)1h4fy|6#1t)lJ-C9YvtuO(QubBp!u0snt z0I5!!uYnBFtYrvc?%=OM2#ciq|A7%j@a|6pHUL-5Jg{M%8o?Mq2IgrfD&0$Ann9;V z`qx#=y2feN$_9<>!d8QoNx$3{5C{hZSXs1@z!J>GbcxKhqF7lR6*a=n=xB}N*Zn)| zXC(VO_;m-G?Yj*i8OmTOL=An=BJyx^?j!WjoLavbAqvp_E^Xv% z4cz#r5^4>qNl$4j;d+9>+R53RD%dzGSdT)k`PHpKzX(AOvDJzReuJ>?KsPV;X6Joe zFIcKMTeYfmOos7`@2GSsGvrAn+X6>P`Z;oykeTXem@Z--ZjMyrj0H9~XMOSNsm7#- z%A1r7MX}e2@&zwk6@|rFZT!47x2+6r?Gh0kjB>i8-b^Ag#_vy>m!8-yw96lRd9zBk zYg&k|Nz%5!E_&Ba_OAEnU0)p%>V_eF#;ltqkEX~mj*CX4SC~Gz;PA?;h?6-5C6AKlvYXt1f-Dv+NB zR)$mF2->eK4eK7h2uQVnuvKufmg}`J$Q6HJ9%3`7Y}H)#a;-#;$*`;zKOhsmSq%PJ+57V0EJ3Zq&5w(c75m1?YMC>PbtG+;v6v&9vq#tm-xo7}CTR&<3(N^HkfbAL>$#JhL z_D}FK5y1(N9wKbovwa}OrcL)My5Ycl8L+1yu_`6cVCaWh!62f z9b|++6fWFpt3j_ACB%!?(99M7@gGQ{MRAcLHAP11&o%!77HH#}h{i|i&yO$%9Jfej zpz!N(H??j+eX`+^-i*F>&1VWzA$t{?#rQquT-ZKL6o zr+Ix8R(uTRGF|>3^T2(l@aT~pKCqcl#$iy z^F8;CczU&$N(MBo$ZFjceD0f&S2P*w%+N4TqM!MV7ed~6SzVkUW4E`OT-~QBZH4TJ1+j z19c!U?FaUSic*>{MMJI|q)R)X%kkntS?=sHBQKrjxBN@NIl<@F%#ECbY_4A(2*z`( z(^Ft2tG_6nWsjIf;Sqs+3qiys8o187d2M5T6}QUBOLt};(UWkU!ApCVpIY+tg6j;SsjA@qXJQmTVk*BMqjXU~rY#^qkz<upMU}_7hcRc&*PTuK;}Wc! zPs2rvsqVQPEm&j?d>Rq&DxKs9qabMP_f#Ro6CHA~g@6I=U8qRk{5m#{7qU4YgZtWr z3sXs{Xf&vL$0I-nCmPv#Iwr z+*&W-a%~Q-#ZzHi#C2i4T6u;_y6-y3Va<+nTLN1nE^X;+NP8kn*MnH2WBLw4RO}3M zIgTypuo4uJemy#4WG2hUu5Ba!;hA+HB*ihUzHQQU=+Uf^N1-lhNUv3kL!tIZ*NLW0SM+Vr?+*w2TK=Xr@F2T@}q9)UQXV=9P>_Ei+*d$&tKbW1imv7{d&3>RU!0}jib zbY2)AQqGBE*lC3xxF5yayaM5G8QuuMK_{bEeSVd_>R!---Zk$RE}z^j>sR^gZ6`fu0k3tkV@_vW%lbVb9IO_+6X&$>_=o;_svG4}7uvUAkuciiS~4l|*H|29fq`fk0yog}t8C$_ z>0yJ)_^Ad}iIH-)qex^2*EDMG<53}PZ*3$mr%Hdo5tP~#d!sDlAT0GrP@ zq0l6m>TW~d$Iig3QI`2g`@c{wwbe!AtVL_2~&QJYbfs6-SEzh?C5kR(ZN7!$` z9>Fh2ecWey@tDWliFAL&g`gX^GC%d49x6~YFu!@xB3)qLA?BDUS%>+l`{$Q^?ff9C zHEa%)?D6UWKLC=^c8c8q%&;EJ9AcaF-b;7IdwCFec5H{?#h{pAweoC*r}xt+oEKjx z3XI1pP39dFhBY62$&aVZN>oZR9u)NvVyoTyc1P@-pjISagMDmx{}kmdFRgVa*6W+^ z+zfzS%b#=7lZ~B8!2@T-F`^vW%C}77T5Q<1K7SL2JaMdH^GkUDz8m?L=1q(U^+AKGPk7+8I|;RrPfJO%L4^_;;IhH$q>yh~K)*Q{ zFSgDXm;2=mxjM)!_s``~*A-PUYUqCELq>BUoB>Z)36#%4JOA`2&@dSX@?wjpS9 znt^dF?qhhjwq*o|ue8~w7g}H~;AO`M*P~@-rCa2L|014+O%H0+Xq4#{FikKk!eW zPH-9=D*f|>jPcfsfwiv<${0%Ut&`!Pvqt6Qd5C~j8c;dMtuL*stuu^j?%UJN7rBD^ zeCDHt+=1voueKjeb79HWqriuTu`PDk*?}XigPlz);hp35Qw^J6RM=`gwhY`GvNrK= z;IMndOQE9S%`?6axsqbkIP4c`&FO%*7xWniQA|MYA>L%uEPv&Bz~Pf##T(cwc422A znX;1vD99=0lt`CSf#_XX+e)FmIkB^diGzh0z@6oaD8V;*5Wd&Ubr|g*^nrS-(#}z&tLq3 zY&>e+Vvj*(@n0~F8t)wy69h3v$xTaEcjCr~vF>`w)iBVgi`CX_Q$|j{J4F zB5nP(k6IBH`}NxgV*Y5L6`9x{9yNP*1jPQsxV6YYj7(p5JvwZy>R ze@L#NRDiVdo``{Fk)I$z^? zM=hqI2bIsRs>?~ON8t>yHU|Jf$8UfH1=%n`ByqEC?$&01b(JuZ;f&+-ra;%LKfpqu z8WzG%{ap|$NXX{7-sKD(5hV{g<^DT(UB(zcqEi@d@+ES)Mk@UQR+8RvU{m1F|L@12 z{Dbig!wKun|2ckhcoU}T)q@oF3)14Kb@9y;Xn>|MFsXnMP8*KoWJ2+|AF-9wyq@0_ z_~olVq*aa^w$W%>n1>mkjA=w%XXeA-_zUM06ct#?HGmEn!E{Qh#i{%OFE0G!rogOM zi_|#PjE3}q*r++{w_9(6&>Vzzemnu})O#*?APPq*QMWS96B<#|n{M+PY!I&ukhtY( zDzkoaCMYavo;=5Fv2NOvky3%#I#T6QNvgkhsiC(x8aItZc1Qgn9zPPFlWs6B*83DT zyLu}RXIIaSoOFC^$(0W3iqw~<0iGc(>w|b4yAJ5feR;%$hM)~?o7N6iQ5JlMZ>;(X z`woV26#AgkE7?)*j1Nj&L@2RkJqr#=-t<_E5@iy}l$WWas|uHVuMqxT!WFd2AtT4N zJPmXkGWFYk^RrqH4(q0RHH!V?$SCT8>CGp!g=|9Ourl%0&!zN4}Ut9zf%zleKnRT}bB;gc*ph4ZLn zO0%)dSVccYB^(*CDe%$%U5g`nynBG3LBP8!-mzrsE92^njZ(&I-9nKw$Wtm2I2QYe z`dIWut9&7Ay~qd41)vR-e{3Y`Q=v;W)o;j!3quXh4xUuLi=zgvP?I}$2m0~Sa6&Df zhiB3xV-0NHNG_491VtDfm_Nf8Y2n`-A9q1R&&c)f=MfsO1xDdSM^G1+CxG7%W>zc`*a;b{tLjM<5j`l``1XYmk&WQ zNSm}jsr3XBmf-S)c!WuUxR?d!(Po8VO0GP{bhs$!4zk^)66Y zrx~>m$od3%t4)&QK5LCAY&wEFk!nmC$Qbr@HfW52iw6Z@mV~Z?Kg26H=h)PRVJk?}V#}pP)7eJK5j$RXR^C}- z&%(Ka)BE!-@-Zb zg`Ca;!OC%4E=Cbo3mfv>N6tDiC%);BzX+&iZ#o6|7pjZ zhEa<&HL+hJJ91xqP|iLT&#lWNC&=AqvVROpTlDp&!LKkb#%L0{oyO!wb~YeWH}Zn@ z#Sb9mK%8#e_k}ppu5tV+yl~ghm;`Ma1=}9}G^BPR%ZbwVkUvdUhn)HPoK7>z*3^HX zOAkdE(lzRw!ElPQe27fUASs`ghg8(-1n@}`fbB@ ziV=X@YCKGHkIC`_bKk=`zT5~jaAsexkGiqxe9LHr9fu={%T!*=;{k-)8-|FpJ&rh! zVW`Iu@AWKmdwt6qJccxnBgJD#_c)9mew@d8i-#ZYvHr-z7kR7&9)5zyTIk`6Jywf{ zpXjlU@$e-c>sSweo5y;q$8fX9F~VcW@Hk8!-sZ6upP6|!97%aUAkNOFPv+pBjEG-5 zw;G>Ei?f4!vd_#otI#Hb5v>SyDkz-(<}UT21Rx z#F3u;Uo4#_lO= z;pKaCw189P)`v;OiZ`uUy?b77CzL?shU^zdhIY+D29!rzVj8tHZ7KxYd#@90UpauH z9(86lHRFZstE(Rc8i7Wn3CtLL@&H;XJGCoMR^S}s3`1rU3C(#9Dkl&}Jcyald~sz^ zX8ZNVKxy|iGTR}n94ry5_<_tOy}zY*E#imExfU{yAl>*R#Gsz)_C=WYft*^FqxF0FCB6f@esKVw9N~@ z4IRfR;wA=Q`SX;OhIy6rt1V(#fj6Uwhv~|4B;J#m7q+TK?ZGn&(L(jO!FNpk`?q%- zSL!`ruN_S%Nk6OfFVa{qyZ~(mw3)mhCf75XrRk}mBAs#hkjh&C7P7clz~+QeTxB7+ z65>>829vBPaD+HAR&QvIf5FrmzmHehwGeDXeWU;DiIKHO#m^zdEuS6Ma?9@vSNv&& z_iXCWwL6=pF4&Q)pEv3Z;plz(wSRW{zh0f4fN<}%Pu8qKfr805)RzCz$*VBbr!%a@ zTjsTA$-v+oxY*{vAY(=O8K+f+BA{$}W?=ZH7KmcFEX!X2<-q%~pHjs}JE9w4kU`vL zBM$SPSEGktL-11!BzJ?h&cgry2jm9)2__RyKFEVFp0XuPc2rd~3W!*PXSuQb_J*`A zVnQ1X#LR>|u1o(x0y8CU2?BI&3HK3k-{l5z-|5cZ_)NmSwS3QQs?aOEAaSO<-d)QJ zKURfq8&`)99!}gCDlyc}=PU2v>K5}olaQPLi^|I?PCUC1zaQro?&d4EsZ6<{@qA@9 z*Rn-rI*$iT?=CFnE0?NFtMPBk=c<+$RQV>nr{&kGP)UO6YkKw`m9SpLi*+ z)%0(+N(iX9DHx)9%E^7je9w5UB%hx1aiNmb{C)J?VR~oFSuX!we5=%{TAoyuwBnx1 zNw_DWWFFn~m`eB)#-YzW1>BSn{X32mmaDkgOX+u+3yn{jJsbn!*4eqC9gAkqY|(JD zX<|JQRipoB_)z%^)$Gv1biVRo6?$pg1XX@G_sMv(juG@MAr5NB3t~K6u<#i+?wKAv zygDjuh4ih;kK{gSh~1YP78Jt~f@`GSYwov454T2zkV+OfV2WH`S}Uk(d-lM7zkM9v z6M&(Vw`tDgqVM;!DhP)Ix56KI_j~!^{{cA3&JNLvMZXz$yQt zRj*81qz!6HJm`eJH}AKq#$-cyZ^dtu#PPqC8qK%gxpz&&<3|tv^Wxq_jDn};)4V^! z%Uy8++kU3$tZ86Pp`eopyc7A-{-zoy3~e}nRT@|FtURZt!daztWz8yfjkTB0s+wG5 zow?Z#;e?FyZ4K6k-gm{pXWx^5dj#>?pCj%AL0IN)X!*ZcxA^TH2>SrN}ze%f@uo%&wz_lfOg5ErYIL5 zDol;qrYVDBW=B_LIZRqSs+O~DDDxvU0Pd>%)49WW;l}^5 zYjD6M8yHUBhCS?#ud7j$4WzDk2!7d{#eOMaxImKgE_|wt2mQggCIgMD`)}g{``9BL zR%Qt`F*+n`F1H5FfQ>AN^G99#d(y!8Tk}Wtlu@DyjW5&q|03M{A+{015PJ5HPa+M7 zrVbGlcy*&~jjTD>*03&2*c=D!B%d#jeT4hh95;Zkm`^x19~?6_U{KPq8PkkVjA!s% z;N0Yd`IdudHjBxy1JaU)iC%lKa6{$m*W5rO0{!<1Lunhti&#$O%Rg8SW`@D?$Kzhi z0Y_-zh@p-A<<_MPYjVTD0rKPR-c=i{qBOlSwnL<+09{)31kPY9=+Q!8eZ^RrR;mfWYEhybs4W)^AX zz$X--IV`4ccUUc%-Uv$9kU}mz#?>BG*9w~I?HTaP*G^hhJLyR(-gCE|6lo^tr%)|W z4Oh9C$(d>q(S4gYZ(Y)|?<(f4s`HEfl;S*~3%%DOZf1@N{(k*|Y8{U~2LZOslSesWMhu1Nd&7I0Ckvo>iC|=s}~7H|7ov;`|X8=(&|Z zE2b+%5N{K8k%OmSTf780*S!nF2TyHYyu`Re6W*K0NZl?~IN5-Ln!A$3iMyo6+}lC$ z)->F?_gXr4@&Hb#++dN(Svg{NBsrzS+NUXjyOQ=p;z0fQeT@2%pOWTzE%}Sl6Vz1H zlq;mKiV;Dx&}~+YBL(JhrRXA^p9B}qkCL+?m-8(oN=iAM*UKJZf!pK% z{_vUa0ZK(|rMxk+W8HK@v16e}?H@O=;uPfLrXUw>;pMMFN30Ni3cuZ?aI~oz3tWg8 zXVu4U#@rpM9-F2V{*)rMzx_3oO&8yoTAqQj!9j=0W~C^56$VpYn1I^#kg*}>xK$^} zZOU^n9oq#G=E_U0zuW*TXcpq%ND6#Hle2ud=m}Z0#!qxT2(4u@pk*ct8uDraTYBJi zAWsjd*nqcCyM`w8{L`4LUl;7^SeM4`bUJu z>D?Ejp=zoh*xa${p*ag4P}S=@RIK1u3XC~on&+t6XV-hR55o8m6J}v}q41k4uRPGE z4J_j@d=bAOwF~8esW>QfOmGsLX+TeBYi(Hl9%S@W+mo90 z8}8$G=h{)ng4t@8CG8@?-kUT!-t=adey1vTLYk>nksnvNrj& zs@7EFEa9sO^E^jYy~}+1HO4f7R0({_Nt+2IC31}>YARPe8i?%PVH@>B+Zz-u>|76a zLl^>c93)Hx7Hr%miJQV&AOZdO27c_(a{03{a=usz+v|D!pv)6L(dm40xZ+RwV+T;& ztF@-RM+zXbEOn__0W7j=hb9a)`Enut-vMvX4G_P%{0*zqb@}hDPIp(1A=S*KWv3ZF zUczQ#@mioW%EGL4oa@4l_Gzr=M*@e%uM%t!cqffB%J!$sT2lhsNKA&r#A8UNRjxgT zUS@QyhfGy{pcnoH$_^l)RXW=B$~hA%aH*C~G@*Nfoj)|hmbC=iplpb(gbXN^u(gK! ze|#DjNNL`roO`r3vGW)qi(aGrg5Am|{S5k>bgW~5Bv3FW^tXGyJG_06CMfivz-w(d zbo`Vnsb*5Wfy}fIEU3jq=V)rnOWnmCi25H{Mt<%%SYnuy8y1*iUMS^q(tm2~yunm4 zGks`}3IuMgXb6R?MES-Gjhcy$XS$l^EXX(24bMXHtM%~bFze)AvQCQYT0eo*$wZIF zay1gRvj{dwpAzKE$4nCeAtn?1z+WeSCM~Ct+OXfqHgEeD^YA4nf57V=n1{A+IV0WG zpJ;uE*^675Kc#wywgb_pcLYx$4?^k^Mye3Ga9m}~gN|@FC>5|vOt)!1LvMuEdog5{;~3}eLL^vs|Ef8P`|pmL%VgvXeT zNHnP2Vb{S!FfgVyuM5M%Hb7QGbl^a-YY6P*h!lGZGrIs31OWli{s#vd%#*$^kmEd5}P%+`-pn1jmsffonI z3F8kA9oy69heOPkWYrz_7m+Qgw2TF&_S=&Fc`0=KN6kxiAt>Hkgu%e`cutW6*3F+H zXLvKDlN(`EQs@^el{|ni&2wX8UwHSwj(v!Y{c|?9`9H?C(b#YN_pu?Hz>as~UBn<{ znElOnhRpCw#sm_@2DTkzYv2p9-K&T+OrF6rhx(tn{Xd`C(Em(L|1KI^oYWgz>vPOzkbTH| z1-l^Z%GlhJZ_d}4T(F07(kQxS!L|Gj;WE2Q{$e@+a%T~D8 zJXRcB4^Wi2J2^lVxuC^##k3Julm(1U@0a5m{`78v-Fgb8>1HA#B)Xnr5@J?7m<$t5 zPfjYPBury`9E(@sW*=X=c8)ie{0T80ei+0uq2|%W+R0yFNlh8ab@H$#8GlPnk0#fd zM}W>vzSyJT>MV(L*%D8ei!^lki>ie1!ak~W0?6AK(M(1wBG!V$TaWSsSh!gYWddi(BTooUPZdqL zBqtlX<3k3KQG-6MMb5#o?0=`5YYwef&Xna{2<&vGDq?4f#olV0Z@@(FM379E)-%1_ zV}R)GnO*@#=_zjo37N7V#G{E>FXiWk$_`%iV9TXntS2GHFhq8!ByJ<5X6!%hG*sK= zv3K{-elvNndDy!o4^}7D*c+Ct$B|{0*fyP~9A)e&&H_yCfz|0&_!*3ghvpO~!(Mxh z{q`1)va?Bq-7X`p41@}QkQg+5pY$Qjn8Y+b!n+|BA{IyGn_i9(8sGE^Sap5nt>9+C zxTvv4(}7y;r}GK|n_pj(BvOpiP{b=o{7vC1?m%5_jS3{cwnk0#9#Kx9@u^#y^}stn*dQhLKJ*1#06iI85Xsx=kH}cz-aL7FiWGd|&b?lKjmnoyjf=6Uk!vK6 z`SzGv2_+M_;pM~0Da?v*gkM0<)eC`#UT1BMm<HJNI+pOYht2E1JK=W~-Db=6} z4U6x$qS@vX`=PBRn=|ykXWv1bb3@{KggV>MvLhF%n*9o(zHspup=rEu3ul4mzc&xf zOf2Q47KHq3N-Wb;3V-ziX6FK@_9P>8i~`_Omr2fSSpWKUVl6^^=B!vyT_bpb@ck=@ zL+G)dTciuz@j8ra-CDK=9V#YL(L`5rBN7s6CkN->Kl#Zuc8JJ_b>|R3=hU8C zH@8Rw$_;6(OF(JE^Pt}}y%dhaYn?n#@3rEy%4t6n`!upzx!_d^OU?AEBbrjQ%5PFMN+IBJ2X9XLwA~senZRxx-fFrsG?-P_JAx>?n z$3JJF>4Q@R^5(=AtFVn8IFAs4Jg|3+wgTwxmybb@Xymz?O1p*`rK}Bk*aYUf_aNp4 zC2ZGtlaNdmnt&qR6pk13jXlVOy&$g&`!BEjV7B zVa@i=K6R;APZ@-dmD~%7W)ScFm#njo5!L27uvNy^z|@)#Jl}u*75Q%*8)sZ60E%%S z>pWKSvmcC8Sal5a)W&n5r$y?9-OtluFDpe9$u)w4-kNnWG@T3}sGpPrhY-X}b(!_% zPRkJwRixaM(>N*6vxc;?nA!sb17OU_2nbOWRMR;4?0piP|OxbXvnn zEkvpb5=|J7SU3Or2R?|I%F1RI(fzRm5;{c)8vbAp3;2upi_l_74SzghZDCAPnKi|A z;2yO#%$N_Z!QgF8I)@-g<(B%lOz6{a#y1yUr#i;{T7^!?IU?yYI@!(y|Q6@6^|lS)wAO}DDZIS zfn|X;D?e`dwi%%VNZIdzghkP0mqil`KMWp&U#R9>!+z`Os(Zg_o;~xSXu(6T6kM#D z9j>~sZKbd3$8C;>ep}F3^%HNPVSm(9HOK3IXi-69O@2f7(Ju8vb$(>Zxko?W_^ujK zgmRpMlbqKC7CjATfT9wy+G;Fr$|k-Kn8E1Fj5?q$kCi+PqleVGf#Sd?`gBPPFa(5eg4G7PI$pdm?zvo;LKhA?hRzkD7f=~`LrYcS&bZhh*wDxL#KTj}OW{JigM-is?2N>nu};_k+ta)2rhDSf z)$*!!MWUvGCuUR~FB8&(##?H6bqSyQR1Rq>r_Gv@_n{+W7tG*{ zijgvAah);|xf!N&${mj#(xX-l7?lq%)t|ABpqK7jGXqK0^wPLGV-GX*r84tMiP)Pq>nUJJNsS^#5`u{PvYx%QOxvwfX-r z>8T_emj8T$Sqrg9Mgb*+;1z!IoEXo9gQ8#Usr&lydr_#x{r9Hb(iYS)SlGx32Py%x>D5(IrrvD(r2VD(HH?^2u%5{Yfl-11;L9AV(Y0 zl36_$bYo**$wsGbdk>#$HLhIaa2G68u0i(OMJ|gT?3{u-%|HbzIAzC~3*ZRzJuDI*%LKHkYE1Z8#W-KX`ANjJ^ZeK!58Y{%)~L!Ybx&pQ45snxfaQPS8{ zo83{DqP=h;sqavtV=k=B3xFvQ8Ym5OB#^?Z6%n!p;b|bf7Tt@Qv)AVa(IQJW;ZL>DmknEO2tpuyQH01M~$X9U5ng_;SRb ziTAc3ZdlehnoS+8eXt|4WBVyxht{LV?Uqcmb`oC(Rabl>j3+Z0(mLu0d{d>9{Pm>Y zbg4=7sI*$w1Wj+)5jR103Nb765|8+3G1Z~Iz@?XR-hil?si*vxDcMt9iIe_(bN&=D zYoGoR>AO&$V8z_v+(kKcOyDkU3)Qp(zA5zCijRnlhcpW%<`9$_9=Z!tX|zyfoV);a z#mVcOq|@k~R-KcNb6WLIgVyQLIt_x;f$KwM{syOYsBFDKItAMqJJDpuQqr6W|C%2N z{{NxZ91cZzNSS@Sl59eH%_!_I;X~8QQL2;Xo=M{@60E2Duz{2eRN)6~!H&RHpAbwv z9iI&J{$>h~* zCwO>@WMRsz)d#H@%-22*J8hPIt}Fr;0t~T9m@A8_h4q{4V~juE6&!F7De-;#z69f8 zaWyeIgb7+JX34@F468$28jSe6^@?G^a+8q3&EB;- zJv}r*S7OLb&+CCu=C999pCJ1m$W6b4_QlL!!-u3B=mg2fkxwEG2@Mh!)9;uBScw>3 zNylzEA&`Ao6AD9*0rByegE%Yn>?Y`x(p4BiW%)g}xeCa+^VtmMQcD0!vh(cR5IHgJ z4ULTl^WN=1E>2GZH)Y$T^mv=Uc2c@#%A=Fk-hBQ1&aP*~3{~3>7(YNDg~1UfO)=u%b)?l+>t4Bil=*+H2wXM7-(1GyKxxcI1k8O%~C+opEn-nZh_J!WqU2FG4LNUBrEvWW|TcT{7tlE-D+P( zM6Eh}DeCj5Q%E+CkZg_D05qmR?DN=F)J1OFd^(QH#q~6>?h)R7xDFQHT90}8sp66} zClL4u1$MT4a0zt^{~3+V;m7peW=@)Y7;*BY_127P7=F6=M(v#Hvp4zFDwB7GWQ7ph zu+N`cWH2pSYTRY7MS|+3v-uuG)z0EL-N$^-OnCZl$VK5c$e0FRn9h0hi91k#-2t7vX?+q* zv10NrYiTFdrr2pUev$$Kuh6)Dk}nBf0wSjQ8(HTo!9gWNyHHi_F_b`{YY=0naI%^| z9KU|V){Y^ERHyS&y5g3(*Ers@!v1sI>UG~Xq|H&6X9|o6>{)ZEBmVIJMbFJg^;F4Nb%Kx~lZZ{Q+zb7YmGN;?9het zZVkS9X_-6X)<8%0x~XeS8fr%Dx9(_5royKXU;OVaLFs!cT|ul3S(rnhrP4(dKgWCI zV=B~KG8%O9F&+g(j2^+Pi=?DkQjjJyxm#1v`x+t$aUZ*iONb!sCT2)99add`iyu~- zSL9Iy{0a3vGl96Q$XEkEW$6D{J_@%Z>O7aEfgJaAbY7TWq_ z;blZ-tiolXiOXL?|31NqN5(_-*v7TEIBxc*c)GF+Pp6hFT!@b&xsp}m(`T1VqkCRp zywu{Kg9j^DapQL*C>TAo-1yqFh7+DA7Ol9T&E0V=f1zx>b|mIib!*l**fK2sKa5YK zdqMn(%k?b761bcRyzu91ZpN)e2#>ylS&s}I)`-z~{5QDR9p7J1!dCJ^&r;=W@`cLB zVq-iCr6o|-%{sgyj8+K_^;!`}sf5xlYD6fluCYeFNZYMJD6T&b5|b7Z(;~G;qJEnQ z+HcHFBj*`i>%u)>;uD(5^geHgs6<65j)G~}gt8*F&4#2qs^|h&pzP-`J-KpbU*WTrwDNWEia76qcNOH!F^^eI>B2gbPFL|_>Sl;4Z#R+V08s-sO>P4t#Jb{ znE!K)Co4_3=%RjqC^;0?(%WfvvfSM>bl`SWN@rJN$YR`StxO*Hk--CjCIGK($`#xv z%lK~-*~5VI5MBqdDmL_HD$?2mPx61RJ0>H!8~%b^7P}yQ_ZAGW&{8t8{TMbTTxhND zoev$o+xp(~Ug(~vUNj0?Urt^T{9VguKn)s^EnTso#oUr2A+YfkX2Ud@`ur6BimIdN zkgk-fvlxbt7}G<*K@yO2IFo8T02cV?O2=Pt*6ZV>lW&zmfX<=!(^-LdEWk`|+V@~w zXuJ|*A>?t!ns|h9;!g=O5FYlRnRxj5YP(R&mx$@z@pE>r3foE=`*_c!hdq;i@8L@y zOlayX2--@||IUlJXB`+NU#&#Z@;~7Bdrm+ zXsNVDueR{Hw?Nb&O`w)ET7!@W-t;DAg{>OD`z~1GAe)qISiLsO`pEOB-Qz+rVHW90 z0=ZoiQJ31X)?;`cdxQ5EKJgcq7Tsy#Uq_b_+_Fda1?+I_hJMF2;9L0Zvv{{z?SAwv zh)rAbKSsCw&+=w&%ceD5GfMTShTa4RQw9K-|BpYY_x-Z}rYN zB&(Ht41s-xHvO`7QR5Qo0W0h!5FNW%q()2i?59JO04dtaZmIH=KV+RD`mo2MM4pj5U@K>Zzy^Py<95s1Yo4 z#^~AXYxi(<9y>Qu6|Kq3JC6Moho+PzA9iW#SuI2+)!zV#7&|GUCYT=L5y`~ASiN?( zmk)SfW_3{_{#!&!a73-OD*V{AVoVcaUMw{#OInVlMr}#UMJ-B8S~k_nP0K>{eI?_jgsqoX7#>x@o9Qn=?RId{2>e9#7 zYRhuQ<%84&D-v9~qByoQ*cWUa(5o=-IU==|%zt7UH(oG()dKiDh)C+-dKDF_8?{V@ zx)3Cj)*`A~y&A2CDuxk{uYPCiadTfUfznR+VXT|)7M81){UYc#0L^(vd|z-9H{=xpjtD()<`TdO)DuZSbs z*IynO&#{2UQ^b}s)9bWE0CtjSDE!+eWRwgB3W^gk+f`%p>qL28{Al-=hrqa8+BvoU zdNLD1bV1_8J4DwVeL-ql(WQYE$aQQq)h}eWV#mGz>m6_Wk9VB>-|yIU%{#svd`F>; zy+aMKfXHJRh`D%W_W-7hg+&BvKo5;uq(+lP7bI?)J0JvX0d73U;Efy{R`{B#uMfb; zJ&KJjG;cqIy~glOzaqX#NmkDYREz8cL&>p#+%{eq%{p=cFU#uWAIZnmsQq)k7NE+d zbOcNfq|WUPG8}cfkd)2pC>TI92wLX2z^9`-+!3EYJw%O0Zms|SKM8Gb*C+ks@Im=8zO1E5x*Rn46H z!aCr?B0>7yAu`OmD32P5$V0+^BK{Gq)?lnjAhQ@&yL21hGLeJwvvPVctS;$@^Bv*) z(r!MTmf;Ilu3d#Vs-O-3B>95n_($>u9cx#i?%J9{Uta#jV97Eoq(<@b7jUwm5v=w6 zZk$q2847j8$OX2b@U|eLfhlH}=ndIA6P1|V8({+s7_M8hj5LfHA|(VO=!#aXE?apE z0~3_y*=XBs)&&IRiHJX$5(uw>Q}zIy)MW&xn}bMc&m_uk=Ar4ZS6>4sH_ku7$%XTO z2yz9^0ScpZX-295DJ}BSSt*pnK{yFhxgIz%)n$&jVBJWHW@@RCt zt%}>dbp%?Gwio}yqAo$xnIbI($2QMe7iiyQMlopiKx_}Pu6-ur7v_$SJyiIA0ixEk zA?7Nl5p)+omyY(jE7vKg$to-WEy^At=_V&V#dukuLmxYfBROO&;ZMU00a$=wrGSfo zu;`|~=aRcLCyvo_P<$sh{b7Xh{eBn1_+Ya^k5!yetidu2>-6BzRn4%aaJ4BaTMchZ z0ry5!BN{F%_<=L43p})oo!R`}K7TTeDbtx92IA`hUKP)+Qf zKsX15@l3vgeG{mbEs^900|O-4nQa`TmyWNVrgt&sea*Wn@vfg-|E@9l4~X*W_=gsNr69i^ z)FghS^yA)AFL(=LzGG4q23HVLniw0OY=vz6X0GrJ8oyrMFtwLRtIPV(uW<&=RE_jO zHLDSc!aM^tB7elS$Up_uAaR=m$e#P|8?hbw1`6(~oY|f(9$EZa@+@FiNUm|I&ANW} z7CRFPbAjKUNQW?j?0kWL?^HD1Yf2s3P~mijovNN5MH=$WphiqjGYd%0L#0D(dY8H< zo(S0KoeHU^hx@UHs2D6IGP38c`tdBmv>!`i_@CShHiV*S(qm6|X*@FL%#8UjNIW{B z>0k4h3L<(aT7lz1dF39|2mxMVxe6j~1;I)StJ0QFw|7KF*y| zD~UJ*-di}I?In?6xySB)7%e!_I?fo}i_>h8Ih_=9#Q>*e*1#`_VyoW$&4dm3B%A)>`p zQXYFDJ$Vr8F4R6v`b3>yfmPXn9$zmSntw5{DNC2v=G$`Pr=d=ZG~a*nB^Tczz?9&s zz;@(M!~$EFyLd<;*}Dn-VQ`GqL~1=jFHawQIelg2kkFqywhK0`LzG2zY33@-3vnkO zu4Oc3<;>*~c z8!yPXCSR6D6G6ZU>Sh&qyeg&nC1B{-uFO@z=YF}DXj4WEbTPSifHsXk_&;e=a_lXi z(;iWO1jq-^()cc+VdOz*_?|XTYL+*yWrTnPXBJkgm;QD(4~s@LK&pUC zAk0@+kBFL5?-!k*!jI^0rr&vs#JolXQoaa2}Ij@(fmz4RUtFZH;AMcP7#2pJV z8~#R;&Ipo9md{FJ5toE^7q@txQ!uFefBafN~?qM-G+>u|PpF$f1mwOi>_vhZ-0 z3-zAgy@6KDB4lxfPc)$RwU$XYIw!*kRkk|E0zDiR&{a-0$2nQ;5>_ErCD%EbbJA{@-&dVw@hFw(5P`^y(jJ(9A%Lg;VA1FaFk&m`*i>oqD6I(7MMq- z9!!QUA#gNIZjRxRJ+6&j%_T3$L}Of895#-AsA~vgnD@7CHTj(3GJG!U!FV3v%8m(P zXM7mmPx_kSH-Dq$6D+f($1}LEK?ua6`ry8To#F}H?ELEMpq%^*7o01g|<7pJc8|p#IkZJh73>+pc`{p?S@0tHUdt35+4@FbEiU z5#9l~@${FGY(*i0r(_K?S&{1~VK2qSOcMD12H%Lv8^y$!&*hdXNy;L*oFb)_lwt5roqf#nE z8|h-NSb^8lPU?*WQEPlkwp*#hS>bEhIs<_|V4acS2dclvn8Cf=u!P=KNOiXYtHvfS ze7xRnLp^=9dQtC75Z*2gf}dq`(L-d~$Gi5)mFK?dv#y|BO`Fl8k=D#;Qr zZ42q>(vz)UP91?40Ij&`0F`-**s>!!xQ=KI9ek;#?;R{7V3s3m2;dN?E(4gIcd<=y zGf-t;x<~W385Ovia0=8wDMt_W-I2aXMRz1KxtYKFHr%oUxY3R_0f>O+@rMd_ywo^u zc=`6v8w-a*X5tVa@ZNWSl$5I0R`TCaQ8P@kX9Ib~pk&N>T`y~7mPj1sEHfF4lC?}` zElQoD@y@9_-D5qKYn}|Q`9~ld;6xF}8aGd!81&mAM^J-O-bXElt zWu`1PFMa7~Sd;2>7|zmtX=CaPq(lv3{-daC8Vn!jwM?8N!{lXn@uPV#YfIb~PnMTQDauz6RQuCFNYv!1P( zi66&hSu63(I0imW-1>;gQsQ6k?@V4F^hWV_xXA0qhu_n;yP2$S;0dkxgn8Yv}S3=!9f{64IjH&n8LyE_93wzWk``! zk5TS_JZ5|$=ehWrTu=m-W-8Z6Tx*P>&^Oi zjNJJ9#woe1TR7MQI7G7*HMmLfuJB7f&lu_5IA8A5T+6I8;KxQ4>YaA0yu%`-VNjD1 z-Xh;bHBNGYC(AAwAJqkj%4u0(~Rj}#^ZerN1twS(B&dzF3EKvZpXLy7oj|B$F3K~S3TKWZ0i#y zsDugXKwvW={e7lYXBL!5@wMPW{0}EsPIGQH7uF<3#Jd5K4IeQ@k zVPIiZ$r1uwp;I+kAWNf{b4IT7kB2FIVjD~&7#{g)mH_taA0gBq8@ql&0Pm;=Gu^dT z?oOon3&;O+1KVik>VYq@6_^sJRDzdPcB(EMKTmdKl1dX0=L4Ta!PQNOD}qZ6fkh-K zd1Y>nv2R74m~dW`d^LohX#emAA2Vm^ z$|()1c#e0873(CiLu?4=$0VO0fC0nyC}S`DB^OF&SvHt?(IW0*vkf8pCMvKIZ_g-^rzc=*R`TA7dgy& zTS17eAk=0~Od8qeFell~qZ|=ocJsaV2(7?I+0jkGJl?*w!*K7GIrB2?1@Wb9w;{@D zh_oj+cbhZ1%}_e`si|sdLA1?mvYAKQ%=g*M_u~|L(;#{eA9qxJT0!#+cex>ci>w5_ zd#ie8Hqo%0$*8_kJdaAxtgt0e+7xt+kh+2|Y5S=yDB!o8GjC3# zBEiXxV}`@%G6-Yw@4~}sRQJ51$AwoU7UU56VA~pXIYKk@u^GBcQ=+IE%9X44Yl=Sg z&zx?Doqa1a<+tHzv-xe9MTF(}h66p2C$7BoM^(I0km&7;?B#p;|zaDHsSDo%>&`(&#<7xl<|qB?14 zpFP*m6v1=bUuzQV(<1HDqPD-yhe`YO{H)?3ef%s-?tRk!BtEPms?U=9zzKsR*W$>X z@O`E|H}7(8&gI-(d+tPguGOA9$rQoaBSK8ml1y7WGR9ubF+D&zY?%xmirhAlSoIAl-#0GV?b{4TI5rCB%}LaWsT#@4)dG0Rsu8Mo(tR z2tMGM!G2qQ^dOXqvS&rf2(8Rn)?DV@kKXGIU-h0EU*5cVH_}Lb>*$!`G#cgOM^Gm! zFwuH|^MdSJfz`mjyEm<9%jQC^X$Y3-?9lQXJEd6G$Fi%NAM_@D-Ropw#&G6xauFfe zr4jZDE*hv1uL>R-{4v?FToW4&}q%_3%5AuJv*g5QPyNSG&808J5k| zdzhGPrr9Ib>C;|Dt2l9c_$CyucmO`fnqO~rr(*jIl~Tt#i^8sXFb*H$YWv=^3EO=d zQzkCHez>D!@szz{-w3Adx6M7DcO3ssbL++Mjbktv-!H+sW( zH?L#%BrtUeZ*1S}X(OuZ`@(b>r!k$aIPUj`h2srxG>2iC@uAWq zJbC*N0Hv4%XlsKChFJOrQgkYqO65` zx9uofe6V+K>{0gJHmQ?MI@(KzjV~51)jQzs9_lbF7DaAuDqpHWz=9*i2|YOQqlUx1 zh8H(V2`^z9P-cQchA?^JVLgI-C=OlCwEeLWJYWjbrbOOj_(Nm7`q*e4Cfv$0k=e}s zo)zC_+@Fy>IvlqiV2M`~SIV*n{A7qYNDA(sbjwYKZ(iiXT$HdV=N=+)8d*Nre(2m% z{^yM?s#+?>j~J*BSnHpxQ5|#@H11)$LKSTn{H@JmQ>aLcB3lwtVJO47_B|HmmnK}W zP54O=4&byeNqfbuWjNjXL^Ql&i$CbKE5F!LVORFU=|4tx`oD)G7Xq&ET8d(&Qx?_7 zB%4FUH_$F{b*TDb50rTC3K`L*;B=}A~Wwh0f>qo=w)W5CFG)}AbS zmHkj-IHuyf-v+?Y?e1$DL=6DPX+70DWfN=`FXu}lq!yNYv1~l$t#>VC?4saRPPb2Z zX!<9k@nf6%N_6gMnD{&^cS2e7iJETFk7>XWV|J*0z;BWCYHt9OSrtVx_7p zR377NBU`mW4hw=&imDc(isx=-sn+xKPPs-Uf2v!I0TZOB1cT}b7^(`ODvg|@Cg zC#y>n=8rEOJ#NDM$q&qwolRZOAgjbPJAh5FcaDq=NJjYZN(=%I0(3^M*^igm0xyft zhv((L-!)U|P$IMf4l&hI){!y`kJu+Xj!;AZHQ^yX#POaI{O?v~ow`;_J}x=`X_(9- zx32F3$2bjY_j@S$Fm3Mwm)3JXTBD*jRGnFV?QJHGAc}Bo;I)(CG7R`fYR&dZ(_~_j z+E2}=&~po&sLRtO-=!*4?AUbp5hh$}fsZW{{$n~o0se}9S+_?k2>TaF!uK- zWHGO<6p0+*C5r6gz&+rr4{;d}wgn+@%cQ&>y)Gg!wO+3%;GM`lvx7+7_05{4_<-rCuwpF3KNsZSpYpQ(j2(=2 z&I`YiymDk-<1hi>wx>hE8UZg^v5UA35yRwf%oFgE^fXgKf3{qzu)+YABi_kfm!1?H zx)r&Jg<4OyS3Yj6DyTE3UqEaN3Ops*!2IBHRB$b^MJB_nK2vFnOaaT-X0o=(BvWLf z4J4hZ1}kA<)|y=f%a@JQ6e3EJs-m{2poQmAYAeFuDMr)UFNZj2Np55W^Km>lVAJQ3&YX890F@VKp?Rjrl|XYW(y^ZiSE(MaXR?*l^( z)P*?xb|9zAs&Yt2mM@O;#`92Rlm65zP_9!jX=CCB>~?Z*#r%qSvG+BO(M6|4J7G^k z5eT+x3d131IlpUO>~9*!X!2j57aQI62+m+A#S|il#VN5FoE1BPa7WIDfczX)ww>*t zw`njs4p=@nyaX$kAe`sMGlm!Ikr@;aRL|wd@w2*B{hWzGN{m+Hj7bC#-k($)Jt$kP7Y5jRr^<9A> zBxy%H-@FYS2WR(=4CQB?I&c1cy^rf(ien!dA>_wl?ORnXI4SLd@`T8j3x;|1-Ky-H z2w`c+nnfp00~n8koHP8Eo&bmA5DAoTW-jCG07c3Chqp7%nX?}iO+`_N?zEtoh6LxO zYRY3}mI>KjpCX=bQTG)MX_(o&=#%x5A@b?)VQj^}89ue^8^&<2JbTxvW{w4M3Ce7ns^5@W-?MP>M;mhOs!xBs zYLm{+d<>QUylSS2EvwVD*6F=!ohc60q^p594$t0PdvxzC*-@x#eu*5avd z4)=-WZm~>!XQj`aZRgJIm|m)CK~>67d-5ofU@F9D*^^VH1kXOjQ8k5VeVT_jee8@X z#A2bVZeN1fqHf=bX92BO+6y+=+P07 z*AXr-bX5BY7Xi4S&{~T^4jUK+k{AgWLHHlI7zr0axQPq#(hfn|JM*!$1Y)CoY{R`l zeAG=UuyuFZ%KWev4G`+N3w2}r;+7zS!jab(KgMksvSiE<*b${Fm_9Id^j<;uC=V89 zZ-Rt4bo{8H>jplzsFS*G(3fuor)(xlQoih@8?Y~e5i_)-&~oL8KTs|p+06j632pYjGFa2z0_rhn6Lw!+N#5R_MiKtywP zEodaicZ|YLTT3)@r~Vg>YKcM!0SV4Fa!NveKHtNG^a%xhG(q~H^E1)Mt~m#)?8v)= zv1DQ7vL}ydQFs$PhxeaWpZ}C2jsxlXBz%$Bogg-E-KRbpa{f~q30_(j17XMU+}Fk* z#VtN8D+|11Pmr*kweRGgnx8g1v>~pyRE0g#o;(Xb`5%0h|7Q>f15vD?Om7ZU!s-mt zH*b{RkX?ssNFJP$v9( zeN(sx!Sv3=oD^Y-~S7q9La4qYd$-4{s~;9#lXdF6MgyEna&LujNLQ zuG>ObW&OaNE&IgC79{*&@{z!-j7_wyRXolCwr-te>BHYBzcP2QII?S4`2U2EgC zR;5Ywj~$YbnY#_{k7Ltx%#duRkPff4$`#*Fab;Ay!V%t#>lw<-nd{_G+JSOb>dda5 z#`orRBjqAkXEwWFe=SyVdVWdd1ShMFzi`#~;EUaoGv#=IsH7&Mi{rxLVIV(7*W)!j{Jm(d&FefHXK4(Yj4YAvx z8vTEquo&hD8luCNfPJpu&Hdmq=pIw1i&k||{YY8YqJ;MY@o^yKU)bcCF;^F8q9=#t zC1GmFttI!!5STn8vy}DBZ>1wa%RY|J$K!l777PDW`!4(Bkp6Q$Ue%bjp^|E>*UGt7 z;}$tWvBU#Z!ViuBALQtB^o-^I?QK*%bQc~@SldM;8^v0|mrB2<{`v;3mT?p=j z*#fD%^5!Jv*vO))lvBkyoOcb+t+Q&3x7X?Le|{X@%t@pL?H}f6_5whLHK%iBvdKrRn#Gg$B`Z43N7BfZ~|EMd`INE@s3N zlO0?TRB~j=j>)%fc*XGqjT-Cx@z_utel3@6mTzpL!e;qTuqxduJRJy`jKXY^nH?rq zYp7x5Iv_|AAdq|9^f{HUxQ(`0JDDl_MY)GHYI|>T-?0{ySPM_UF%gG$@^V?X19SPR z7G-}|Pr*-{yhyU8da}mNt*vyH24e#TwJ{JIvm@>1b=J!SzY_3|1^kgF%Vm@08!~x;wjr$3(_Ei3$t=YvyfI2&jJi8Ub2*0Ti(%a{DoYH< zG{fWr`-~3CtRSESw!UYNzWRth`}9Cm&zMeT(G)iV)~H3T;iL~GEy31sv|B;kH#@=H zyE`ea>pC*^Fx$Mb5!s$287NlJQBcT1i%J1pDq{;{0BWETN4)x|I&ROZ&LnS-`+cQ- zQW#3?+9$c~p7sTEy`JXwT}MIOq}Coux_cjYR1KM4{Ay2)xXJrI+Pit*y}LzG8dCg9 z&kVE8b9m;|83i`cIdf{?5QTdPb2)0l?wUiM6Kzf9%tf6od2sbbS(h4EY2bJB+D!qL zhhBmGf%x6kDchm66u{w(2H*EGMUn2*PAf+^Z}HJuSxRm8Xo+Bm_$#wH(v_{ymBXXk zZ8znMS&=tUk-nI|>t`(DQxjwP^tltUyNp-lEd@bJJFy5X9J5aez1(8Swjvm9G6s~S zL2<7)OMHHDeUH6cVJ_Y@eL;wqtD62UYKD4#@hXn@@qdZ0!YXrf)eu(h$g zJ)qax(01>W&9rUl`ZxE~s+!sc*0pbfV0`k*(5X{pFGnB#B0(vc|GS{A(n1MJC2nt3P-2j zE;i4ZTLx^BsximQ3Z!TZqT7C4idNXgR~F2@9L;#?qj$kvUo>NnR=7?uCA#^&cJcKE zbGz|yQN+jpaUJibXPgV{VDY|aMOm}n)$5LCIu7Z<@J_>Eu*W5^`bGWahzV{(1o$6^ zHwgC@bzvu;ANN{Ac@NLQz|3x%S061&5&JZlpCf>(p`r)Q3WE+u9DB|>d(L|P*OZCS zS~2hco?i>nKvd_7{=IR!E5yYCWA^~Q7!Zz@;&L$ipk`^i8EzJ=lkEkP*xbC`8_W2_ zR}R1P=5cR4^!h~a;di>@8P^FZR`KzFfN;0?y6ZU3p(pFk_W|L{!3B2y<7b3`5**KEHoa&-9aF0C{t%6Vn|7 zm?fmC1g5*yTLwmSbfaHH7)&T{3?&b?Lv`+rO@lxuQ7ZFx>U|=gw7AF7t#E2KRh6P9 zaLxs1&LyX6)Mg`iGG~;FlT#v+$!1-8B-W{^_G+r8@4=4Ac*1^+|NyI zaHyiXSzp_Gc_`ERCYcUu|AW~8%U!yN35fs`Voo49$r&m-?#*k z0nlt@dQWfEg2v4ffa8xO{iX*idsU}X`=eV`z1ix58iqWRWZ(h10z|%4tX=0-RZV}H zYNmNcyb_cn^Z-POAzY>_gbDxDUqX{+1nJs{*oeZOfU*{#Yi*~HLzJC#FYNY?oOKQ` z{ZxzPA$gyZBXcnekfoON2P+gX(HkDEu_D0;Vsl{sJ@nb}<{P*6-%eSNo7f4die4-! zy0lz-7!D?G&&m4rD9#eM$DWhj5`y{tRZme{^_EZ4c=@0J^Iw+ z#o0Y>DWZP8Lkg`c5Z+fTU+fl}mznF`zF~|sOyL$^sdr_|I~upmP6 z67DzjxTr=vWNV9N&g=A$i?w^sFPQ5zM&ejVmpFnsjc8kxy$=x!b`(R>GIp49xKi-h zZLFyK87sE$x`Pwt0|R2tl8KkemYBaGU`wPU8NY{rN|vCAlZ7sdKD2W>p!3^UX5pVi zt0q_*@SiVW6($X+rO1qq40Im27g?)e6u*?fKt3cN4oi=M22_zGudz5U_A^M7$R4~7 z&BhF)HZ0j>=vM(uS`bK%xEEZ9qEMOzXZ)N|&{yfyF26~MgP8d)EMu!G z&Wj#T*7eXrWF5Sh@U9U$WSNA>KAcgkAq6!r4A?LNCoYIiFLotz_RbC^32M+anj!!qa-% z&>^YO+E{E}UAa$-#Q^KCvnag(`q}yB0lGrrr#FetCUsike7r^hxd9Ej^!)CcrgGAv zu|<&r4I5OsRXtx(TH`c?&)1cDR+;A;O52(`=V$IdZb^(d)O+GTJSoOjwJ@>Tl88xy zSSPDC!<3+8yR24zg3STCH7;b1dl9v;hGH5G&Fe|47KFVOgBS_xH1vX@Vf~LK<)dG) zO&(>>c@%y@Fo->;il&k3UlIL@Y49ugRJ|8-(4vgn16+_RYh;PIU<3`1SK!`&FGJ?* zqUN_Szdf6DVD0+6fvT4_&&ion$*s|%uB&M{ceXqVoK8yJ1ZNTDmAJ}BhSt`!Xp?Ot zui8VRy+f{=?#|Oa*-48RAB_h@A%_umN4*YxC@_J?1*6|g@P-m2S& zy5uiE?;NO=D%ZAB1#4T)k1pl9bWHyB#&MQev6bzJ%9+Cp6Js7jk0NHA%5(l@a!vmQ zmeM0|?FlRkB?ukX+h6mET>qi725!B)=ac3G1Q|oz3wPMzHuRy6**?l`BT$dSz(ld3 z@V`X9g&JJhlf+VjbJ5D@>5P|`O`->rkAfLg5DeKC1D=&%Fwv6-=iSd_UBL+v4T3Bm zvfW&^Q`KM4zYY->AH~FDt%L|dMf}SsNn({d9A){D`GZL2-n?;|%^C!B0N;S76KJ}E{bld~-Htwg zhka{e-*FTYx@m(cm-m^je+2iLJh5iX^Hc*hu-O!b$mTOQ>LgLukF}w-=EnOY<6nFO z2IDm_7z>cIdB0_#=VyKJIE3s7ChObBW7UCWhhl?HRd%hDQOD7bkD(grL zOusOn@LK}r6Ny!2rAxUov2xEMDvytK=E5HA3Tc&AO1V8k?iZl1XZFi==0Fkz?1JiE znSxqLeYSlUC}~sov}kQs4Y((%;j9(DC-OUC($OF5Z-GxidvPslc3DI6N5E!G69^!& z4x9jT{<@E9?}i-dB2jO|NiDP=~=4`d6QsZAzYv^+jFv= zgo`t`*NG~9xo0Kd5@RP^N<&2FN~eqqT;85E-~!pqF-{o~=VYyu5JA=h5aFM)P1Zae z+E5ET2>u`@KZ8H(E5HxDNW4iPvMLLREE>12aSJ~H-h~SAN_V1Ibvk$l^$gYhdBYhg zx4%gPU!Ihfyvk5#epB~xCZyTdp)NzMdAIIFCTgcih{O?9QcgBvE3s~Jdo3($$vrEu zAf0|KAySA!7ZZ$X{B%H=;w>=0sf<2(QPLiu!TUf=v|V5EC2iINdw^N4wV(PA%jG0Nx z&w5qU``%}x|EzWnx*A;=;?j7eW-vVe^_K>UH%!1w)`r5YieTYYx}+s%T{^@(SZN^1 zikU**ms%3bnj54-g=e?BDRe-DoHN)Ty-GzqorA7KpHMnkwj^dO$*VOqJi?Q+PGM*| zeC|RR;39~hecY4HeAOyl|H89H4Q`jNltX>}fWOL)sLzxkwy@{v3%Cai<%Dde21K(&q4YlDJN)*vbVw^QAFywVTbNsu*Z|A0Mu!Z2YUa?O&&f?ZWccBy(w zF@p9c*u;3a3#jMQJtwK>(>P|)-R?pSR+f}BVzvfzSCTf{sA;m{)5y@xC(X;ZBb5Y6 zC{nCy@*W@hOf;8ubgVCa+URok{6>(tJ(RLa?^ZbHj4we>SuW35^Z zmX1(a=i(cqS}xXNW2Z)|xk7F?!iY0Gms;g=BnbOODtV-WN@&egj6)zf#R-|Z6((if z-uD(2wC?jcT{

18)!*8k>PvoC9ik`mnd7;$*?Us;rQHvbtMXOw2y1Cy`Yxh2FZ+4f)}9f7vuIou$vLiI|6YIu2Lo#Ew~fsA5r|NU&#H`u&_ox=a9@IpAldvc=i^lY)Kr^>c-hXeOKh~Hy8n1Rjwd>nTI&?0UM6&nE-Oo+JqAZP5P(bNY(vt zJ_?*EVroEYE9+JFTN06o3{uKUd@y#3=DQ&E7P0}p+P~F>7U3Jhn15VTh*#p^3(ZmH(LbFH)KDfKO_%3qUl8VmTQL7; z&%l~D7v07mStlxE)3VN0)<2BR`<4yd{7yBNyjA66q48C8a|rA8io-xb!s=fX9-xCWc=p7B`r_cV z!~6LdSaf&G#l-;!%m6v3?5cBaR#VmGe&+^`L$9ZX^V%-N)rmieb>Z%J{M8lfoH?iM zESh23bIz1f#g;()Vb-~#4b_$PL#!~D1$A(oQy{4FM^xN}t+Ib$tBkLutx|QSMdLK9 zoT^h6)oD~wGb^newoXf;6EwhyhkltwU2-vAP!pB~oq7G5LQsq$bVv?zBtr(BJ$``b z0GkqsAZ;7bur){r_|lKE$nfUhEtUpIb1!5yXjA_EYS5-uTd;Bu78ZiX5f{EZ*9zuG zwmAihq|cbGMT|;bnmi|i!2d7ZdTVeZ0ULqsoa_&K z&(%!99J)fBM$#8{T!&jRrHORCF#ajTXrlyMsWXrkT~eM~jY!l|Z9x5k#%K8fW*F4m z-)yg$xyPtpzRU^>js*r7s6{Fpj$n*ooXjBnlZZwQ$QH!Hn)BC?$p&Zyc=zC$0oq90 z2FdHKCP;{nU?Tv1%&!w2T&f~7s>2bF%$Y~~09ip%ji7!Z5tIi*KJOP2VI4`hxz60E z==6bt*GeHOr)8bfvfgQ_GDKDHXg9LXNszbCxj$f$SPjF-9+YAU(8YMO)3uBRIP0cL zIRrU`^7<=?zmv~5o;m)(0H5>n`g`uy{1#OZ{HPywTfWL`C>URomRfM>1*D=N4;fV+ zUIU}d4&9rUsaoS%_2oEaTltxBkNLJPgJO_}s44&IQm!!2F&1(Pjmejt;lsMOK8IiN zZy&|ZHsv*a(qHAbO0<8LGv-qHy(+LF2#)7w6+aH2b2?M-?{?Zvb407kj!-G?T-64f zFL{R9>l=d|@ktwfibjy=%&BDhN_z7QQ8*WBM$%G$Hv(t(zp%Ll?m9E$P4u`}#KBQ* zx-iPaI{#Uh3hKSUAPCNBOz2A#5nl$!{au(Vr?hwV;@xHpsp;Q&hU7e=U`gojI8!wq zQM`Gd!g3EJaI3%VOpxj*)hF+XOu<{L?~pAIoH^b#K=WLpdGYUpG=CTM2fl)QQ3v!0 z^Un67jW1vd0^%>QI!RL`9d~wURT_u<{6)i8V;uxzR-j&BufiIBpPivVYr5$B6$O7= z?K$r+RJX;Su_dWH&ru?ROd^m95Vxos{(eT0_Fdp7MO_VC zS8YjuJ>%+xixB>?<%=oQ>y>5b?sfRki8lD9;FW^IO&YF%;|e}2@?9M|>FSGNx?>cs znmUi`gj;@SRSo=BPD3ahS8!RuRTwn)9wGOY+YnL)&lUEdpp$B!2D=NmI{+KSCI@#& zuUJGE<$~&my*|Th&y!)0fkO-GrXWz=UedwLhgRL8&sa_$Zwl;}(zY;Jo@U(QX%M{N zA8&%x2=ptuca`UQ9qI~opwJ?iEB-F|d{D~$65dy`tfLz?a^&yI?EbLvF%4?%VEL-v?yZL(`>f> zih0YML4Hg@x`Vu>K_;vXE%@{EN3I9T3p7)mN|N7^6c`3qbsJB{lju-Y@OwJCAplb2 znf!OTycE9|xgoS*1Z1K|GrtHGW-7b~<~{-=NW+{n0lTUUkaD1Q&A(kB2hK>#-^9j< zg+1kQ(w}TebR@(fx~A~?KsKwfaa>%W+9F^9vV0+C(t|#Y@ioO(K?r2uM%>yWx0&{S_eVE#<6$7 z*8>yuB-rjLW;y-4C9ztEI3LR&wFHe6TQYDafi5Pgvb?HCkKXmMqT#9^-8&8cUWASnJ zmWjT3P)G_M9H1|Cx(bAcr&HVp@<$p?QRGHV#R8J+S|Wz@9+H8xyea7SV)}W%m)UZ^ zmnUcs8903f&V=jM8X@vebPWTJ15=?%I^!Q1YF@i`bL`I^HmWEcVH~>Lq5%VSggH%R zEl3y`oboV%o-og>^~$a*6j_xZ18DqLx)h9Inf%Ppdcp*8et!3DJQZLl!;h6XvIxN~ z?P<9#Ep=sSpBFuug9Mr7ONmtrVo6H9MHm1ax<+xg-~8LPo9m6YGg%XKBMgCx80f(d~-+6kf|sf@MRY7wxCSM{UU6Ra9T;8lZf-ROvr}5)4a7| z=o#~|O34szge0ekV+!35bOq$zg!OM!g%?#)5T_3t_q-IWgI5^4GFwt+d6kbI<&qBi z4Vi1Bm!~3M#a^Vda~G<*kSJpahfNxb1!5cFU3Trc>CrJ3l-N|&yt~NWsh>Vh>oe%E z;T?%+QBc%fl)ET0Y490rfCx9-iEx5JXXY=mi_Ht>I-;3@z(7O;4g>}wMi4=N6cL!y z9ffGENP83mXSO9ZJP>+<-L3AAP6X`bZ!*Dem=`Gp{xF0E5ef7%S zEP`j<{!BUU<>te0DLG}LGU`>Q`kM%`!pLDJVEiU z6f0p#)cr)pkEQIC?8Rsc;Yhigs^t41Tr^B6&JKaxOAG*){=j9Ne3>^A=`hMHyXf@o zU$J24k(7P>g8dH9_2nxOUg%=&5+eKWUGM}V%TWWOdFyF9mGR$ur4Xr8zq-C`Ye#!C z^3%gy(j=xtdtUNfM|=xqJ~e!E8mX&gsHUoRr{3)~M6_s+a(|&PdH|pq$OR>j)XnQS zY*x5b`67ooB4cGihSrGmS9tQg&ObpU2_*t&66_96GGt^GNP*D}gbO}ni+hiDgfUhUA zSK+JKrW3c8(fOtSbTx^{%$iEi(9dy{8}tc|a-Ii*vIBY}Y`86`zc1VBM}cIoC$Lv1 z4C>gaYhl~lpbqw)hLABhD?6D_jF7WNJI;FImjIJw4{QUxHZPp%Y1Sd-zFBgID!rit zS#hBXq{o5e$dJPaWX|iG#Og!l>eg>jz=HPbD=-sF783 zlM{0)z-x@@6?sta`aio;m4_#0|hG07e0=CIlHq(=vc}^2+p+aM_;Yo&2=2q?M9%%J#m(E1eZ`t0@81S)@qn zzT(m$BEM>Ra@z3Z@#En$;vIZWS>j4Ob8~NhqJn%513Ud(08aagaO*5rA>exoPcb5| zh&~CgAQ#Q5=?;PA|G5^HkfSbpg66_j_Ti)ixaW^W(ZUB5qXvuJ|2%*R?0`UH`xEUB&K!GXd7qOKVyb ziWT7-cZq*coI#jm9A1+a0fAv+ZVo;MHE?viR!pYO7y2vNahSl315y_$*O#y^AVSRTn8F=ZmQiUpCR6V_S(b$M$4t^_%nf@D5v1} zWCLyD5G7LJdVMXjT2(!%I+P2mM(5?QG+6woMuZ#@9?_yf`LMRj&ozbl(k6I|!a-l2 zf#f@?p3OZSHtS{VnuuCQ!3ZvsZR@{TFv6l$qPmgY7y2h6KZc3O*DH9wyP= z`T57kKk--mie>0QU&{LM;DgEX{Be^Jp7Yz=9{=RyDDj0?!EmN0WQpcx8g@E zFZ?d>E4x;a{2`l{#M)sEMml#inP zFv!FE*kER>r7zyJ#55?lf@XzP93>Z%H&KFZ9|xy!PTdT6@|F6fB=KNAfy8rIgAxx36cPQ-D}fb(BJU*l zVw1<;U$IfaFV;_5X|euX>=|#$>pR6>-btcUK;}K@Z&6g)`d9k9Ft5eCVQ;6n#pm}a zAf*v$N5FRj_`JUm?!4S`F((^S<7Lk|Eq(ayi#W3NKjWt@gDKvH-{XfE01kPqZHU`D z=@>tvBI_1S<|*8WT@5+MKge4^8gax*Z%Cg^ngCh6lloE~MB&6cc{o3e8=+vTmbWNi z!=)2&i=ttN{BoS{o^R2>Cra-IpH;B_0VKHm{|kvVC?)lW01in_H;4JZaR{pj!#lCw zvV@eOEH{S6g_$pVOBrF{_08?NY(%ZkN=(s^I zcjDz-=&s{rZN<{$Jt~0kkJTNNOf(&5rz>9NZ|HT{F zDWb0rF>?F}Eb^nuZc!oqo%U-iBtcsP6O?R23DBoj9bjVU>v4PBsd30^K+O}XIHTi- zI;?dLZLOER;IM8gR9C%dOZq1^4mAb7+L8{+AE_l_#3&=@iyCH&LaA!G(y9`n4@4!p z8*E8P@8@2@+92W!girJTPked<_-HY+f5#qY;ztCH(X>KoLgHj)gVzW!vs&sLY^}qx z2}r@Ny7>)9GWaoMz%VOch2n~$Y&F(>_gU&n(-m6Xh>SRE$3HOwiF9mDI{A0 zen2R9gocx%bZ&#}QJI?1BL(jBpKif708Sk7K{~_qVWdH9v`H(;Yq$Q-sKxIW!LRA@ zeMRB%Yr)v^w7S&Zs3Ee=EP7-pJbIL8?yw-4DZ+_@zjbaKj0lgkuuhB0smgI$)UL!; z7N;uLY2jRRSD9Q<)~Tz6Nj59a(eiEvr8n%RAF|6;L(EhIdLdC+B$WTa1=1-8F0!`;9eMG)3;Gab5V;gZ*Bu|h96B7K z-AGuktN=Xh^r}Nnc52m9H}}0$jILg~uI8JaO@`)GwOU^5{#fapWUEy;Ex*Dc$0>+) zx+CM9f~Ts7C-m*)yr{n9YbZtQ}tzl831z|DON`|U85Gw)m8=wqMviZ4h9HAp{n z7AcD_o^oZ7lbYCoTNUOi(SB$6#;|I{vg{8Fy_LYI5?I$1I=Dd*1;BQxXr2?u*G8NjGVq~p(BrB z#tR!Idi%h4_ySjHi5bFW{GZ1A9xww=ec2V9Ur;H2x|JEJoSvgFyxf+7EdJE+n(zG8 zqr=Nq0(?FFAX~P><9YWsCfd4QNt;~krj;sw5?)eyj>cow zCv2R-xIG|@e$zQ^3hv}2Y@EtiBqm$Xo4@i;bg73v!D{-|xCC70Z7sNya@!qxGjsRD z`1?kt0p9D3U`ief%lyHg;R?@Ow-L&9@@TE;)w^+tD1ywZbl0 zLxbk(+HgTsl%%T5+$w!)M$NeIaHr&2XxVnubre%qVn%qA=No^`e!tihzN!AMnrB*2 zwu7Hhmbwzq@HTm#oC@O><+yUpv80QbenJa-$`OY}JY;!{;i8aqqe*uPk1=^VCO)Y| zuo#Y2uK2)6v0s94Kk=?A%rf!*c=NF5vzwi*7M(t)L!T(>1yP^oTk%=85Dp;Z0fa~l z@VZ^W!vQl=U7})<)m8NP#yL6CiqEqrndjt$+asBI_px2~F!93cbC=`w)DWX2hCkwS z;Uk}X~-;q5b zJpH-sByT`6L-M*Pr4ehF^-y zaf+pt>$_;i7-rBCtRL8Sc-WM*8TfL7{)}o>wQ(h1 zS~fboWP(bse;+KBV9CT6vQ$L1G#7-8VNL6fLxMO*kEdLbhOhj|@7<06mVfRy?eEDT z3=E&)UTFDee%>kH!UDp(oJs}gG4`Bl#j0u{{P9xNiWA`X6}6y{Q;9|%2^$L;=c@ZxmZZ0I?)^VPGsXHu#k|5WXKv7`&RJfq6q_qpw$K3EHnxClE z*B%z|mxjMF^aoh~Mp|;)Wq0Sd+mv_o3zn2jpd$;{@ReXul=<%e2ovRGT>z6GSqy9o+!Hd zO_WF7#PsxB={ct_|H8kzvO9(WHyt~+esv{=!(f}Vch_tz_nf9NPSF@1<0`|)x-ThC z@0{X<4r6^HkF~@-l&P-1QeW#lx_5jXcC?LM{tOd# zm+B6iZl+LB?RP1s2-OmDO|^SPalQNS-mGb(habC0r0aW< z$qMt9#`+3F$L@(UX=64&W&+_JJh)TAKVs5$d96dkMvvd)wZ=%Lg1a#Pk^nrLiXg{| z7_-7(u38WFLu6>1a=nyjaH#f*Pjr-(guA2iZHdCXJ=%-~bUA0voXq}R^LCE*s{Z=p zh|DErpqop{k3@J2dUqgQP|M(C9)B4fPmQn(W|CHk;ue3cRd5QdU3@Zp>d#E6(kDB4 zE<=z^(jvX^f#8d|B-?rp>0Tlo7898%}-FZQHGO*eWhx=H5A6H8Tm zh>i1Fxcw6Mc6M$xKSbQH&Yky_~X)Uc$_~fa%qh?Nc`m!sJ{|%iu@$72(8~ z)H9gz4rR_2d1o@a2YE+iB5jfnt@)xFKan11q>yO0=tmW9r0CUrT8$Np`@2zbAa6Xw zK&_LKAF5yM8_INaT#3FgXnOmg0f+?8N7dji8 z4@B=#V=O5-6~ndf^~I{BST$Bv^Nz+5mfqfH0C>|NemHd@;qZ2bd8~mtY2z+1uIli&u zYMO2$o6eI^+TmI8qqrlZwVBe}wuj`w4t*-NCa=u%90|~>8zh8#AUbQDe($T5_3Nc! zG)IBQr5Q}kGQa09{`wqu6v#JwARc$n%x+hCx&3@BuWFsV60Cx8EP4BB)?!E2 z{E4vOs{(m?UYzeSN{&3rEqufr8pSf7v4B2NW?h+QiXVAJkKeFP^)-GCbAelC%j`+j z7~Rdiy*V{IM=XEDex)qtQ|K*IfDOocTPWs@;jHjznYhc2o4h zp-n?eLRoG$)Ak>?xUQq~lDoAoeA8ZSMtui9R9DZDq8@GB&UQ_Oqmu9lX{}!=sl48y z>gxJxocOEjM32#bsZQ6t9h~AAssddh_`4opT3gq*FIkdCPRT_Ee_N7&`Le*$2$KDA zgv;!j{$1Fjd;D$3UkrZvS!=T%BLHRa_oAVG>D9{Rb&g?hm0S^*5Um|E0La^mlB>h^ zz+ULq3^}Ut=Dbb2*07AM&_#yojy*ca6R<2E?oN?)O>A6{DfJ%dReyDT#xbBJ=ULWi zB-H`vsTy(FN;q>ReuyLIfIKxLY6iu%u{amfSfrOK4`6g)9=D*{61=FjxTY zR3sfLq=po*+ENWa%#o4_4|$J4vG6&cihdR?js$rcRR*Q)^>OLRju; zrmed{S&Y}Z^+YrhYK7yS#5R6AnTV9JGM>v>Jb z5%Kt;8<#fgPQK%dXS!omSe_s4W%C|jR-gVToy{A|^mg7jPgR_H58OC*>`KpRnKH8& zAE?js$*8I{iaGv|8@&r(JV{R-JN6mkGw~qNZx++}`i<^aD-YNChLIS7z`||c45m-@ zcFo%_gk9|ES?miL(wFo08}XyE?yB*<&~Z_B3`+yW|MkrGAxyly`Qg7uJu80dIGS+@ z1N@Wd_D+aTCjMO=AFr(0`NFYdG){NUfj8nu*0jEWA^2bQAa(|uB-RCff7(O;{g>zR ztNxCEW%OW}qk&<%!Ir~#{@6P!(Fdn~NypJ@%q57EoWkbq_AlD=*V7?QntkfNv91IewVFxh+DQv1QdDbnyZW5j@WhRtM@6j5v_$x6 zZLe0s#xZ4dc>HryWR2NmV@#o(VfqbJsO0~cmU#27;a4|Iv20o*Xn|)8Q*Wf@2vLk) z{~2xwQ<;imj3fD>=r`geP3ZKQ@g@yx+W!NNI9DgId0#V`-~E^&h(^{VJalSwCi{#h z?*?M8+N?jB64btiCD5NN!b2uiXh{OwRe*w=8e0_7inK~dO%*kHNp#k#Tzoj@&6F^C2&og>Hovz1fxwj z0-~+S1Q67AAy`FQZ4x6Y+Fgi%O1HZtYDDV+sTM@ENvIGgc0=p|w%tuqt%zD79!P5`yP{&)TOl9_kjdFMT!`*~j7elJ0~!#soj29ygE zPHqby3?axDTNr=$VktK4CH~e8+!nUXgFya(D>z~R0VzIR0Gd2i(C=>mB+rHr*m0P{ z+M<#!Ko|d4iSCV3?1TVNalS|TQY*612W}6hTRvu6{zhe->$IKgEV$4q;pu2!qMpEJ zfMv{m4uQ$QF;({}yRi+ZaJ&y}Gawn0P-dmdV5n{pHp|NgS>#z&BPC&Q$2rrIc`>7i z?^VLmiVyg)JVc(;)eN9s^~BC-b01n*L>;qLH+^_J(rfbv3yEFdYNk%2p5`nl?ZI&(N`9;!vPDF-5VX`PjMrFL+ zd6bcnIt(j3Z;?7`NF5&H2PK(+!Wk8viE2eoCiW9vQfE=h*E-em%-$VS-udW`L7i%O z7DPbm>@1XnEHyh5o0s@gYgDC4&Nmc_#X4TZDjt)%Ukw^Hd{|P|8%Omr$%NAkfk@MN z#G{_^kiQc=C3iFv64Uik2=+*mXHo{?0kt?{08Z~&Y)C!8;Eb2Br=I02m%ZW7l3`y# zc!F|8+z}rjb8*nea8F5F;_$@$WNG5lq>fRvTKK6X^vF0s7c_`yUQ$1OywwnwppFz| zulqT*h6P<4uIFi#U)_7I6})KRv)<7%?ww`zZ|w@#Iv z8f>BWW)F_A(4S_19&VuzzBdv9X$Thi6J=qd?H^nyOrguBP&=8;yxDiU+$X`N(K|-d z&2DhXb&T#CxU$KAI>y3u7T}ZqY=B;;`%Fh~jl%(7PgC~L$+}IXo(bY8?RU#P2MMh+ z@V+ia(Cj{GH&S@V5j1+d|4rE%eRUHda@M?wX4+>^c1Be#zi)N7aT(qjV4`n%>nN+U zZM`_swtus>8g|?wa zX07#GYu(Nb?&^AWeWVDsZTW2wG2-t#qEOqG<(_q<##7z zAj@5N7yNP^IyxahVbE6{(w+O>@ zI=>E7XQWDddDSrS(Lxy&siBIK1X$Yfq zTPVP6BCZS9aNrxo3{xqcZX5JE$`#8!pWcV6VSfiy4MjxNpcaO4>or>W&s9Bvl1t8G zjix_s({!IhLzpVEj#^fsT?SzoP|Z+gLWD}YZxxO)3PggQM%w4#Teh(2+&M<+(?|nn z@U@v8nsM%le7RlLY0%3d!8kFlWKGZYXzMd9qYHtDj8b}3r4ll zPDW@t3{F(Gs*ZeT8<&B3&(FUFQ4CH0oDmwaZnT~se%<9 zy71w}7F1#fT^h$0@rTQaBR(Dn)&T{VvD#ZR~gUGfw_* zYj1CABVsj-$4!=j-7xeykcyDuz*v;rJ={z>@@Hz7uliS(T)sfnd&zGOwZ=t$XHd2a zto8!SjgoFUb(|M;hDTX{lpXyynMu%v%{<<59&J4$3(#TBFTjjV(9Gjocgwn2S|Dy7 z4)zmTVN|-2yoF8a;stwoVwjOS*C?D$g2TzyGnBx(go}4V!bRG*SjU8vhlJX`EAbp6 zTWlcNV(W-etF0x_BK34CX+LY*&yHq5N&)UeersEP&zh|0#sS^>kl=s9Zx8l*L|ziT z3UJTP7mtjJNs3xEEcmEHMn!3;3bIt|c&;t1wU$U4tQDlG_L-EL{zqI`FrkYWDm9Lx z>~y8o;q<3K;FOI8K4kw%l`e0v#KnUG07K*&N11CbdFjf%LF*9qAh`_k zD%^eHTlW(y;i+~1Ai_OmRf*?F2d4UXJNEH@ZXffxI50R=>c=VojfW1EO7WE3O-$)M zR0`_~GT7>`tI#`duy`*H{{v^Lsyp(aqKdlfkHwt#MSF zSdWQya_Yhd%=2{0)d$*PyY3$Zp!6SP+g&v*1mqOziWdh6r;>IsV^9Jhs}|DYhG%#h zJ^Vh}qQMaE$|+&Yw=RPUl*GEtVyL z*<@KhZj(qHV*e=xv^e&7IpzrQWp&#y=E}qp&muD9ue39apy@anb2~4bbTukkX|2NA zLLDh|$we$NXN3&{X53eBI*PR;c$(ZWo@Pe%z2~HFL9PrLc)#{)PGs*8ONQ3gRNrNN z6Z_W|!AWmoq-$bSt)u!DTXNYIETlp;4ZCfwiE`K4d9LZf)vfGiy1D;RP_n)mN2{+} zed1F!!Oh}-yM90n`7kgZm|y)Uo~9v$r^!#@X@r0i9eNblz)qtG5n@X>cm57(ku3VZihUt-ZNNQVP!U^DG>?(ZJK zgRCp+D0~Zi(~sH?TZwf#{9(f}kZ4yj_U2ufa!kbUJ^Zr&VcBT3k4k|`a3W9hOu*N+ zU|1EQS44dYy)vZgQF_Isq7c?7D>3&GdS$4Z-fEzI5@8$;OGmDfXtkQjeyd&u(ega~ zfO1?pi==PIuwLfr#@aXX=lPvx>73nt-E+tVM6-K7Obw!bj*CFhxau{_JiCaz>h!&u z8BL$Ckfv6@wal}VWc`a|?O-vbsF+eS!!69yI@f%SvrTP^2FWxbSgx&H2F3>T($RZh zPu*}80ku>Uls?`GH-dV-=M_R}*RLg0lS5U1aWDS?t(5;Tt+aHRXMQJO(`WY{rIkLt z=k@0Il1sC?s#mj>uZVjf7N_zPY2%>XanWa>@gnHPL3VsV<>T5y6fDqmyXe!N6a9!UOsG+6`mf0aAgAOb%-?m}*zR_YK}-?{4*Yn*GK(u0t7 z(m}g;{E-v3UtWdMn!~qZf>bTVX~_<89Zv^4cRpqNSC@o8i6`m5Ozn+2O8Apeo|1cs zqY~Z8QuXws_7g#BajjikV@;O9^1!Mle>oLe5+cY{qTdy~r0_QgM5yPeK%Toc(HemA zyrdJr*bN*LHHiSjH(-~t0x1`1HQ<2%s@VTe{Icw0{ys;^Z!4?E?_++JU4h>nNSWv- z@Oe`6-Gm@$ds1*H_h=LEne5ERt6q`BE*DIDJ5?grUSu_9r$rd_qKNncq%U^5MARz5 zoLYfJ6x0$#L9PDUMT?u(xhZR=(*|T_P5cE8}U~tp%LAFh-c4KFyy&;~!^E`Tf zyC#)D@=3JuYqoVfxcN12yMlxKwX*fWQHXZgc;hZaAKp+R$T-51qlNq8XkpJ`LSyaJ zA?&(remi6b0lZbKYkfynyrKTX;~_!bE&plwQMSHsw5PVX@ibS7@IsDfFI%fb{JDPA ziKH4OS4WN>g3>MjNlQgF#b!&`fTJfB1|cGnkx%@f^A`pk=To|{=s6;}v8>p$h0PN- z9=V&B-Rw1?A|WcO-pEo5WbX(=t5+0zHW1jd|1QMi-kE?c)gQ8cz3d%+Xmw$+XDxZQ zmwPq~&q{*d5rkG36np+b@;~PCXCvPs%blaBUc(|R5_rZnHDq{#@n<>>?gMfo18=P4 z@pMj#J&ES>wb`8#37%v~@6-kLJkjc2HSiEH1_%7Lo^%+DxfTi#&( zZ*#aytH0Z*zpEj%tyXi_Kx^Rqs~PXE;Tz~N_5_uVmRFWGIHYdJ8S6?vUk>#LPditxZkR5!X8Elv-ByR&e$bKe#H)5g zutT8J!5m@aCnM(!qwozEJy0Sx_n+dT``aXJWkmym;U!?) z9AcMlpqJMV6dGXKJJCa{&6Ob05EKg!4+axbZFjF=Yf86PBtUp?2zJr(9iyZZV;b*N zX&hEB-M?X{H1;y9=Jn%X%OK^{%7OobPJBxWoysI0m`{p2fosA8j;|!RS=f)@=5dve z;^yC#C4?#_G6mmN_0i|+rIUQx11m6rMf{|%?vPLiPrJR%@hLp;QSU_;e81EqzX#^( z@w-LSnto!DS;yE_s)7S|Dl79HQrI}=JI+|>F>seCn*mQD>Nu_K7A|~;;1v)$VD;!| zo!y&HL<~BeDq0dbAw{C2^+#q|=;yd|!*sOP=DX7XRf!&hSi`q9+@T6()(R;&b7U;# z>v&sRm&hQS5T;PBFd~~UsiG$YM`^b#^>{jfYj52N$R>zHfneL52?1ogrsE-Gt5&J1 zuiZi9y&l;_Vj_`EBtka9i%fcdsmIv?m%g)ih)W+Qo8Y0Qq%(I$4@VWdGWMDzaCh(WwO~+EtiVon-ukQ5X&1D_Hn}u&Z z;E*z@R34S|N=L4>Z8YgTaAVH2q?bGVOJv1aiCIo{1f^ZcCMK@c^fFahRMON=H7^7h zOHJ#|$&&~RqF3&(P}6~Bl%i~|Ft~GjuoS@^zd6JfHf)qKcd5sH7kKW&I|R=y;P9NU zw~}aOLq$&wzlZ0pleGsL_QML7xZfBtHXGSyA5=(&{P%6P$zZ3o$`N<4pN0fXR+Pi< z5R<~p6)@Vv2qcJ!m>=y+S?Vbw?OSmN{M0$pJXc_!fQ_lBkf~i!W5B#;#@|YVgQ-8Z*q}`C>GDW$EIQ^hc811okh$BErrRf4I zP#bs0`QXm!yk)PWoSL@s;85GwMV^*+tm*z_O?xs_EK9vmKgserWEoyeN6KTog z_86Eo5SwG*c3m2*YVn`gGz7-6smK#V#!*DZaaUj*qX-PdIEIoD>E_(XIKBqCto5~r z$FT~w0&9@!kai%&gKlB3v8)TfYo)~gsuQAFnsRg3UF<~ADpQd3NEDSu(He^46S<9* zWv_vji92@hIS3J`zv4Fzzl5%N{dRz=QH?znqkX%`bMg+r%&FT1%&Z*`7-LY4)d@o4 z!u!a-nQMmbsURrT9i)rkSM9f}#(Jap*@yXMe+fbil!eOy6}>S6nDWVobm>%M4bgn# zKUqU2A46uyrcB}dj4uh3p8RKr{_KGB-#oErjyzb3EzmQfhY-P3HHzgfu^<}@Z8SXb5>)7;qn5}4LN1W8T zHDw_HRF|U^F z7re;k&eHZ|!D7FqQxf^5*!g*>m*;z5(sbiiL%r;9eZwIc=vZj8njTx;urmgdkdjmW z7AdSBidIAHoWE2N(3UL?DSulRH!Je?VnJNy$QB_Lw^(X^Ekd$xm{^k80*&u@_%#eX zpDH2~YCK=)iM<0Fbm(o+plg2u1u78(QBjh0)uK-S>>vxz_l_{C`c$EZ-wCpkxlKq> z6TFK-S=yCBo}f->O{h0z>jlxCc%ul;O;;4TYYIx3OWb-6AUDc0z+- zY1VNTz?bY+jaeb$dbNn%pd>DT2Z(%r{Hn4&U>vs=Yw^$g_gI zmHB1`%HeC+vyekk8LJ9CU*3jF?CV=liLE1kGf;c!WX7Mn(irqVmvQPsDT{!o(VWW` zMc_riN{fK66;$LKwW2vDLrc8zRF^eNX5kN;BM3DvE%co1!hC&pi|`DGF<<#y?+gY4 zcuZTY1_3`kLu)t?KSvO5Tv+J&XO}6CYTS0q6eno3xT6aV;GP?{Sn~_C>C>g%`T-$6VG#&S0={TYzJWh1SF6?Sk2h}Xvg&1X z_@PEap~puWSJT_L0QZ1CF{-iJ`YwhRD3n^JIUc5h6Xzw7v`T zp?$k6!`+4NbJLd|K>hqOIiKdh%`q$1J=BRm8f{z&*;PU0Udl2~$M)o{=RzTo0N}h^P=S58C`L zV?HTU#D}atcMjRXbICXr@r?_*Y+1K^vpCebunVX&O$T685QNzC=N_z#OiJ5%&zRGt zVXT<@0^Myi5BBrM=We4iGE~5eJfA}UKq)=1S1DcGt&|Qh>_jQen3e=YMyAaDT} zGR~_SyJ@s?_A9WgXGlD3SP0G>3k&GWuXu)#UMF$AHscA-xC4%S4XF&tfmDe^L1*y> zeun`^+Eo-)1KcMiyq%58IMQad$kGjNiF{JfbODx(_8!~vCBOxYX$!8guvD(E+qJW} z$VDuTs51ko#>{82wK|j)N*u9ceO*5|D%RHg z3TzM@;wJGeN8V<-)_BG!x?$uu?A9Ou@CpcqyV?r{HAZ`^((_S;wbbu+NIjb?aM**_ zJ*&K)583bdy`s5%i754T=!;_1vz2?IJjo7UME1erIvEaPH-3^7s1Y9YJCmq-RsC+S z;3HpF_JDft_>Tg$J2E0K?wK=}&d%$||6us-A@D1+jNhC33MGkbcJINZ|By6$(>*Jz z`tDB@^!60xI(%0$!1+b#>HP5bB}YoUhdbTxmdX!>#Em3@iwe$_*+p^-%%7r|f-_|t zA^1S8Ap#-zkXEBYWZ~D_JZyeptF_SSilhqm+`{nXUzMJIS^3lTB?G>9^xF$jH?fqt zSU_xLVlXW5$*M6ne(G8k@}+3kCj;s$GGgEV;X;8Uqp06zF-&N{nicHpX+;g4I*uyv zmj&pk8j&Qe47P}rD|T%5jK})C1B0<02{f{*ca(KoFGe%f+sY)bcWWCq5>oVFFl^|! zfcQQ9YjyQ4Ct7({DIY7YZdtNdSQm^o5<|)7$-rMM@UDv^wvzn%rgu6UcDMR>JADHv z(nw9A40a~@R~0qJs`#=X#AUpB19wHiXL5o9jmMZsg7eE;3ml#K&}o41h3x-{We%}7 zo=0e>XgK=SyQ2A4M{9l&_Z%9)vYrk{4Jvr;L2oO`*jIW=+O3u32wYTFA(BMm{pv9+ z-tWWpzpzjSaAT55uI`F9{zEp)f_+)|A7i%pOl@THDMe zSXXv&U&^6cUl(D!Ra~cZh;ghIr=o}@{;7z@71XB)hk#WCIf9n+-+}Q zWHY+}Yr>A-du|L;2x#!D@DT*Py?|DJbn|_lBFS@P29MFURzp0VR`2^lD%mu9?hiFV*%zbcC3B+c)^V~V*Il1z>*(QQkCWWCk*356^P0gY`PMqxu8Pq0E&z_a^cTH&VeAqUu z!uZ^J*R&UN7!q~zbJMiv-Hg*0O1UO9!5XZjVn7y5&78ZXu$O7rsz}drqkf-(a%VZ2 z2nzl)PL~uuCCuP4$cJ$c6RJrXUp!&ngyzlQ(ZdaI#hnv3gP^>-{{Q6PpnC zFWnvW7OLC!rwtA>lCVS$-NR~58COgYm>$ywG@kggRawINKa#nxS`{CWS;LeeqQCEp z=w`P$_K!a>k&~HeA!vg)R9IE1jKs_F4Bk!pV6k`b7)Avili)(FZKZ@(^TU}rV;CZ{ zAEaEqQnIo~n(;gG5M|UogJ^5QJIcs=YEerM9oZyl!Qy@p~>kn zrLa<(5T(3%7d|h{1UVM;tYn@hQ^wO!4wjvQ^?ZQD4~3q)$qk$ThDSe@+YhpVXKJvB$6;{UBSH_`?ZVV^>$s`~Dwf zCu>{h$}$AiD7$M1mSxUvOuYAS^z5g8$Y|?AZcer@f@&J}jxR?8$@u)f^&b*iLK(1U zZ2G<&QQpWkXVutDZq+;#FHqRn>-iC$zb|e)e}io3 zlSE;#>NfVML+PoyUH>79>2fITnHw-@N=qd#W%d{}X<*P4YWv$_Pw8!lL%zMyD-QYY z#^{j+2X3||%PQX{@6Vu$UzQL8QU`q1a+6q6zZ|&3vXH=`S2EbTc(v`*o0yi$QmDW| z3br#hwpt0;O!Y0l7;Sf$;<;Lyo8Y(~Z+6*}UPvLfWNv)!2-GzPx8=!RC(Y z%^i5VP6WLoerrYCP4&i(o_iQWMg?rCiv%D^ErW*vUxJvLIo7gIy~@0WnX6RBY8+LdB%6-;aS-|$Zc>N$+yRofO8gAd{sGj&pj>@NTMu*)m9%l za}gN8yDlDILlgGJTL$ZKSbF1%BA7LB2%1XGkog9KR-(dh|pRNuVQt?=4z z=j|~Mm+Dkwyeid1zHa|*x87eyL-F&xe3sa&QbOI^Sq4d-Fb=ZItykvSd3&!!*?FIy zI%ww|JXK_e`9Ro<_Nl=RRb@rVMKrWRB_s^H?ZbQaC;=Xr`}cG4K9yHc)&GWV$IHmE zoh(8WD>0NI7@s3)-f`Q|U^Q>MIk{isnX--g&2+;y>G_Z0dA^yReFi_e;GpWGP@@ia z>J`;9%QX&YVWrmB6!xj&lD4uRSSZe5-{W)+2OjdgK%Rr*hWQPiPf9L3M#f-Hz#hal z^fi|_yj#|*vcQaMSgt-h$I@tcNtY2ULi#9CSW&c4Kg zZ&&Vq+0$_Y>obU~&ocqJV8EVZkW%uRB;jGXU}>^6+cCgiPyF1ej5Mev^|HZF4|=bexMf{aie9#UEQ_Zl5g>iM>z+#IRwNb@-juue41e!^ z6T|=Xekj9leeZ@nX0)=n%sSQYDK1lFNvG`+Crx)5q< z+*~I&t?F5$ZS$@h!WS~(3rIuFXL30o{v77R(Du=4Ca_MX1?SJ34QcbDS`7>J9;R*<9vR@}e_X%Ay4#-d z0lR>gzT0aXSJv=}*7rqJ>u#Chi=*Jt)BozXW~sd10-&)z=K8Dw4BC$zIM2TQZI>Z4 z#2&uLyY`GdGv8X-1Vx`cGZF%Com#`^vw=ui?|EtOd3JA)1;oseBn%F_h4 z@H<1zUa`o|mseKW^>TZ7zBfF$58ltWZ+rq-nZY(i8NP)F*%#V{10j1=ULRQIF7^8z z(gou3&xk*spELUSeg~cUDO)Cl!TnaRew#T=u8vU}GUuyjB{Q?0_RShD45BuRVn1S) z^Gkd5|9?=D=MQZH1fp4lu0*EXfaxT;b1e8dVqLi%~Z1UD;6SPjpDj_lVsa{fVQciPqfm4WiBT zx*9S#N&mQwxm5FT&`@P5H=#I*Vx-mj&5Rg(rg$@nNphr}2^S}AfI;{-pd7KRA8$4B z<@1u&dU?{il|yHf7Q~QIhsI1Q{EpPhjrW>X_+QtEeZkw~20T$UIc{jM`I#a3?guEb znLh9CggZO${2s2nZN+Uwkr9jcB94kY_9~Z`RAXuSPb)dvDrM&J5553h^LT3r@BzUC z7wmST!wDm{aX;H1ok?Fj^{954=x_{xf&M)gZ1V~+qeRV2tl1(kS`Y>E!t6Rf>MMt8 z>udY4J^|HM9cQ8UF32(`=Y2^Ku-Hz2cIpIb*vXu~&Jx+9a-qfZ(RHkYZLL@bCkV_` z^8)t6gOs1yu?{%9LkDN+-fcr-ePBd99sT)hcb~TQ_9@oZXn#~whCcm{!JoaKkKS$` zK&PrG`EJTQlujK=#XUm{pQ3C-ZX?oDFWBE*Kp6QsVB~F!SE3^|Vh2-MyQbdlj2T)h zxdeizvceTAu3+q&9)sd{N-%7D>;|#zi9*Z@(aCqCJJ|gxK@x4p2$)mCd<;(+yVCbX zh+?;N-9%P6082I&@yq&CHfbU7Oi$PcoACDDkU(?rqP4&ZNr)P3l$@Ja(2%nF*=~t5(hD-~#xdXY3Nk!+g;HwL|qm2DkvWIdZy5 zB8~7sMZS2H4Xoylmm`#)7BmT3&Y%>VvhJEfe2@?ZfF5)x+Km`LBEHRylQoivDPSc<|JT1P}a6Zt5Yo(u`_xd~yRNhJlIzqf;tZoZZ>waG)A>b2GF8HEKB z9>mLc%(6Uzm#)t48pzVj|EL{U8@T@_6mD< z9&&3NFCyqGaXa?ZG@>F0L@#6vynmsr4Kb2_zr35{F}BxlID=PTXorlrzLt0be=t05 zh!PHt)uRi%?xLDt_a><;LD;n7+A$-0#u$R<&_-SGO9HzcQLUZa5LM&x41DVc%;%LUT z)-2h)*(N#WM`|3+dYtdh%Q8ez>G1j59E0El^1qD1Kvylv_@&L5Kms%xnxv*Cx#vzP zX2{p9bn$#JA=?mX5j}=sFR6rNcD*Rdb1%P9ivfj4>>R31r6!wiS_$l8bB~BBAufb`;bD*~I z2M_qC6PPcJ-WhO``SNC~URF%}=zVo81TnDmhLsyWbbK1+69jn$6mc@xrSPy_oH;Ax zyFLNWE1&d>M8gYC3>GD-*dPPx8za$yAMAyL{i2# zZw6H1Xp~_Zl~LPPa`>UTkPF@!Rd_eCfhu})N_PDw!@Kd3BBb)5)el#WrC^Sj!+>85 z6~33IoU=qCAQG(FM#49!#?&+#3_|6{*Nl6v4M{MBcB|+~yI@(-a4lobjUlxXV!X%9 zptwO~vZ##RS9>o%zRGD(Ay<>oE#s(+kFJ{PP>`(0^tL&IFypLzPyJP_|N5)Y6Cxf8 zR==_CDwPFYo7E+!jD}K36`XG=45~4n^ioSKop101o`PLbOd}UySB#Zi1!c=}XWJR~ z+xcd1!T8c#)3>G;wZc48slSn%jzD682FDi|!qS|~(R>K}M1>I|%f=^)v#d*088L0p z?*Z5t1RJZLF6FeCQMp-uJj_y=y!n>Re*+6m6=(Hfkl{qYp12#Z?k*TwnhINP!bfDO zQ0LpRtWk9X{hBw6d@q|a7F|{32ktD{RKen_iribpdOR~_LVU?LObr2_E{QPc`)QY2 z4g7E&+_@rRwS`tm*~46+C5AG=U&@>aEpUJ@G|Zy3;tmZXgUb*zRg8Ix4^2o`-dzlc z%Zx-2OdzY#($plt1?8_dGh*)ni@4}|=hD{JLRro4FYAgT5ybdGY;u;kNUOnucAi6CZoL z>%u&s5ya=~M-3>voMoQy z@mGf}p4Oze8D2Z74im}<#&m1y60E;rZ?4bWJvzqjI2e!B|~a{J?4Fc z3@Q67H61653B9p|K7BC+hx_mdeHx8^?G?=apu^7JYK|IV=O4PVGqJSWYo+2>IGsTu zXODtPD;UQMoHup=O~Qyjwz9*kKSZvHJme6=_h%a*SNSa4B4gsH-tmhWD>smnY1ggo zH1R)GN^Tw*VdC$tGBY$S#Jd!OG1kjx#E>?udxA|Jfjo8i^Y7hs#VBnNc4w^L6Jdu` zV(>0;dICZYNfnA*^}eo=-oJ2D^MpEPjDx3+Q6;AM)2I5Ag6-fjlf?FE$zvrSO#5Jz zn!opyO3nW?yEID8KbWn;->sWeWeC=a&W4Jam}vC}7X~NG7_OZR9g+>zKmU-N5yT6< zd>?2whKayBfWkr)#_0VFQCN&nX1qE~@LzTh7(Zp}!lsm8u`RW1ya}D-qY_dD-d|0( zXeg!T)t(9@D{)$O#xt+tnNAQkI9#P1_39Mi(SXNsDv^a1K^CUrV4fzGpm;(%AHD*r zdm=4wBZGd5QGT<~!w_|3^smHTG?p+xcwplD`!Mj-hCAr}x9?k&zL)c8(|1CIk--{> zrxCl383iVuCf=pObwW;dp=@5*6ik{P@lewR0iJcTGPJkdQv|=Gs{s(eHW>;AUD>d( z>CP2Y!{@3A@C^h;#4&W)KUm>}3nm$4I9Fa+n8j!M(8Qmn+yicOHfdedQ}d z0T+bn6g;Y7JN4@d0vUvTiF57c6_SbF*kU>vH{$%8&N=_4PbcF>a7D?L0ALs%lCkJz z2t{z*6EP?UBrxM}E?#U!7d&Rc5aDph?yZ7-@nVQMYFJ=XI33pNeOG$6M5H|?+U3p1 z0xusWj7HP1=gLK zWCFpxDhg9w$BR7%5KcaRUP>k^bz##g@(p+38$Gam2W)gdMw$qIks3r%!*M+lX(`f1 zq(eyHnK555d*ncQxG{NQQ}LBNAwYSaIlwClsU5?^jZZFYT1@htsrxU!c%AKcMGQ;lC)nP$4dCta7+ z;T?a75gd{O{0jVgZYV#ocm+O=-|T^1%y_>+$Zg;VrIJ|zXICzYn1!LJ2n{tI-mdA> zNjL+tMNAZfQE*`_^yb)^oB8W@-`DZR?id~EFwByna}6Bg6labZR+6Kh&Su9NguV+=U}nZeC)#K?;hq zyFVNZo`i_PXiDJ%a$ezH0Z#MSbNSe4RtV50`>H`w4r+^WtTnn`(9soc;3m zo)<17uJe)emhVv!kv(N!me6VHl$i_o?``#}#$C^7(bt%Cp5(k0|SAwx-D%JTxW42 zEXv}0FOl!DgIHGZ^}XkkL5s1cS#|=hhvWJ+{H9~S@5k?3xEFnM@42_}J08C^_%-0! zlZob!jzeunbp|Xc!@ox~y zFa4=NW{F2&_-f9;)C*G#2}PnpKaO>5_wrUpw!n8rn##zo}?nQ&Ok z#lM@TKA$IxlanKUjM{HcfM!D9lSS|yyyM~@0q4fHmOvoJ~x+d8n?$d;_}1axia6A zOunNg<-yzGJ4yfNJ4#ewn#q{LCYz>Cc~)qe8I3^R3;Qbzf|tWq zjq_vo0-64{q-zdB_e69zysPBdkU+z0IBSPu*oEa6Cpx(}W=n;Ts_oO{2`yVb!(yI} zn@n=ZCYYzUTXPKH`!S2ym{UZUCUg|CfQ&b;TDDLRJ(EQCK7*aI@$=g-p2^K}8xP(l z?5T;syln94?UpT??zb}W0_wH!g923=hqH-=G6SEQBMLJX&-bW_zo7pTG3HHV(X8q} zu-4g}v*63~5gG#)+Mis4Bl0lfh&-Qj2wX7VlR)yflKhYFBR?1JfN{hf5REYL`)~mz z3^OPLKSbM~O*G3U2*b3w^F2?H&@LZdB6hh0S+EWT5v+B*tdJj8FnzwKKM@iA{Su;Z zG({5Mulb@vL1=+tz9*bKsJT=$ttpJ;gJ>)WWz#biS{Ykx!3TAGV)RbLDVnPVnyWdC zCY_&~CCkrJXbSlGFk{Dsg>Ma9yv#R+QqDq|M$dQaxkp)wT#Y_p(OW~zRA4SEp(Wu? z-D=>2rk5`tTX^}WmoHzRf7$w)%D1Jwq;dgm;rVKk6on5$VI7`8*rfEf28b;Jv{@z< z$Z=;$odIj=OzLEJsnY@6lu2b|Uv8g3W(AH|-M`uymm#K0E0lz542kKr&Wu0Zh8&Ju z2pnlldatkbG(va^e`NEN3~$d|mC^Akga)~cG~J*uKyDEByg{X`zLbxUsCQR@bYY|k z$??GuApk=?8FJ;ML|_=VE$PQ=(}RpZQdVGj2w zTVL`d0tqyZxCH)t8{xkt&3KY@=_SvQ%Mc?cUV<2TOILUKjew=w2s{NIIP((VX$rqi z1rj~!*u@t^IC}>9%Lodxttu@pdN2a_+x+B{3?m>5A2_>FGF1mcxr(>K}!gS zFh=?7GD!^BDZ-Bo=MXoIU{U%+_)jJdCvXA5q687$WzYQ2vRd0qObk3JG5#r9W&Xv} z$+FRwQ5h+s4Ms_`yfmJX3lzh&iu~}n$dIbY9TWPNw3mUl@v0OX+cQBO0%3%p$>0YmO}An)ulRqir&krh zW!90*X4c~mWF{co!pwvg0iMTm&)wwtZr1bGCA?&s8P813V&wcjh0N4UNrEIaKVh|L zOL?jRLKvRU!rNb`{W1u_=we@JKe|SSFmQ8%<@oa7E^<~?ms~~>2{_gl5&uL8R_C!_ zYAuv;;ph;SE+EHl=-o;=luJf=iZ21guMZAGEz8jqPtm2?0upcxlJEk_WR&*IzobY| z)UStmBIba}p_FqjxxzAs491-cGSinX4Jl+IsqP?s(M5^}$Ck5D}Llv(L-{t$n~E zh!{|hgB!i$4v>`)`G;qNm4994ua_N#wH6l=btg@5Up;4Tx734RHy~t5c*$Z?$x>Pp zYT+Szoxm5CmA&y23_!+x%3w#Tg|LyutZtXvDKj&d;a!)jg~qcN92u2y#_tw^K`0W! zTG>08tcK+wbxh;w<@xn~$m<*by?p&MDUyxrHzwC$`??ZF0WmCPP?cB7&o)u#eVt`O z$XZ0}j&!#0D5YT@&|f^AyFClMI; z&NGaI@CY+d7Ykkw{m9sOVM9i@ei;N2yW{aEmrKnE4 zm%cFXxG~6kAQJ*jk84p~$j*7NA6rf%ex9Ag@3D`gPRO1VE$^E>_`WMPfr*WmUwl%2 zBjVI>N2po+7!#Wi9~uW)5xngFjA8Z)NE}PCyQ0)3@Oi$zXsvLP*cA?U^|6bs#B$r$ zpQ^8eHVk1_x!9-8p#msJb_}IkMpM2}{>QuMvJ}eifAjF}kB5+0YS3&o9=sUPpI`vI zh`uD)mVK{J^}dUZOUl;N5Y3nSp?IqZhqL=4tOU7mH~}L+yar=jXYV zukU6A6( zUb@&cuf8h4P#}Ir7fM0&-iqU0IRb+b9B39r1Y}v`53DC~R2%b){R|gJ zl_7-?L>#eC0RkSxQPqI&Zzh}fP#+xzwXY;pbG(!UQ58iTAHRS7z+sJlEha%!^?@L& z@mvi*ay9ISTdRM6q5?H=Ayk`R!VK>thQta-X2fq;1*z`UMY^8c9`X5p3mwe^ACa3qRvzv2$~=By!$oXM)DF` zJ8SM{Q3{`pa8twmB%V$X(OqV9cbVzDlAlo~ zH`SKjU4{@+ps_NZpNnx#5d>(;XMcGXu@Qrf|Ze{g%}eS!WcMD zm=}lpvb!wcw6A)_1srJS0#|*7bOPx|g12lG_D!N@C}CvY-mBY zE;|jL4yoHEVxg2${*dSCPs$7;WtusXJ4F~mDZkG1gpvIIB!4fFMN!JH@;v=WUO377 zge!aSNtozS)J-x@u$61cQ)m_wK!BzyxBvWNh=K^$s&q`~A5#%Yl-DHu1*TSQ>}Ed1 zrsy{;?s|#);0Ue`?e;vZujzb**6_yCsK@pJ>ap70JH=I#)i3-JR;DTZrna9QGmqUw zG&WQc4-O$-jov-pIw(*_(%OgHvHIb5yclT5xu5^P?RdJo9jkxa4%@@+crnn9FPU36QHIR;lxTjqB7VFzBFy$nGfM=_EO zj95d)r@6Tk2G&qaVD32hvQJ>)ZSPYEe&hDw46_|}IcXm)Gu<5w%Xom2?TKpV*;@4OQKasV7e&;S$ zK8AiTF5>zT*)sjW=vb*KPSuj;a2F_=d&=Fu%!(IU^tUs9$vj{UjmEYZWJi0XoR;FJ7Y z?%W=Hz2qQPQaR$yT$zJo<=~8>{+Yy^@na9bxi1iW_3Y)6LsrIV4<)b=^PZSOfT+4V zK4*GwU5F-T-^6y;cVdp`9;xpMuD;hEuJ50hU7HZu^#4;~Wp91CsBdFWefzuX3*qW3 zdbqybmt7lwTOStGLv0)gx$rQg;YcHpQjkU?J&QCJ32Ow+Zgt6qRQT&;^$sAB=7ZAB zVr#M=x*{;O^;^&M3G(%!tXE~HFDp*&LfvOxpoZ3ezUG`#JN+uzkYuI*d~337hze#w zOdXMH4Hi5GvB-||SW7$36S*?%FLs`XEzgi-CJbZIHY6564SJ=fkIqk@ee7ozNXy|KZ{w{B7?lv>3Qe?y(jdeU!QMZ$VjGWNA+-nLWr zwLcB6;}ffWrb>q_cv;|6%~R8SGh+zd5j7;~Z-w~cus*2$Adkq6c6*NF#1<}SJh`p+ zxL+rqw$H@5RpHz_Ba-Zab|Slmd*@LE}~s z9=l3D!AGTVH4=8?qsl zpAX=pr_TQ_UfkZ@$A6PLOtD1K>Wu>|BmB4Ri*pOQ>sh9r{IPEGPEwViX#lC}MmLIm z&?Ra=_WW1fZ93f3rp4X3dS_3YDE%3 zanc3Bn!Hl&7fU5oxcOD0xlpS8)7gO`P%+~^H%oyT&MQ5gr5FaGwc=O4b*3u!!q$eF z(%hY^o%ma`+T@{fadB|9$;(~Ttu|(!J^C*NGQs`jPF(GLUt#Q9?LVYIoL=DLDZ<3E zQcaq|I$WW(n^AKfPPtoL7e@v<|G_{TCO4=jHwOCGMEZB6w|_lrM-s`wi;My@)(*qX zSpa7I71byRUA2iJCY&*{A$sNKzwYHB!i4flp*Nh0H$XN8DDh+nfeV<*x^tMyE1e&o% zzIqcik}n0i8gl_gLyfL;@TJ7GRe)az@rk; zjSz;-fG}*DwrM<4$5UJ#wsR!B6nu&8=b&~plUK7JMu3~1;Aw0a3xqc%G-knTub2R- zL{S)4w0TaH%4mJ%H`evSN5e4K&6H7gE|+oV(eg5pk^d6hS9%-<;_2!OtesK0OpjZ$ z{5Hu_!vRERk%E9XmR#vh&(~By^Aqu>CpPzda2hmP;Gi5MWE5- zs#W83hOyq}`RL20G$qgM(VYjeJn0;W<)b9Ftg>siXDrFmldL0zCQysGSXi*v|I;h~ zRaxCF$438c|2a!~PU11j8H!<4-F%tthez^VlY8>N?#_46fbdmOjCd=~G<%Gv*)Qd3 zy0Dj9Fs|)LK~Ws7Q}FF<)So8;Z~%zFaxm^YyCDcV**u~Aw!|ge8rNT1Bl29w**k*9 z&~rG+5Ryi(@bf)G;)c*=gQ=>uUZKy|GJM@r?JXio;d1&n$m(l7+b%S2zu>NQazd~N z2SK^wRNj_&XR^O~a}jK@5ZZCn4n#su`hnGqT0N>Isdiop4+D!K9TRdY+S@XGuRyX% z=cdoU^sO%S^VD#v>P>tO_FjYA%cK;Ekj%vkuf3qHy^!c|s-v*x+BBRKjCwkS2BnDh z!pEoS+}UIM*i=GjHT`rJ+pmcLZy`P-**6ii*Tmt8Dh0Pga7NU3_nr&K*d!p0>>i`4 z*$V4o4bX+CE~bL;WsV@@(zDNpsxj&3$a|u}SZ-ij>vLKhIN}p(Me?j^lRlsgUkYOTyOu`CB#m4AqIqvk6P6 z(Ra4#Ut|>l3B`+=ww#5j&k1(382#WBC!z;Dt_kg)OWF>d(2Hb#agJ)83TTwfZ^M!o zL+nB>PWwkorUZ9m{t6Fv;_t<2PkQbwr$yQ`j^TYC7b=KTiy?}TFt8+nY~1JDH~f6R zc0yBs-a>dYkBv0dakl9{-Ax5be(fx<-6=BU1SPA5VooYGNcqN+DcwOa^Jt=g>2_KH zSVdb#(FFKIq|Np2@zxv#M+;VWv64LK45J(SpKUtvljKQ!m1?-)zR>Tzzntk$oxUPH zeKox5k8Vbh8blq10h?lRABXGEnm9H6U0x?P$(q2pBt_1C2uBOgKETm*O8`etBdz{@ z9NmaIJ_*#5At2+c3&86bjIZ|QnQl5_5A5rrHW_^U7B4@t!ROz#l^lPgk6Ql>U*h`M z*Ee3!H1;e5mDm*yHt5NB0li0&1$qIag`>u?LLVY8sITzNlSmy%LH%KZgM>NGI5!Jz zm?)^@zW?=^j8#3^0 z(?zyyAj~IGY^Eg6G%lp2Kbqp{N1jHU1(PC-piY(9G_&>!;qK*@K$3x(^v)W)S136$ zJMCN4FHa4!L&T99;*A-bxK$ykT9^23D&_{&+&_zIcxMsE9b1rO+$9<88KUzePE6ab ze4VsrF1Rz|2BjK>Jh(UuI^g3pJMKOPg^bG0GZ>ZqWDRxGT%vB8Ygk|ml0KOA(0sbi zJT#wM0`qzH%>Q>jS=gw(jCz(L*^x#91{}a|6mZe~Xr89%ah^ts-zkVg7#dAcLy^WH zQPfJR3}spNKHH4ny#1YzQQzZiQyJnB=2F!DB%G0pI7~-yf0X3m0GVg-e8ez{^5Z@q z*MG$|PUdFU<2o1D`;q@ITyMnnL0s=a+J>|fX+#qtGmrz7$*4S8!5`1$zv9jly=NvzzLRJFI77}dfM3nQ3N5_j zDBGc#UU#ko;3P1)8$@%pr-q>PDpGp&84}GAr4Q9=iQnY^qwHPaqAK(M@iS*G40uWg z5D~0q4i^WrV(^A$$_%JLmdtPw@Wu>*=vo3$`#7v>x)+~2{ z%B<9oG_Aa+dD-ggwsw~}|M%yd0kQr4cYi-#uZKD3^PJ1`JmUc-)$2<0^zu3^MDRhrcqzc9t9fmKnT@#xkwEh=tMm#_4E(h(Ri z2pVo}bi*y|+GX5`<)+%^d$|~=<5DRshxMw}rpNWuZe|)EZS;pQt2TtVLR1S)Fldjf zsA#yvA!MsN>ypdI)XVu^%}vj5=mVg}1s4H8%{^B;PU|(X&%Y7rjD0{{L-rS?XUYD; zL)B?9IVW85ZD_1o)wrf%LxrGcT{^Z|1>vG5ytH&_si$jor~CJkIKFoEdiUd!zgWL| zxw}pRN~u}M9_GGqLC}Z6t@QQ=2snl8p+a_y$1P;T)n3T93Q=mII97<#2*q)N2A53` zP}%H>sIQQHH#`M}>`8*=W+D3?K{Hs$p6uxqvZuH!q}3k?8dk`jiXwP5gV$7)uJ7Pt zI9+4q%4QXxJ;#*3)Rmp#QXpZY$C~b03Z0zbDu7aZ8Qyoz%yw`6#t< zbSFM1^}ItHU8x#%MTWut_W1=7gY3J$vREX(D`3n+&_dM@IXtgnesB!;`F*CbQY-d~ zh&4aP_^ig5pjj=hZ%cMI=&+eBYsU)4b_UL11%s&z*+?flliQL->NKB>j~G8m#yGV$VB@KxWQ0bg~Ce1GVAyG{k2Q$(_z*QmMC zgLpiGir=J@MWY+b#4qTUvvi9Au|4q82~DPNFI)a`87)%DHk(q$g*z`@hHwq%6IhvO zxp0}Nn<_!ABuV-N)}oe7=PvK8FpNw}kxfmCS$tJX%SB;dfE%*V!s+VES5}Q^Y+T(q zGJefyct0c9^iEibvnuo_*yxZvXIYu}(nZK${&t4IMNVTTg*IyOPpjA{cXgTg+(m3V z+x~inBA19~kXh%!7ha`}bT29s&joPbP9^V4>@MTP^*rtzQ0UdPI>FjP_!NZm?QI%izsR>8&N&IOnjI!pOSBU0C{yGWE5vD6CWb_ zDw$pmI*L^NyNk`1(lVnl$+%*9Q4`9R9AdV2q^g)igS{<4vByT2i8})DvRHnG;+IW@ zJi{Ya8k*be+XD5=3?64mVfaDTOsah+6CULRkSpb=xx84)Q^O{!hks{GEVFlfU(Xv-HG^ld2D`dUbW{1WQT`c= zQT$4a{r7>ALg()T=shT`T+Y2cnCm@;%IbRa&W=<2NZvuV!hoWcb`ozaWpmm zrPJ_{vdBJCmH@EE@rq=v>8=1rFq6fs>9MaM#d5GOy4a2N1qM9C#l9f08-PlQMlY>2 zmX;gs2~@C!S_k_-F7_qmDr6#Fr2V!)l`=mdbA2TSbu(r2#`%LCDGk7y&QB5W_S4o6tR+eyBrB?g1&UzPDJ!d8QWpM(}gFNz(V_~z2Op5W+-uB z(Bs2Q(ArmCD&gsfHQltp(+Q}SoA{m(Sgdoy{U%jA`uBmAXa=m7p_AW84Qny%I#d4L z&$VVN(2VsJt1oiNV$=o1erjCbxM9PZ zR&OXPgt2}#P!zyoT#uT!-skV8{nPh!)XOM{B1T}w$56HS^Jgp=Q{ zRT%o@M876|%feqtOP*;OT!W2>jlG#;$48}GxEjS70H4$&hkh)82~uux3gj}Q^iWDO zSz`KB`t;dqaPqK!xQO1~_P?h(*U4*t7c@DrpH%E0IDON*UriIC+_fs-(*B|o-?C4C z{nV)k6`RPn|7HC>+)O+g#fQg3P*Z|A6WvmP4?{CUdk^vFX)5p(F+xTfgvhLHr5VkU zSaL7+B-ogVd#NA?PIaCS76g*EJ~a+A_}I@=N>GN~R1PO&dFT|%A@8K4|8=YVV71LB zxwJP=kB+zQudeacV~HmoZ2@h=J({{7OXa|R7$Z1e2qfjH2u{7oDPAV4-kqni^08xs zz{2@OssEiUTM}bS(BRaXU2!68nT8v*?60UmkCUS7x%0kyF$^JAJO;ly0}tD$hgtKA zl#Y+J(5&Hnm-!pbF;(sGJ8--#O`JdyxvUuc`^gOZ8=pjb@t@6fo(7xt^z2J#1W9Sp2Q>a$*ss4vR+pJ&S`9G$P~x2VA)^b` zdWW&{UH7iX9Y9b-02gv`qL&;qcScoo9O#SoZQj37hd3dhMZbDYyqSu+FU_|<+&_%H z7Y2G)eX=cvw^IFToabi37YV}$_2}Bw>D(|luM1`XI;9|9Ru?28dgkp{km1pB!+^+& zT>qB4l&l^f**yvBIdHtMiHwc&RHb#=a@46gET5y{;in+u-KT10-xIj>&8c?a`;Dfx zCQFuM{JTf2>DN;6?$em4t*5|%K1SVzDMXK5`IMl$e*W7Kp(w$;O8k>IA4h09Q@8ex*v)9Y-XwTUy@nv0M0#65HF@{ z52KRHSaag-u8|`~w)%_-BP$jry0qD**77%!3M`kTK^3m4*|tc=wGGf@gp2Ij%#>zQ zFNTEJau$Au$b@b5b-z`Ab!tHuM8p?3P8f%SByQN?p zQP}tm;j8~DZ6|iZ3*5i$l6PpIEfOLp4~Z{@0ct^f%@BS?g{y$CRG~HC26VnMqG|CNo1RALR*Nn zeQg0#UbMy1>us^<|G6zT#yZEAigRgGj(>$+;yq{xc&kjU*gKhVK2cSp8y0j^;hih1 zU};_(^f5tMcj@5mA!{jvR<^oIb-NFZoPyDf+MXEXe_4yixe~(>&A?Rx9^REiA)0Cu z!(p{FR8v`jlV%eK50_!C@^BZ-VV`IB8X0G072bn4H0wr%>0)4PG@u-bPG^-Lqy2`0 z_+jrmpd>Jwtx1fbcd(U7Xt@DziJ`X)H9B+qUx9}yZZkLduAtC`({6Jm#uR>aYo*%% z-V9d~;bldy39$^3Tsu}_44GMFd<}2tA6~XF9rrNS(v(ai0EJNl3^`jYYvF>&7FNQI z*GHcA0e^W+>eOruM`ir&FTwgewH%I}AI}$m3Sboe7$C;-kGd>0pZ~p4vZdF9VbL25 zsj=FWs&y$Ft*dt_fkhJ65475%0I@_4(q70Q_9O2p~cM%*hcf>+?YSj#W?~phlS6VfE}& zpfih^>dPl<5g_*E`C?B1d(DFZa=_AIu}g=)%EtjT3{`#>;~K(S_oEs(a{;!!E3jSb zieiA~t`KZP;!`p^Yz6VQA$-p0)B-+DrL;z>JSSm7+CR}RH^`$wBpn;F@RtA#pF9 z;ArW%EctgZ{cxmQY|!qm2$8WW++Rwj>1SVAAEo3|_#WwtMv|gmh19K|h|2LrOamMi zr_L82qBeMt+Q2^!Z6K(J@i01tZ^&~?{x7iV+-sM3^~3tH^Hwk6)?hX#6Uz<63hmP0 z2)MRhzt&OyoQ#j=PMR;yq%Gt90otP6i@KqSNWu-UwOZvlctYC1aHuK$;ZR9#4v7}$ z#b$p*0CeSVFC?`QdGo@ffdkH;7QuCkx>hYnV5vuD}8cQBUh zCGfGWyNCyy)$kUoFLE~+(cLVzC62x#z{z>alHWM2|9c@cffhBD;hpPc*dheWaCDx? zP#L6NDud^G8HS9rn1AzVGd;Q}#VC7H6_a(CY2Uoge`4PWpL5q9ZI6FTu-SZr#^2r!9tp5p9liI2ZPi3y z9!v7)N^ZoKzkO1ZF|7KLv(`h`Pe?Usa$Xu)5dO_;14ocwJWLv0x`(0aTx13kDKxv^g(@OwT)$i?elWSbdQA00P<23V|nNX>AGN*jU+i)ZY;{JuJc+I!~NOTQEy6;?E#vHuhYzCHvp5 z;Br2n;X}B3n_-qF!Y<7f3kfu4L@(q~yRJYUxL8YK&Y$OscA}ezp7AZ{_WLDc0x@5F z0b`mWDTvZoCH``yI$Pq|5cgdtjD0?q#y%fQV@=S<()h5Zu@(XiO;v%>2MJ-K(LPeb zY#n@FSTB~M-z+tDU2n}0@=p%B_`va1-CIWsmJNpp2&5eRcuhG_yeZ%hN2d;kAHrDo zEXNzt`EcvaQo6i0Ad5Eud514b^r>=3K6ptFm zrsLOI*tMU#N6v)|0>M!UGE)xXOm-?e=3-{93{gyJ)DJxfn8#sQ1t}OE^U#d2|GY@J z-@DeVKc3z61duP9L-%OCpJ~0x6QR0CJWW-aUWgBOWIVvVSGX@!h>t0(3v*Hbe&#cw6;-$ z!Ro~p!J2knb8Mrog$6TizNR#xVpvZUpF*KNMlGs-fX~P_mAJ5znN@>XSIo4If;@#UHyfJ>}K4rn}7!duN+gJZYcv2RtD`L_c*F|p~;(q8_i~c_S z@fGenTmS;s!?;^G1~in3UhFWi3Y%2RH2m}|enfboVBkl@6!Hes>@QLmgr`Po&=#q) zc+0IW@2vRr?6Tb4sAe@6H>iLcnY(QzKGWPVe{#y31~7^K>E@=HU+ezHfXL-6tO=^Oi8iLEKuWD0#i`rt$3jbI~Z z#oLDR(16Y2`H(DrdN#3i^f`g$J-xgkgalXd7!7Ul*SaX)Y z!GWv9MX_|zFkJK{QM)Xe584#ACh9he?LmYQm7O|@WJy^TT=3GfQu=&0$P=hf0EO|j zoi(Yic_1I)qJIj70FsC8D<)3CXfl(CTW~N!n3@lhr%e#!`-xgUOrADDyse)Y!iUMz zCWvwU#85s=o;E=o8VF9C=;7n$$TltEsDVIJ=c=$s_gizs!Njh8`76n|F?V7O<>*0R zB_YC~PD{4W8IVb!>=1_3?IVrY_Bk+qCi(vn`99hF*?qCM?!*2iwb4t{C)V84yrFIv z-Q$}BTWq>#pK{Ni>0Mv+*6qH24=+!-Me=KzcJL8+XB%uw^lQBSP!&2H;S_E)?rz4T z{l%~nuGn=>9#_jCL!r5=ceaN$_2Mm~{5;8Df>RgVCVrk$hdSJf7)(Z_5}fn+9Y+cC zTB+0Wzfx96ni|nm{R!mRS@e#3(Gpi=TuF&7ayaG}pfv9Z$<6P0T#n=>BQ>{9#RMGv z-5_Iyu!v&26718wC4}lddr7*`hw7bqn)gN34CyYM#Q=tn*S^{xbJwAs1pC|)-e?x= zPc48@E0^~>{Hu-pkrEz?B}bQx>^-Za@}2sE_!l)m_pYA01iDvd(0U+zH^5H^^r}ii z_+C%g-_3(s{kc_F{du7^d12n<@i4e=hqN&ifZowLgH5K>4%Wb{qemw48PR-XoH4WB zWLaX&3^%`SziWx{j~&%_F3I(T&(*K`>mcXtOVVX9LSPWqMBY;KexP;>yZ3!*+MSrh ztar>2U#0bSnCr`!&jP>S|BmSIjUBAT1Elaog)3dER^D%jMq!;*dAMx3rmue#-;xZAS3?2@6 ztgC>T7J_16haH?B3K$()#rjm=8cT?bdO6D+c(FLZ;UxK7-z~@vQsvQrfVcxe8v2c5K`i+$6*@N5_g0 zY;pjw+2mlrwk-sjE@Vc2j4gVHsEikPN$}ZcW{YRZxPQLEqerC-k!WND3#u6?|6>`fwFe3}l55;g@2I zp-*F>PVp^`{(dAjOVirmeki4Bqc@qWx0G&I*NkBLTrnoY6{CDVy`cJA39`E%FA$z| zrPlrr3D76NTf!VmI_aIW#ft<(ai`RecXD2W1`fCQTZnO~dc8aO|zB=>TusT2NB!_~31H=}+Hd9R52>ig6fMt3wP4 zf7PtkaL4w0Wm3)iQq#(ZfG6T8409C5+6PO^_f86-u2;Y$zizKQ)#N*efmWk!MR=<# zl$o&{h2=t?Uvrz)bI!T-^PDVO6atwcM4t06XVWv@UF3nG zAA0ISRns5O2{JS;#FwIQ4#B8=P$4y*dp;)8J$JVF9DVjLpheYo`F_S{Z>l-R>8Y%X zZgCdO?mQf5(e2R#K2qD-1JoP?iAz^eSC-XGzbyQAHu#?T$o}uyuD| z^}if~vDN-gI=6Uk*!e>}f_jQyOcSQ+ywAjPG0%@war)+W+B~)Jw60XG9?R(uXoRWZ zwt~>zZzL!B-;3IEuqP`7f+t&o1>@SUz9)IpGyp5VQo`Myg@Q`9gp}d;(MvSSOME%T z@{f94>M4Sl=E~I7;4RU$X4d6n(%wlJYW&B8IXdWM~Ekvp_0Znk(E z_2>1noPrDXXG`yV(^_nU&9G;hARC--XC1c5i67x6)8N^ie}Y7S0GfLIcglCr7_JZW z^RMp511rXB)v3X5Q^AD4DS) zO}9sb%`bMoTSM*%i{719-7&u?q#vH{sjxko8EdzzS6dSg_Sg?g*(-~m0Rq|{w)kN# z(UCFCzT+gf*sBfqzmx9Gi1t{UzJGA_rq!=|Qf+y$tKYFjXgoGsUR-+CSzF$4TSS;Q zPjAb+#l}Y4GA7wr?3(YvM$48lC2=Rd^LADaJ8#^hqB;C6X|cX0D!2(5-dwK;_VSq; zWp@Yon59N*J5Ab{JFDJ+Mra_jU@gweL!m%BErneFnF`+)q^7RBVta_7gR> z9qAaO>9t1di+v((dY8@yEah6m^pFVapGw5%Y4PC#SbW6ysNm})Z;K?zdv0t=ua`TD zaW6li?5W(TM?uH2QhFQ9SO0*3lrr?riW2b&n%aKqC6gMsMvys<)bwqgFch6w+2_{x zFE+Cn>k7&3dQ@(ya|0i0z1Yji6A{+H3%x0Q?}EWSW>Og3!+ggwzeGIK3lYzWUYPC& zZSGHEKggh5q>Cw+{9Q4!Jow!p#i@vguY$pVj<8Q@V`GP?7LE?S=L{lnj3=*@TDU$a>c?_HxhU|(np9dEq8iyi@kF}x36b*7KM zwkFc9oC`CiXy62wKH6xsYO2sUIIwA`MmWgOG-lGK9LKaNk2hKZf#Bovm@V@qPD`@W zABx3a$arIEFUd}~Vuqou8_h8bdOiB+m@qGkI15ZY^r6j0_pb;BfI^UHiB$`bbtvQ? zh=Z1iS^=^Sh4@`RF+^Z>LE^Xl#83gU4&};AfuJKjq(WK6@+20H1tQ3_N4O6Zi)V>x zzqc2hio&y>3i9lP!ee@`Sp0zMkRjJ$AI-Ud;6WWMe=qKH3?AKkUsww~#@}w`!zQnF zB}EJ+TMVY@#d%n*6i4^-ITF!e37<20nua`w@9L!(q7d8l_^+Tq@Yhsdw{NdgcyLPq z%1Ij^zVUEYHM2yyvWa<>LB3c6cLV!LF`)^Y1n`Gbw7a zHBiJo?$L0!Lvf6C%KtLGudVz9x47Kd<7G#Ab9BubZ?Xmaa04FtT~QXy2W$zWU^}3J z@z^a_s{Tiv-UD0W(@3O${R%u>6?CqogRQ~uQly8FdU*O}7@2>BKDKkA4Jemt8O!+Z z3%TeZ%4H!*p_c`*j0eJ7M?0dene$rsEX|oOCG0nB3DMj~GFyqMY==}775!{v^|n>6 zh@p-l+Nz3_+}w3wCmfC;RgZ>;i^jJXw0$ad`EE|k@8R@q3y(gozXA`;&aUB1edE&i zb)makYhsyMf7L%88t184cJ{>(yYuKY(%Um_A4uH(aD%Ztx2J9H(WgRgxGyYtUuffU zBW|obgB$aYZg|!a3WV-e4x1U(B2e=?i^VrdHMmPwl0qj0Q1dq=$YN@s_>{$0Rf-&@ zka0u|ah4yG?~8C6i^bRIzE)YKI1;zHw@KA=kAYdribDO+LZt;pFq>#KM-k(QVe0nc zth6AUOF~AF8l|zmM6(sP7FZx;`!PCvL9)LPBm+Yb-G*Q}7?ZjfO9jTkQ!>Atg>ldq zt0mTyzp&3Zpzb`}9CF9H`(!r6ztecXccE7w8PtKqyR#PF7@_62IuHb%*=Td`JC1w$ z`1VA^JfVV^&J>A{P&s}lm&1v22YhRJcH)WW_R zX4-I^XCwHWX!A&Z(aolfb7esR0cM}?3f5s~k(fz!m?+mlpte*ngaLm%nlY)Aci}BX z>;SJ3L_`E>0!>OkRzgqXU?T|(_WMdm%@E>zNIK9;sbv4IC;3{|ld$&Xa{&CFo7Wm$1g*J=6%$n|!Xk3NMirH+|@+ z1N9~=iaNEyHih1#e_us?;3Ju@Tpttc6Q=hA9`@B3!5qGJS5w|xe~hL%w0R+B6!)oF zE$l#fsV8FXPfa-ku7D&W;+8AtUV_!ji|TZW=kh4#k~c7ybRcyhy^FLLX&=&uNV|}B zBfX7u5Ge{g<=^m2{ONxDo<=&1^eNIYq|cF#BN0z}62Aj^(iq$uixfjVDdwza1Ki#s zbz!;Hx^vcyHOn-6v_VKub@VTjox|r2a12OOpOCS|XRLKasB0oLpQ*Ma^tca7#Vc1o z<31p*ei&Bw8N=M6==l*~NWHAakulVf5d+XZ`~ANogSfm<0P;Cl#*s0~5urM!a^wwl zM5s$obUE^391)t*2L(soFh_)TMTH|T*3SJd7XhZ?7k-(_GIb4e^$XMyPD7FSI!zug z1YnQgdy3|q^?}7?<(gW^Sk?!)BpkZ(80Yf=g((0UiL9VOw(}WU8tGt*)IUc-T3l;% zpZEefHHA!#Ugd&<1sv+5M(0MFNMxeg1qF*jl(jB0QR{+&MIo*WDp+LtCKnVe3jOK+ zCv0&+!J-h?^b=opdcfL7DQ|H$NY&k+2MhQ|x+WDRUD?tJ+&p~szFi62SR~W|YA}k%V#A+HOIi%nO-wd8@u_UxefHn@! z+Y00+TCo!IIn&=(?zDx1epJ;mnuDpT5h|yq0hVx17XQO>uQPtd#_7sqN*9DzA6lf8 zY8uPHQi~oAs!||Jo&;7G1#L-H$_b9P@2!@R0ZtdZEK90h{jglm0U_Su%c@9AM;lU7 z;pZ;5hyz4fTB;E5=_kt4QiV97pD0U972=qFqAV>{h$#|+L8A;{D$N?OyF5?AQet`| zELF3B`HA-Xg_N@j&zl6EHxic<&wJZtndgllp0|9KXrfF1mw4W|%f$1>T@LcR^Ja;0 z#M@pZ-gYSQwu%m_XqFgF^s_|wUr=~nFsXJ!pHvIFoWa+5-iXWAn`E9>_y5N8etDhe zO)L-2?Gt8+2Z&#MN9Gq@RAmI_r1|ej@VslYygrpTYf|63*zkYggHQgS`QXp`x!VDJ z@R5Gv06zFoKXCvbyng^6+)()MeDI)I;(NpgKYN`I?xN>Fb}jS4>RICRRIjJxdOeSN z1^HlmZ(-2*)avMkK3el?B(zT(^-U*dU!T)Cy-*e|05;pK<;%jcl5dPii(31-`^ap6 zq{gH7PzcrJDDnhU{2}|+h{?Skc4L<5T%lM?FMmjW`KNd}F2J&|tLeQPUP8+P^G5-4 zJET{U(C(&dlI)8G@XrH>ELnvlm_!&-yf978-JBNL_5*aR!#VDr-kZ_6a6f&k9ka0j z9n*O(;<8{_+~XHFjbDrwY0)=s2p4aeqnMSfr(bxU60`Ax9v_RfkKV<&TM899=2en#`UqYi zSO!Z>AtIid)n*%-U{BcFDC|4=CYKm+q5FbbXD(~HxsR&LNVAk3siOn>HH`!@w%mTS?b@y8a48>JfdrUR@O zBJ`U8RlHqSlt_R{TG+6!{RD3Op$9@B3Rdu8O$!UfzfjTe59JLsXaNgmW(#Y6F}Vsw zlotj`GUF7g6q>%*N=!COz2@lS>-oy))T}w~KQ81V}OOgjN z-=Wvr)%~z!^et`I&w1sA7{nN_jCLgDpQSPtwO(dox zB;m84r!*ol9f83g;1@hW(`yCLqAv?Yp_WaDfm{f4Wu@Wqu!$`lyA8Wr+mes1R_$zU zgt&J2HlHuk|6u_52JlY@U)q!_y>hp9Dt<@v8b9-xJS1kHx~wX0@lvNz>CpY!R`?*I}SpUo6?q_U*$9S0J=R`S&ERwLV`0>fw;Ab0l*+ zD7inD3#CE1gXPj#Z$W*81V*V4YLlh$CyPs4I46>nkpMJ z!?XFitJ&?@egw|5O-fY{!IM)`#z07u>d;$OpeO`BFdoglG1l~Sf%rZ(H2z^Q{6VRF z80u?8s)ek8sYhHQ_zjElzr!Q63!7gx>1(z^-*6w zPSjyNeN;G;^PWFjGb`cMk?sjc^zip2SXQNb%B=57_3o>w@zET2ri+RQGa2r&j^pI3 z&PAdJQ13HMDG--Y^VQ1D_m^PbnXB{{cQJ}jda!W?;x?+uLo}0%9r%i5?>=#3jQcKX zLF6oubKXUcoBPbGAJVts-EvHk>nGAog7?go-*Yhd9uE3k(ou!s7hg&*>!~{X^i*SS zr#);tQ{7u^z8+7&G)CHrxKz<+M_9i*W=}q8JFIePT1&@WxdJz&JOl*!@nTF`h;<~s z=!6#XK~H5TCLu<|pO|TD;g9UT^<-&jlq<7!%}U4_pl1fxi5Or>%ZIkd06Hwcb1bUE zt?*Pr^V1_QT6knoVP1eunf3rvx-+5htr&aw$&x%ptySD)*W-jPUO6VoJlqeh z*TsCnx2#BuWz>%2`u0L32P2Usoyc0zQKan)Ds-ajyiAJX*G3E!G4SBeZ9o&~t= zkN;qGD;NSYj`C-=ir<}R-EtOzA7dHBX+)ut9y8%sJe1!VhDjBKpBDA_jv(S=r{5Ps zAs;)vra{mdo!*%c4Ek8i6h1kuDf0L~*~1&2J&W*;r%vEe8=eqi82i}#dMVtaz4EVj zuQV=I#AH1mgwxZ07X6#aO5`W8O;!C}&dnD)o7?7w?f%=Ztp`HO?>N*P^1CfCQTZ&y zn|vELsHN$#BL}qK4EnA!9Ls;x8mVU(gPsoM)AKh)H@%!MHV`)cNwOJ!Wdb4{h9c5o zlOQoC4Bla|M!wp3!q{x>Uf=y`HY5ICYF*#hbk19#ZF=KGX{Bbv=v25VOufk&mY+J6 zBRII!c#Hg9Cpp-=XT7dXeMgmQn`D3OM5?A0{k%x)eDwqZxs;A>L?D-0i0j#qFD|5c z`fu_+CmQ!UUpQfR=W}WSaU&}YFc#FbdMZ2L2<%b!h{I56#PzJG$T+QgP&)rII>NL97$iQ z_(?ee+R|JiFgp=bu^~!G3!MM~GUY$Z-_7!5O%V^q3lctO4sU}&Qg=5pJlJnB1 zpu--_rc&`LU{9nonPR%lXnKXNm+5L=C4=lMbbmixWAZ_T5@pOZnqDHW8|8Y_MoBh2 zlT|BtYy^WWIOGJM7Qr}^zZgg{HNmss`eo^@Mql5fc=ZJ5)JJo9!+jwO*a+voJUEnq zk77thvS~8ONdDNjbu45|f>iyNC2~v9tEqO6Ny_PU83Kqaq)GB7+<^#>z-Yy#Jme9N zQmyFVk>G)8spJw>%7a{*A-pEaI{&K_3Ud)-xtRSGmd@(gU%>{m z7VZHr<%tVO+4gDgvRR$8z5<(xFc)xLZ_X24MDHg0*)Ktd+W>4ZtLOGrViseXecck% z@s+a}`(KSQT~nHAD9tn)otml&`M{-t$b%?l8Zda!_~4i{J_$za*uID5GsW>+9t`Sy zmgkA>v{h@9w`$L!-;mBnlB8a&Q!IE0OLbnK-sEZMO(^O?^gb=GpSacr#Yw|prYW~* zyS_P8(VLXJB#@v>IZ0-ld@*DCvZCp0YB^v)U>o)iDYy+oKjyP0>SWc5S5~cXgL?e$ zVM;-F`(Zv%wERA90U&If%k5Fu zeUG5rFjwpI&9zrcsfkQ<*>LMCvtSPf-aHr|PkmQ~d5Fp4fF=PJuA@*^;C*Oyi&2jv zO}{aM`wI!UR1_?-!2OxjH0E&}gZHg}Dj_;e!$%HF-efX5%&g*w=sqOXukqK9?0|4? z4R1`gmI?--Oae@sW8E)Q@EK!x^|+D}lrD}hj^{JRHJBK8W4SSr;y`*fjQ~imxnmlE z)F*E;Z$iv6K|LlZ#<(^s$!yYv14l%80^b#md(9f!|J1+M@aHFnu3gA?vGqdu z>Ugsj`JQ-tL3zE<(Uf0KipvS1Yb%kDP-MmNK-E$Q4O18SGwzxO=pV+E?+`<%xN5n$ zf+7RC-yyO@?3MWt4@#V>lgCzMuIYbV|0RAPWBN9b#+njlDPNrwJloZdjJwY71D9h; zb97$p<5$F2k$20L^d$5_6KgshfYP_!#k`4ET{*yRSCwz>hEQsc>Hxdt$!^FBam~>H z?8Y~^H`@F4AcNjy-;CI<>hfJF7rVu8a5)aQc<6fUPd~!DFx{lGcU{|LVP<7rx4rc6 zO@qpVp6j9I_rY^LcKD@LTZednainzLG<7zQU7>6pL|dEEH`M8C|DsM$uVfep^eXvC zg-At6xkx3@*OE?m4vyy`l_I4lF^o&jqiY!ER*W|@(nzFHNOvNoAf+OWK}tdzhcpqX z4#|j=g*1?Fs>iv26j}woNo1_v0Qb%^P2q)m?1lD8Yl^gcLL7;=V^08gmlb#0yC8*B zJY%>>Y?56X?N)c`_?0Q8fQQ`^GHERa?D?m<#n+EC?UUNWqWxh*+cTou9y_}Jnf5qM z)4Ni8UTE7paMl>J{$cowaLL|`Vg5Y*@|9f?Ogjq<_)%SX(d{{Gdj#8_7t8Q#xLH3QSrlxXi!j|KC;S_Lb# zWK-KGr_MZm3>1Kv!12d^GQ#v|bOR!CySVda@N^_`|#sk?$!F?z)#{f`w?23{2&wC1j&*P@bw zDw0=41c{6LiBYCSSWig{glpWD5+4KW>Z=IA-E`dL4IQP303paWxg;>h{eczaQ?}NuqAU!JOa$nkzm1T_WOb>5@(6195B(1#s9EY*}&7%=x6-I^+x)Z;+VP{ZS3rKZtCtRRkw z6-)xR*!Q?X#_UeU3>}<*SJ*KBDtyepa>ZAOFZ9cNA?fWoHI{nQH@Tun^o=sT5_E!R z2fz3u&1+xfrm+vQE%7prtF@_jF7yl0E494(E;6%8+#7+p-TiI>a4x`4OrU-|Ggmnw zXPaaVEMhSEH}p;l*3g>&fawx_4UfiX4tKZxS}&W)Cu_hxX54inX8PB#UBSEqn|WjI zQh#UoC~k|TdpQ3_BHK{N*nI!HSA}OYgEAqw&57sX1`$!Hk>WDbOP6w*X~@H2`ck1Y zygs3kk6;$0e#?1BtYdYP5x|?(-NSJ0Bch_XpC-9htz)Oz7~$P(oWI_-vSA#E1(Q{XkdF5qsK`ySM6-T>xQTw=p^m28l)LQLX6XSVrIo|$*}pA{Fl;Urp!V(K2ji(#w4Jpn+W{xZlC zTW+&BB>?C|tX$`Zce`)xO*J!)ER73JXj!^?v$1f~72P>mMu2bMHYR{M8XOZ5FcjvW$Dx z>~O!KzSZyZAE7HrzB~G~EZ>DM#*B*)){jV=?7sc5S4|EA2gWx zFrIlUKCbnzqYU62x&}osyW^St@qc|)>;F*lXUEj@zU)-Filzy<*ao0KUy>P(UGmD$ zFw3wePGWuqj-u3Y_ZL4;xgY%!htg6U=hAV9ByGpB1IOp_n~&dm{N<8-TYXx(1$vlD zVq~r{Od*aJ;&>ABQjng)`8Da6DP|nwiWGQ@UK2qpMNGJ_@ax3yPUJNsokTn?cAuK5 z$MI?4Eov_OGUe^(5F-Ss1&LdO_HZ-y%b!4JChpv>-4fevd2A+U$4wcnS*^E2B! z!@@gBJW!Yu>QbrQA3-Y)t5lX(scKXV!6*GR6QX5IJ1y87AaolI%l9NEQ=Y2+ITMlG zkS9_e^i{~~1b#jirU>`tnZTz&-UiCsLwUlE4#H|WH&fhA8S5zHP5Gu>uwgZpE-+$3 zbH5REFih6tGh@8BD>GU)o2BM>Tf$5fp8I86+r6C_7;9Hp<7e8U!fbX{t`m0|Rod3} zyG~SS?F!TInS8_`-j4f}+|QK?cXjHO{3zseyj|lrXv#m6eDDx4sLvmhd?Ss11B*o` z@tEXZCzV2w5auhrN|pM{OsuvjdpVW;X}Rowl2&1pzhkEOl)Sf}kN?`vCkgImXRWG= zH$sSlr||}jb(LgneV8|pai;45hK}PIzg@%gr6`W6Ub04(Bde0Fu9RRjkHc)%`uZ`K zkL0y)9xF9Q8Tl&!BM+Kp<};?{`5v|<4Ghv#VaL}r{b?q&N{}y3R`5W0!KncQBA7JT zwb2Zauf_kGd|l1^QUAz<@j=D3mz|IHa2oH9)7%A!02N*X8`>bFQHV*;wYQ>n-C1j< zR1FD(EdR)7@Dx|R%J%NH+I8Ppy~mv8zXN5N#$6zhk;Bu+s^q10p~gB>a*n6zd6|YX zW=Ki~s_y*D{kCYfCR!zTqeyq@OmRB3YB+68JEzKh)FLO8+S@9(cY8h; zOExN#rS$2vZ_n0OPnN8cz(eC?xu*JV$-2ySfa5 zh=JbvxwO{kv``tB>zo~~8j&jJ(J3Y!%XPr^$ZX{*Tvo;v&$yCiLUgotO?QxKzu1`l;<5BD9V#uJDX<>U2Zaj0n69O$&ST+z@x zHHgt;F8n)2YkDc>p?V}AQV8+-PR9CS4>xGL1~br>o{yok6J?!U8v9D*5VZC#?4j=O zY{HhOM}#jTp+lSIxl(0OV-cG&md3#Z61NqxmU|z-xji)>Yf&FHjeYK6`hE_cv7C}9 z`=oS3cFJUJVTNRS`;)r!xU7=REu<$Fvv%8M)2>5A(i(#y0quwANdwLg{^tB6I(H>9 z#w20n58bIc;2l`=g_|zZtlBjA>2YGS)vr zjgk9!*zu8W-~FOM<{G&&3oq7TuB;hKW40!b`mrld=h_?fkI~>kE2eI<{Nza&{gUGiZX>o}~EKVt$uqopRm#expG zv??X7Jay_et}GQIz3=Wjpt;`PH?%DZ;N$spTVCq#@CyRer&lO_I>)u+7uVGO{_d3X z2K4u-+Z{f=!^$|&-%A3H#Qy%SrT#uEAourX>hCL$2m8CMuL}0%!6<28e;+pB_?7|3 zvK}OO{gggB`g`br<4JwT=Vx%%UN-Y4w5 zA8yEcl^=|wp7q*Pf(=ZX%=`Gk>9FU$tjeFo@X!NfsranEJhzG7)U0o8e#C2|MFj>c z-g%ItHa33mwb76P;X4Nrnyq-MTr9yRo1e&h)wx5!LGbEd_0oH{3mKF{{MN}sT&xh& zz5kf|w1bo@6pdgg`l`<;!@V%W5r+)dnF8SMx-tIg9{8e8klzUI3wUUS*n#c1cHP{9 zxdJ&Y$paEkT=xgk-X?skQ1 z=B9#a##_MSI`qjly_xVV^Nm*3@f;h-FnD(8Z@1}32FcgHxK6&qrXLj~|2Tj=)uzu3 zlD`{3o^I1m3zEMbK+dxM;|sWe_dV4X$2jEeF){RG=R35c6yc(6Hq*5AP~9UNyf&aj zY&@nEp2}U!wEAta47}}wJ|rbTJPK|JD8KJCsP~Xh>psQ(0}0MI5B-*M_V5jqI7X~r zh&TB9w-~b->+e6F6egG4pU;Soe#~iF{mLuF{U5c*+$x^|K0|!}qrMENPkp|3aS>z} z;^OXBKQyiszEXkNh-Eq}yRXN*1n>ssUM>9{&5f=S#x;zo`v_CkPI-296%(QTRp~dB zy0?Bqz^O7tJK)?t3?}w}P>kL2P@=>#&Vx%7idUac#1f`3TPNtP)~EMh!Irk3f~4Xg zC(9wrUC0XliTw_rHz$j(###M-`y<=rGcV5S_V;JFl|!N~JDTIMt~d%#NNzGn_8VBn z{^-#X2OeT8VC+$cT-sqaZH)cmDQxLy=_2fR-X~^}o#J%(@phg&1zDE++^PC}Sl&dq zN8Bf75F3+DY|QCXnBTFb$5!8TpE#N56N&!26QJi78r`3tLO)s~;FHqJiWuvOQ}(e^ z4&T4C|NIo@0!6=r0b#TQPQyS44h?l$9OP*lf!CU#!Ld))@ASL#1m_jY@)_1Rn9dbx zpl&6LI*Gf(zgdj}2wE$jqY`pp6|Nu$nt_U`$iXc!KVrW~>r$55ROvD%(3ehDn~vJ$ z8B(zcHD%1T!J8U7jVPnVI+w5pWdr~inFAYhst7s!)D)wv*UN@%;4aJu^*#MM8|Rq0 zvJl@eJ}S|YI(N7hH!JtyRWllWqhjM+Ia8E zzs72lVjpi9$+R5XWp=+df9Hmd&e!IX!Qb8|71tK`vISaCPN4i;ri}=dPe6~@DM%XeA%9@ zNPDJLg0{ku7`;cmJp=}XH$jxDWm0XnpbSTt0l#zXZC{Y(wU$>Kx1C+HTChcX082^g ztLPj(r}t_Mf-OVVukr4tIqm4b>q(&L$BlsbdI6aAjdI9s`jV9xE-?=6Fg(Ql#i88X zF^YoB?fRjN%tS%Xc7Kp*s$RcoNw@$=@)(BPwz6UrD7 zrLRdz8x&i@1dNdy)^?vdX#}fFVTLbCd|R@7`myt- zBdMRLZ0gqZ%qv$i4T~Od!Gr`5kjW}%$PqtlU6knpa^3BjuS5(nUA(s)QJ>gORlw{b zb0WVAb>!8p)@z5cp-tx-AvblZjs#akLYSefINoTC;xovUB};?rO8G`yF+C!}bogGe ziyG`3S;$Csqt;7@ogd$eFyT?mj|&XTbbfW~vIU*zd-t$Cehv!rIQ}1*6}HnlRz+sQ zA&O=J3{8#AR>Nj&1!f#`uJ zp3*l9!{Tg1nZ-I~o#&F=k9=IJ@It^1)T?ZIhE)3x7_EQ%tXepjlYwS)r0P@S$S3ZLwS>Nqe7hX+Y zUUtI>mVr&Lk$o))Z@>Irv4D&jeh*^?^0f#7m^TAo3y33t?*s{ua*uU)PxZ_N@}u0_ zdLV&^=m5_QW;#ButNpjvSpRf{)Ag5Q%BMLQc(U?X_uzdH7~mN9*T88S-p`dE2ebA* zGBC@!`h)&QJn=!!XnJ9uY$uq3K}3t%Gi*Z@V|sG74fDc(97}sEFrUJG6XsHuBi(=! zO2vev8|IwzJ&ZU@Wh2hCo(ZX`35X#xo+iKD(U_nbq`gIqC2+8M>|u;Aue!ByH9}oONcrf!&K_L8LhD1^XsgQzsrO<+bhw-oZP*z;j7ejCiYfV zV7y&Y^@wT+A1Y%F>*a2wKl8bY5~76{j=!j4y0+W zPrMTm9K)qGq}npDQjCx0Et6&oXgpaUd&Ym6V=ezP)6{(p*7-N!F4z(qNjKb<)A5%jOw1D^JAkStI-U$qG{7)ZAiUG1IK=$20dv>D*7u-LL_SiEm-Y9bw|ixv=S4uv_2g z>cBy1X(?7hEIe}no>0E~AW$>+XyBrDR^k@-IjNN%^y*{aq}DXD+dE8?9M9{Ax!bQA zjborv0Y)1Cjv3Bs2y^t(K>_PyhSig>`W+!kC*<8KXd;A+bRjClrim2tZnI_N!(KTf z!`fAXD{Ve$dW_N9QR2rJm#tfxHDoGwV=PP!?3_Qz(qhFq9AZl_w!f2!MW;ud|Me|q ztxcT{ovY2s01lYvP2#GSw&lmpj6L|zd(LzpAi4GVILTCV)%xyy>dS0;7ImR)mXEy6 zx=mtu!*n*vnw2ANm1VQeYb2X}g=DkV@~iGm^8Q)l`ZS#^H{pdXk2VSTKQw zhQgWstC3fgR)&`bFFx1C+l_ab79=407FRvxn26k#?8KM;RC#TAQKsS2!aW5_1*#0X8rq@ zerz}=VXk;PTRcSUMYn9L)Q#^WsAFjA2S)5oC2|BhJULA^ZCnlL|N7M_0}QpIzL0I} z-E0X4R6kCvRD2_B-EV!Q*X!T5dCoSin}gsRjh^t;?e1>@cVS-L<*vV~rp( z;_Ky)cYja|=fJZNcxm?flOYmnPUIna*UvUE^`QWK;|JZV=iS&vL6GMwn*Y z&&ASq5x!xBd86>a^RvaJRI!I;JzLZb_1alH>i?o%E;v#}J0h%`iyfMn$2BzZ42idj z#oV-@J9Qzkya-kBLvBS1CPnPCaqf5k`qW8D3GB2K#>I{+)P-0_{cNwCb9)6cv$ggL z>Qwl>^?q9-nBmDZakOTYZnkwzhD4KKSz*X0FRy{(r}Wju4dhbCDSDmwv$C9 zp5K%=2V#xJc7M<2vpaWNySE8YQ2Y3f#!Y^3$-Y)=_vb>__NTi?cQj`D-Jb_O9Q`2= z2sK>97qM3mXDmMc%3B6o)*vnl+a|t9s;n}hu{4gIkJ>oQ-Y zhc?omH5g^^u+~T@ z5$1b~Zh4ccwl(yYEB+mS$2>(R`WbR{K|>v_ufi)8fw;JPG|}au*1G$+Fxd#vkvImO z$&o-CT*ncuBXJZ?D`Lk~6659iRO?C_=}_y?|2!I(dJy0)eOo#ZD6h2StSgd5N7OUE zmpkg$#P3yMx^$?+gl9B-1_GSGV$ZZ(a%4~yi(qH2w|w4PU%wf86~<#ok>w4m5$TeP z?H|CXAfI_NRg>9AvS264g`HhRcmUK5x)?Nfig7c>V?7^FLvl|MH#9gTX9b7kkGXR6 zklb0+A{dgdlxb6e3&a}%Y(6m+53p@MJO0nZEf=NE-_iHqrMBc{k^9rmotx9jdc>1h zE2~`r+w-CKgp63Hv4z~Ue={mVW|21mvJGaggCL!254jmU#vt2afaH#PlW?8x3)`hy z`*}s|Xa(vQ!b|XwmiFoX%{q@7;VczTgdU#;&1FM4jS?W{4&rmvW;HBP+Ro11nZC3l z>Q3v+)BRg4%b+5WYDT1R_kmf)m1s)bp{C3E1Z?>&=tI*&&`5oTZP6B$3`1ATKN_76PPoyb_zlA=Co%>NH2hur??FYX75FmKyzV-(+^MENJEFkE)wHMvTXK=A(i2=mFF=!MoD;E#|=F^oI;V$z)0CS^k zjztr~zT@h2Jreo{IzqC_G_eRK8V=oo?3pc?$b$ z`l|Qwuu52)7rs2$J#G4oFfi7Ap&*-1^*$B0H8eWxraihD+-gJlpo1QR>9pj1_lM+W z(-`pA_vlxK&#vSRqG=zqlT^c!H4YaHn_@;<&O)U>k%3Z7An8y5nFHKxADe``rAj>C&i;Cd{HbudDbM;x*4fia$ zM%oJ3`L?YflJ`7|(KbuwW zh!-^fA8YR(*Tj|gkIzgdS4K++APB9=a0`ew2`U#wNeCFwc1cu3TKfg8h}8B`)~>d- z&yv_;uyz;Hb_Le%CIKo^X)(Q7m1iL;qN3Z(=dcyVlaX%J+R{0%E(b-RJjx z{r-p!XJ*cv^EsdM`FzgjDhfAA#y3{-f|O1KbWmTYw-Tsrm+E-~eD9Ej6%8&N&F)=H zgi*nT%lYt?7RBEcr7tUW^q8xI!V^P`Zv9nJ_1VJo_jWWjbv9{7>klW?w`6xv}!fB)ufb*~JowX?#t>Ewf{iryFcNw{&PM4Q!jV;f|8#;G}NVRG{l zLl&!)lY+&{p@AN5v;qlwN-M+!J;*qrpi#4oXi!kHZN=+?9ieIkQP4O<1r3@@CN)bP z3PC}G<|VH~L38bec892-!JWcMFLXLY1r3_blbWBhFMQqAQ4bvr9Q>Sjo-KC>rOWVX zM+}TBp@CLDTvjDZ56MJAj-kqnRR|ly@I$WNWt4sN6sHh|;e!1m#5E4s4|T!$O?LaG*Uv{)MW3BY2nnzfTI!6WdDPsVeCVi}WUY^V=cY%A19V z^@eR_53#L0`Zk_-KKgdZw(?4$uazi=pCC4r#m*>y!kTOy|A+4`N2mlt=}7b6&0e7*zEb1Zx< zot{G91v0;tm|xHr#QaYdfjH;$FSLl?fg)lEQa_^HBzCG=rQRH75- z&BK-$*5XjwVv^bEEqvwXRZWlg`!=tt2zltwL}J4K@9=wbFuH{M+cr!O30O+vz<3uxpdCXx?!6#MAI&xEs)`Ecnqo59PaTug}W z3ki=vbN-3VAbzY&k`fhRUr~spvcQAsLay9V;6auo`YX;aSyaaJl3ZdBC@N>mWyZU-R(Tmq}819PjIGl$?O-qsSb!N4Uu za|jg=#tk&yR@ig~71Ts;HxH4swY$k5L$xH}B~*Jkc(m#F{Y}kxiib+1xFd=usyVfA z;2$Uy!-ci1AMv^1kL3(o!f{BP+ZRfl+sE`s-{-gptRFJ-7K;A0afQBn$a&}-u?hGk zAphewf$6#prT5_Ex3>Gu zkrqjAN~Thq(x2Ksh)qQ8Yu9C;{9q#i0zTz!yLfTE`qRJF-9&OS4?apAxa(|O_n{YI zfkm)*og&wdS(J?8Pro9!|Fm^){7nOk3j%Rs9^>ye41`^6Y(8J98u5Nc0>ypqX8%pp z(g#9e;&)KJFNBx=sPdJc?S2Xo=f34<&y|dJ|Bk53+UF#v>4FFy&nWPFx3(y~`@=n{ zvVm`}AlgHSYX2S^+}+%)DGm(TP^LlYsidmjkXI$oK>gB^PHph$oROnB=LaH5fVhn6 zU#G6!QdxcU;udx7IvCJgT@;KQ#OF4yz_*6b_H!hE&tAb5zTzlV4O^6J8nsDP2EPQb zbGNy|{mRC&a4s59;-q&=n`fV`W5^1Uyvpfkq1E?p5%MZe(`=F#_--MVmtirNs}jeQ z58}^aF#tvA^vA3N#|54KceMcVh>!ckCjbXJ{V#}4KYB`@wW&W*oo3Z7JbKZpPD`vJ z!NZU9gGV3{zj2A;{j<`NEC0GO?qU30Q5IfBM~<6)G@CxM`V8db`^AqFyU(UKPx!mW z?%(Vo1?foKM#XwUiK<|i*iUIIMz=5;-8)ua0@=EMyh3t_d*8v{)eQ}{IMWizlL)f7 z@n}iK==fiiu}4d^U)Nf3kB4(?|H_hj)^Sp&T@kL!wYu_4^vtTGJkR^RL@JlZ0+I#a?o`6DR%D`$`f2HXM)18H~M7T7L(`6eOo&RtoKX`^%JeUwIdI;o}Wf}Vkw}ve;Pct za=lMm&mnC?)98-rGtjc>H`amWSGLO0T$dul;60Vf5uXvT_UM%8vf^Ci#*JhM$Oq2J z*8SmzrpM+yD)S)sWmMC{+v_VfZ~EgIhk!m?<;_o?DOqu`X+;y>*aF78#p>%L1&bFT z30Kg!kO*wM&H#BZ(Ar4nM(e=5af1*+9y82AK%5oTi{FnPl-mE2pT+8>BVHBHi@qlQ z4i+G-lH|@(1&+?CDyFy%aowFUXX=jTm?SwaIT9JjO>)L%QJ5@BoN-`xF+NZQ!lRdV z!Cg9}J!56DV6a(5U94UyD%qoRq|n&&`HPI{LpXI?uvU^87E81_@6t7XVI8}$R^S&F z>wp4^c#&UxMsPxigFZg6@A7G zR>LGyy{<8z+ez323FbHd_hmgBZHhB~al&W)!X?pqBsyYK{^8rEra8o@%#?t)`WjZ| zxz%3efo{|i+j0=LWqV3OxT_0g^bQ5rSe=8 zGp8ORCh{z6M}!LG@XNC>nI>jls5yR8bGC`e3N=rg)Ldj@Y@z0eNzF@4OmV1r%B1F{ z#;_3pVf=V=&Gg)nm=+lpv zpFcj){WE9H-02**DF%5)N09~9ysaOC46f0esfq zaL4iR4_{8;VP|eA$DB9c_Z6uxr$tPbf;~xIk@(I!TtPpIC&G*`zlKd8> zTY-o~mtJ=;o7)MY5{Fsx%+hfi@i9M=VthX4V@@{y62(P@)SCWf zN)VtL8B()#Z@Dj_PC28w@XL)G=M-&6<tzMU+a7fweD8`a+UrU4g^gv&qiB%cC-=Duw z3`){v{qUwejh z-;E9YFvgcjo4*^=eKU4xcm`DJT$tZG_IKs`Tu@2v+7?jK-lx|Dl+66rZ(BdFuAT1L zd&*PB?s~-2QR^uqS;i^d;8}DbW2owGsqSNR$2Nb2sM#^RU!5KqR5DGM)%}0&zoeuu z4mUwx1(u z$Hs-$#P?^>?lB|j`2O1a_x$XB(-;?f?fvwj)EMVl@gbL<=(|JnM40flk39@YZQ!y{I(}%| zca0Ic+ZMYS07QH;bV=c*kiFz4?1ynU{c4O$z4o1mAy{gc{IlfBA^PfQ-N%L314?(<>^n!^KO(&UT%cMD z#l~mGBpT;CgtQ+-|Jq2D5?vDPzWP=J2o~fMG(Zs>4FNDB-g)-u4oQUb4YN@88%y=QD>|quf-x+Ibb7@GmZC~n164usiMgaj)@*zEg%Xb$- z3j;;AV9SX9;Ll^+VWHkEsmLkMdXCUOuoy@bLe0v>cUylGA@-OtCYJAQ3jokv+Na7dAB$`L}CdoK_d+q;D2I>GF z5*>{n|38IaD1Y82pFMTJB`5tLPYm`?N=%aONqf8`1lsL_E{sR@4&acXDI>goyMT99 zRP@@VM7NVkn}oMhG+Nzn?IDSL1$oQOZ2PJt!%&|QUb2k5vx?DWVf@jS0%K(1BnM`< z1W97_#PW~)l@ftuas+Xu$9=h{pw;&%x^opxtry|nje{Mh`1TWK@Bzvrk9UdreKy(u zt>1-9(#;);Yk@x?Tmex@sX67;gr<|!aJp##jzF;!HJrl78o%^ZP8sofh|Auq?k|1Q zPjz=)7uXStN={IcHXRNxJ$*xS)Ty?X^Ehe-nbH^W&OYp zR~x_lPJzX`Bwq7mxgC#=08W_+92NFjH!p{#(zcipHD87BH zs*AEjQjqP}v5}R3&hsGwIBG1uh4?cm(U~B=a~p|Mc12S)PNFceYAY(udDZ>qEo07? zmw8YXry7p@k6Tb$%bM`UG0NhfRa_KTjX!XMiz$RoMd5qrB%Cm@!dNt0v*LhlLX0Z!~^MbU$ByaN;DV6m%-O1KoK8&tL5d8}YskrHZ7xPucio z>#Lu9K=djfw7d$~#I-`XQuGSeo2Ug<&ATK&^EPjlL~jjqh|i)_z^5hu zu2g`X%1gf`OUlhOC5VMTh>aP0H&=z-i)1F;{?EFTbi;vx={SG4cWQ?%%Vf6Z9!b$J zE%eN)HIRT~Eb2(hvTzHXX36I*UdobB363zN0+x6#Pe+%!`;c5dn+a`}$4KQ(-O-Y9 znz&TjP()ER1IF8zRTT6?8*DqDIR{$d{_OJ&5NaFGXPqy7j;)HAZi$G?E9|cvSyUtQ zCzIT$mAjS!@-?#BwYA;eiaVtfLn95fYMgZy5B~hk9GS(kkSGgb zZ7|L{29<$?C$6{O9JgrLtn4SaEpsRiTtQ&IBLvS2WcvWT#a zOfWuHLQI5{LQj6K$2E2>3V4Z+JV+x-e~ow(32kI?0M4}(Cy)@|ViMvjRtrNl80atr zSk0acD@~^Ez6n6#lmA2qP0R?oX?Z?9RNJV*jq`@@0HKc|%5ux@hioz z2EY69n{1a2;P2=0o9Cn|DmJe-SMnu~GIg@}Dw1n(v_w0)ZdyX+O(iHPvPDfz%cJfS zWDeQ3?>7qUZsUD~jMr6Dn+C6x$x91nRT>uw=^UY+pV_zx#AKg5x;w3TkF`b#-!6Z$ zzO@nepMy<4@E>yckzhke6iAN=O%zTLjlV>vJG+rp*!7svXi@~d|E7f1V+A9rse z=hhAWl}cZm1HL}{GJQ{+>QnevD*Pw(pV&J;KHXBuuZ&CmNUwBn%02;^F3ZgGTFc7m zrp38E3Iy9i6ZOK_2G$foxi^Vghxo^#bilw7er!_EJPgcYy8iuRmM-FoCA3R;SeV83 zy%UX69`!I?FO@%S2@HxY=ENf(+pj57(B---mS-vS+Jbk8@)DniV<9daxOiav z;{NfA`^Hu)g)tlpJ^QO`L*gRQvt??6c*pqts|FO~n#yM)|M{Xtz7532VIzeJzJ3)% z%{lri3KI~)GiwnDJ(Tfgl6U9JSHZue`I6x*y5Uz4s!f+HXU+wZzXXXyIK?<-M2VkBARM#CaRf zBlwOmu5R~JF+ceB+F@M&?=f#zc>Tf6_4W7qizrtS9KhygMIS3^7e(v2Oc9Ul;i(GUy`_<%e)B(*5T`Uk7Pw z6Pi8=jf3b0w-eFUF~zt#pZE`iJQT_#x2VRQS}};#l4`w-Qw>5r1QBC?oEw3-F3bEE zv+nRP3*r@AepA+VV#l5DE4LrG%?emw)!1;(BtK?Sfw03v6c$Fb19H-#=jC$v-4oKgoD#mCGx`QT3VheA!+QIRC`SzwP zsAY;Vl__KCAcNMBIWOY%$Z zimQ&3cK(Ar>zuc6U>U$X;wzpws}mkLANWUdiGJaR_vteHp<97+ypX2uhei!j$&=!f`WInhQ zf8UB9?9>p8ip&O3s3=`4_!YuhB#Y6%?W2* zTo67W6bmF5&xkqUh}tuLXUG);sR$%AFA*vedbGNy#)PaF9?~q~B|>FFGzAX#GfXNY3QnP=&EO& zAM1n+d=9ifGCum9Ar^%rsQ3yPSaWkfIO26J;T1n^xo}KuX)ZkkRW7bWUwr1Ozyd?; z(kLcKfzm@rP2s?Wkb;j~{KuH!tVWn6{GHzf$iIg5axjeWip* zA=OFQz>HTW_-IA0&raI6k@oI0XfMeS_~-EH$fxUjzpi)R>&llj)kg;M8CO0VZIw6Qx@w6FhvGK3 zNg)Y{^5J|f)SWKKkcZV&hPoGdptfrtA@0|08376Pd+`c;W<=aGPijXbv)XsGD_ie+-H>GtS}Bi}c3GK#RbsMAkGyU)tU7FgJf359u@V!@kQ{{D zwI-Ifu!7(@2c%wY4vwJ=A1JuNX3nNf1r+MUS_*K%?1}!&WS+4KLn_X|mkowQQz3OE z#T>WlGcvm342wkK!02F{0RSkrKY-T=m$dF-1$EJ1gReOLpPFV%W=I}g2 zX%izMuYkrcfnSWYcHMvj)2XL~JX9EQUk3~l(8Id6;hT!y-& z5It%w40UdWIxpE=_3U=-3T;J-fj5Wq&pxEhF!0Yls$F3?2T}9c-)XG|-g{Y#Y?{bd z7Rj5Vcylywo(7|}!yI8Ut1V`Y)}ck3!L*tx8I@*yfI77gwka z>&z7^v{f{B@t10cS%v3?hr=B76g-B9g(tZxdMX~Sz@La>H&1cUH%z)qZk=0ahBKwZ ze8a^r)UTkEFSHlmSNG%MeeK0zbuTW4wTP|o;^MFtp%zWJ=+;8U(&D03d+yxkix?`e zF5$Ho$JC!R!wc(`&9LV5_HIV{zow?m&{bc&xOwGvWf&18K35bf;Yj#F+t?$OIi;Vj zsgqGvQg|6vtTR*1SnHBdz8Odyf(r>y zrru5C+WBCacTf1v0LiYigl>LrX>bYEbUFOu#jpE^?!B~x2`-TYWmG^$pBq+J99H)Z zYY%KUBYg}m0y5|)*mH+zT<7Jnc`uNQis#9{;2VY`+9f9MX-GPwJ2U!+%)xxR>2!D? zpX%@by7%C{!F(o=FA2z4lT0e^Rl{MeNhUc@YYlg4O>&}atIwbf)!4n>7sXzB51K&= znqCYCKK1r~T~Tu{NI_M;1YQ z{R-BkbfAs|m5`9q&BCvkqD;zV_-n79G1-J9QTVR&>Mi(gJ@4(21dw0mc0JR1>C~&g zx#dYF-NsEn4_m7;>(Uelbugj6Ke6{Y9Y#ToB^-K=iqE4?`BH8U*pYr1W_uNhUkds61# z{NnobfQJ3x{Mg9pZ?OH|TzKP%MsnVVi%9Kx@5mYY+y}be!`^f6yFho}d|DBZbxr$> zX~?1iF~z+H%)963ykyGs#3*$Qw`x=U9*tC+X5MW|@@Ql!*)u%RX}pF_X^nQp<}497@(3FLHA9#+?>$7FY2z2WjeVrs2ym zD*h?+bBlr+C?AlwXhfkOL2r82@5Kb*fTqD;rR6^eejHxZqQDw%nwNv!!>3Sr9a=0Q z781{Ro91wrDsQ1u?w1y2iY0NePt$sA?bl(S+{UYS|1Ah5*x zH_}3{ZW>SaDO%LkIa74(E!zFwE|p)kUjFG6eOQlD=!!et@Hx)HZ~%En@zy(ybdM6n z0$b!a&L(oo^4Sd%s!Z

8c=)* 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≻gn!mse_b+BA#j$B<7F16SJy+}{zC*SmuGy4p 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 literal 0 HcmV?d00001 diff --git a/pc-bios/meson.build b/pc-bios/meson.build index a7224ef4699b..54729278e0b0 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -56,6 +56,8 @@ blobs = [ 'efi-virtio.rom', 'efi-e1000e.rom', 'efi-vmxnet3.rom', + 'esp32-v3-rom.bin', + 'esp32-v3-rom-app.bin', 'qemu-nsis.bmp', 'bamboo.dtb', 'canyonlands.dtb', diff --git a/target/xtensa/core-esp32.c b/target/xtensa/core-esp32.c index 20f5644cd650..5a208b210219 100644 --- a/target/xtensa/core-esp32.c +++ b/target/xtensa/core-esp32.c @@ -9,7 +9,6 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/gdbstub.h" -#include "qemu-common.h" #include "qemu/host-utils.h" #include "core-esp32/core-isa.h" From c584eef06617fd67fea99efc432e8a41188ea569 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:25:50 +0800 Subject: [PATCH 29/56] target/riscv: implement Espressif RISC-V CPU type Espressif RISC-V CPU has a different has way of treating interrupts, which is not standard. Thus, this class will override the default RISC-V CPU behavior to have 31 interrupt lines. --- configs/devices/riscv32-softmmu/default.mak | 1 + hw/riscv/Kconfig | 4 + target/riscv/esp_cpu.c | 316 ++++++++++++++++++++ target/riscv/esp_cpu.h | 86 ++++++ target/riscv/meson.build | 1 + 5 files changed, 408 insertions(+) create mode 100644 target/riscv/esp_cpu.c create mode 100644 target/riscv/esp_cpu.h diff --git a/configs/devices/riscv32-softmmu/default.mak b/configs/devices/riscv32-softmmu/default.mak index d847bd5692ec..2c0f262d91a1 100644 --- a/configs/devices/riscv32-softmmu/default.mak +++ b/configs/devices/riscv32-softmmu/default.mak @@ -13,3 +13,4 @@ CONFIG_SIFIVE_E=y CONFIG_SIFIVE_U=y CONFIG_RISCV_VIRT=y CONFIG_OPENTITAN=y +CONFIG_RISCV_ESP32C3=y diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 6528ebfa3a3b..39bd3adb6234 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -84,3 +84,7 @@ config SPIKE select HTIF select RISCV_ACLINT select SIFIVE_PLIC + +config RISCV_ESP32C3 + bool + select UNIMP diff --git a/target/riscv/esp_cpu.c b/target/riscv/esp_cpu.c new file mode 100644 index 000000000000..a55102e5f648 --- /dev/null +++ b/target/riscv/esp_cpu.c @@ -0,0 +1,316 @@ +/* + * Espressif RISC-V CPU + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/timer.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "sysemu/reset.h" +#include "esp_cpu.h" + + +/* CSR-related */ +#define ESP_CPU_CSR_PCER_M 0x7E0 +#define ESP_CPU_CSR_PCMR_M 0x7E1 +#define ESP_CPU_CSR_MCYCLE_M 0x7E2 + +/* The RISC-V core in QEMU doesn't support the triggers used in ESP32-C3 + * tcontrol is not supported either. So let's override all the debug registers + */ +#define ESP_CPU_CSR_TSELECT 0x7A0 +#define ESP_CPU_CSR_TDATA1 0x7A1 +#define ESP_CPU_CSR_TDATA2 0x7A2 +#define ESP_CPU_CSR_TDATA3 0x7A3 +#define ESP_CPU_CSR_TCONTROL 0x7A5 + + +#define ESP_CPU_CSR_PCER_U 0x800 +#define ESP_CPU_CSR_PCMR_U 0x801 +#define ESP_CPU_CSR_MCYCLE_U 0x802 + +#define ESP_CPU_CSR_GPIO_OEN 0x803 +#define ESP_CPU_CSR_GPIO_IN 0x804 +#define ESP_CPU_CSR_GPIO_OUT 0x805 + + +static RISCVException esp_cpu_csr_predicate(CPURISCVState *env, int csrno) { + return RISCV_EXCP_NONE; +} + + +static uint64_t esp_cpu_get_cycles(ESPCPUCycleCounter* cc) +{ + /* Let's simulate the cycle count between two reads of MCYCLE thanks to the time API. */ + /* Calculate the time elapsed between now and the previous call */ + uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint64_t diff = 0; + + /* If we are not in the first call, calculate the difference */ + if (cc->former_time != 0) { + /* Let's say that we have 1 instruction/clock cycle, so 1 instruction/6.25ns */ + assert(cc->divider != 0); + diff = (now - cc->former_time) / cc->divider; + } + cc->former_time = now; + cc->cycles += diff; + return cc->cycles; +} + + +/** + * Convert the given environment to the an ESP CPU. + * The environment is the field part of RISCVCPU, so retrieve the RISCVCPU address. + * In fact, RISCVCPU is overriden as EspRISCVCPU, we can then cast it safely. + */ +static EspRISCVCPU* esp_cpu_riscv_to_cpu(CPURISCVState *env) +{ + // RISCVCPU* riscv = (RISCVCPU*) ((void*) env - offsetof(RISCVCPU, env)); + RISCVCPU* riscv = container_of(env, RISCVCPU, env); + return ESP_CPU(riscv); +} + + +static RISCVException esp_cpu_csr_read(CPURISCVState *env, int csrno, target_ulong *ret_value) { + EspRISCVCPU *s = esp_cpu_riscv_to_cpu(env); + + if (csrno == ESP_CPU_CSR_MCYCLE_U) { + *ret_value = esp_cpu_get_cycles(&s->cc_user); + } else if (csrno == ESP_CPU_CSR_MCYCLE_M) { + *ret_value = esp_cpu_get_cycles(&s->cc_machine); + } else if (csrno >= ESP_CPU_CSR_TSELECT && csrno <= ESP_CPU_CSR_TCONTROL) { + /* Nothing special to do here */ + } else { + *ret_value = 0; + } + return RISCV_EXCP_NONE; +} + + +static RISCVException esp_cpu_csr_write(CPURISCVState *env, int csrno, target_ulong new_value) { + EspRISCVCPU *s = esp_cpu_riscv_to_cpu(env); + + if (csrno == ESP_CPU_CSR_MCYCLE_U) { + s->cc_user.cycles = new_value; + } else if (csrno == ESP_CPU_CSR_MCYCLE_M) { + s->cc_machine.cycles = new_value; + } else if (csrno >= ESP_CPU_CSR_TSELECT && csrno <= ESP_CPU_CSR_TCONTROL) { + /* Nothing special to do here */ + } + + return RISCV_EXCP_NONE; +} + + +riscv_csr_operations esp_cpu_csr_ops = { + .predicate = esp_cpu_csr_predicate, + .read = esp_cpu_csr_read, + .write = esp_cpu_csr_write +}; + + +/** + * Checks whether the CPU can accepts interrupts or not + */ +bool esp_cpu_accept_interrupts(EspRISCVCPU *cpu) +{ + /* Get the MIE bit out of the MSTATUS register */ + CPURISCVState *env = &cpu->parent_obj.env; + const bool mie = (riscv_csr_read(env, CSR_MSTATUS) & MSTATUS_MIE) != 0; + + return !cpu->irq_pending && mie; +} + + +/** + * Function called when an interrupt is incoming. + */ +static void esp_cpu_irq_handler(void *opaque, int n, int level) +{ + EspRISCVCPU *cpu = (EspRISCVCPU*) opaque; + + /* Interrupt incoming if level is not 0, make sure we can receive interrupts */ + if (level && esp_cpu_accept_interrupts(cpu)) { + cpu->irq_pending = true; + cpu->irq_cause = n; + qemu_irq_raise(cpu->parent_irq); + } +} + + +/** + * TCG operation called when the CPU has to actually jump to the interrupt handler. + */ +static bool esp_cpu_exec_interrupt(CPUState *cs, int interrupt_request) +{ + /* We could re-implement the whole interrupt process from here. + * The simplest solution however is to call the parent's implementation and + * replace the most important part for us: the mcause. */ + EspRISCVCPU *cpu = ESP_CPU(cs); + EspRISCVCPUClass *klass = ESP_CPU_GET_CLASS(cpu); + + const bool accepted = klass->parent_exec_interrupt(cs, interrupt_request); + + if (accepted) { + CPURISCVState *env = &cpu->parent_obj.env; + const bool vectored = (env->mtvec & 3) == 1; + const uint32_t cause = cpu->irq_cause; + + /* IRQ has been acknowledged by the parent CPU, it is not pending anymore */ + cpu->irq_pending = false; + qemu_irq_lower(cpu->parent_irq); + + /* Update the mcause and the relevant PC */ + env->mcause = RISCV_EXCP_INT_FLAG | cause; + + /* Recalculate the PC thanks to the cause */ + env->pc = (env->mtvec >> 2 << 2) + (vectored ? cause * 4 : 0); + } + + return accepted; +} + + +/** + * Taken from `cpu.c`, as this function is private in that file + */ +static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext) +{ + env->misa_mxl_max = env->misa_mxl = mxl; + env->misa_ext_mask = env->misa_ext = ext; +} + +static void esp_cpu_reset(void *opaque) +{ + EspRISCVCPU *cpu = opaque; + cpu->irq_pending = 0; + qemu_irq_lower(cpu->parent_irq); + cpu_reset(CPU(cpu)); +} + +static void esp_cpu_realize(DeviceState *dev, Error **errp) +{ + EspRISCVCPU *espcpu = ESP_CPU(dev); + EspRISCVCPUClass *klass = ESP_CPU_GET_CLASS(dev); + + espcpu->parent_obj.env.mhartid = espcpu->hartid_base; + qemu_register_reset(esp_cpu_reset, espcpu); + + klass->parent_realize(dev, errp); + + if (riscv_cpu_claim_interrupts(&espcpu->parent_obj, MIP_MEIP) < 0) { + error_report("MIP_MEIP already claimed"); + exit(1); + } +} + +static void esp_cpu_init(Object *obj) +{ + EspRISCVCPU *s = ESP_CPU(obj); + RISCVCPU *cpu = RISCV_CPU(obj); + CPURISCVState *env = &cpu->env; + set_misa(env, MXL_RV32, RVI | RVM | RVC); + + /* Since 8.0, it is also required to set CPU's cfg extension booleans, unfortunately, there is no + * public function to do this, so we have to manually write to the fields. */ + cpu->cfg.ext_i = true; + cpu->cfg.ext_m = true; + cpu->cfg.ext_c = true; + + /* Initialize the IRQ lines */ + qdev_init_gpio_in_named_with_opaque(DEVICE(s), + esp_cpu_irq_handler, s, + ESP_CPU_IRQ_LINES_NAME, ESP_CPU_INT_LINES + 1); + + /* Initialize the parent IRQ line that will be used to notify the parent class when an interrupt + * request is incoming. */ + s->parent_irq = qdev_get_gpio_in(DEVICE(s), IRQ_M_EXT); + + /* Set the user operations */ + riscv_set_csr_ops(CSR_USTATUS, &esp_cpu_csr_ops); + + /* Override debug CSRs as they are not all supported by QEMU's RISC-V core */ + for (int i = ESP_CPU_CSR_TSELECT; i <= ESP_CPU_CSR_TCONTROL; i++) { + riscv_set_csr_ops(i, &esp_cpu_csr_ops); + } + + /* Register all non-standard Control and Status registers */ + riscv_set_csr_ops(ESP_CPU_CSR_PCER_M, &esp_cpu_csr_ops); + riscv_set_csr_ops(ESP_CPU_CSR_PCMR_M, &esp_cpu_csr_ops); + riscv_set_csr_ops(ESP_CPU_CSR_MCYCLE_M, &esp_cpu_csr_ops); + + riscv_set_csr_ops(ESP_CPU_CSR_PCER_U, &esp_cpu_csr_ops); + riscv_set_csr_ops(ESP_CPU_CSR_PCMR_U, &esp_cpu_csr_ops); + riscv_set_csr_ops(ESP_CPU_CSR_MCYCLE_U, &esp_cpu_csr_ops); + + /* Re-use the macro that checks and casts any generic/parent class to the real child instance */ + s->cc_machine = (ESPCPUCycleCounter) { + .divider = 6, /* 6.25ns per instruction at 160MHz. */ + }; + s->cc_user = (ESPCPUCycleCounter) { + .divider = 6, /* Should be using the target configured CPU clock frequency instead. */ + }; +} + +static Property riscv_harts_props[] = { + DEFINE_PROP_UINT32("hartid-base", EspRISCVCPU, hartid_base, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static struct TCGCPUOps tcg_ops = { 0 }; + +static void esp_cpu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + CPUClass *cc = CPU_CLASS(klass); + EspRISCVCPUClass *cpuclass = ESP_CPU_CLASS(klass); + + device_class_set_props(dc, riscv_harts_props); + /* Save the parent realize function in order to be able to call it later */ + device_class_set_parent_realize(dc, esp_cpu_realize, + &cpuclass->parent_realize); + // device_class_set_parent_reset(dc, esp_cpu_reset, &cpuclass->parent_reset); + + /* The goal of this RISC-V CPU child class is to override the way interrupts are handled. + * In theory, it would be enough to override `do_interrupt` function from the CPU's TCGCPUOps + * structure, however, in practice, we have to override `riscv_cpu_exec_interrupt` function. + * This is due to the fact that the RISC-V implementation doesn't call the `do_interrupt` routine + * from its TCGCPUOps routine, but directly calls its `riscv_cpu_do_interrupt` function. + * As that structure may be constant, we have to copy it in order to replace one of its field. */ + memcpy(&tcg_ops, cc->tcg_ops, sizeof(struct TCGCPUOps)); + + /* Copy the parent's exec_interrupt function as we will execute it later */ + cpuclass->parent_exec_interrupt = tcg_ops.cpu_exec_interrupt; + + /* Replace it with our overriden implementation */ + tcg_ops.cpu_exec_interrupt = esp_cpu_exec_interrupt; + cc->tcg_ops = &tcg_ops; +} + +static const TypeInfo esp_cpu_info = { + .name = TYPE_ESP_RISCV_CPU, + .parent = TYPE_RISCV_CPU_BASE32, + .instance_size = sizeof(EspRISCVCPU), + .instance_align = __alignof__(EspRISCVCPU), + .instance_init = esp_cpu_init, + .class_size = sizeof(EspRISCVCPUClass), + .class_init = esp_cpu_class_init, +}; + +static void esp_cpu_register_type(void) +{ + type_register_static(&esp_cpu_info); +} + +type_init(esp_cpu_register_type) diff --git a/target/riscv/esp_cpu.h b/target/riscv/esp_cpu.h new file mode 100644 index 000000000000..9923e2539d90 --- /dev/null +++ b/target/riscv/esp_cpu.h @@ -0,0 +1,86 @@ +/* + * Espressif RISC-V CPU + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#pragma once + +#include "hw/sysbus.h" +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "cpu.h" + +/* Make sure we are not in CONFIG_USER_ONLY */ +#if defined(CONFIG_USER_ONLY) || !defined(CONFIG_SOFTMMU) +#error "ESP RISC-V Core only works in system emulation and in SOFTMMU configuration" +#endif + +#include "hw/core/tcg-cpu-ops.h" + +#define ESP_CPU_IRQ_LINES_NAME "espressif-cpu-irq-lines" + +#define TYPE_ESP_RISCV_CPU "espressif-riscv-cpu" +#define ESP_CPU(obj) OBJECT_CHECK(EspRISCVCPU, (obj), TYPE_ESP_RISCV_CPU) +#define ESP_CPU_GET_CLASS(obj) OBJECT_GET_CLASS(EspRISCVCPUClass, obj, TYPE_ESP_RISCV_CPU) +#define ESP_CPU_CLASS(klass) OBJECT_CLASS_CHECK(EspRISCVCPUClass, klass, TYPE_ESP_RISCV_CPU) + +#define ESP_CPU_INT_LINES 31 + + +/* Define a type that will be used to generate a cycle counter */ +typedef struct { + uint64_t former_time; + uint64_t cycles; + /* The number of nanosecond an instruction takes to execute */ + uint64_t divider; +} ESPCPUCycleCounter; + + +/** + * Espressif's RISC-V core is different from standard RISC-V because of the way interrupts are handled. + * Extend the standard RISC-V core implementation. + */ +typedef struct EspRISCVCPU { + /*< private >*/ + RISCVCPU parent_obj; + + /* Cycle counts */ + ESPCPUCycleCounter cc_user; + ESPCPUCycleCounter cc_machine; + + /*< public >*/ + /* The parent object already has a reset vector property */ + uint32_t hartid_base; + /* Parent IRQ_M line */ + qemu_irq parent_irq; + /* Number of the IRQ that triggered the interrupt */ + uint32_t irq_cause; + /* Interrupts are not always synchronous, so MIE may still be set to 1 while an + * interrupt is waiting to be handled. So, keep a mirrored MIE to mark whether + * we can receive interrupts or not. */ + bool irq_pending; +} EspRISCVCPU; + + +typedef struct EspRISCVCPUClass { + /*< private >*/ + RISCVCPUClass parent_class; + + /*< public >*/ + DeviceRealize parent_realize; + DeviceReset parent_reset; + bool (*parent_exec_interrupt)(CPUState *cpu, int interrupt_request); +} EspRISCVCPUClass; + +/** + * @brief Check whether the current CPU state can accept interrupts or not. + * If an interrupt is currently pending and the MEPC was not set to the reset vector yet, + * this function returns false. + * If MIE bit is not set in the MSTATUS register, it will also return false. + */ +bool esp_cpu_accept_interrupts(EspRISCVCPU *cpu); diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 5dee37a242fb..0d46014e3357 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -22,6 +22,7 @@ riscv_ss.add(files( 'crypto_helper.c' )) riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c')) +riscv_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp_cpu.c')) riscv_softmmu_ss = ss.source_set() riscv_softmmu_ss.add(files( From 167401b7df19832ca2b32b3e0829957deb25c7da Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:30:07 +0800 Subject: [PATCH 30/56] hw/char: implement ESP32-C3 UART C3 UART overrides ESP32's UART --- hw/char/esp32_uart.c | 23 +++++--- hw/char/esp32c3_uart.c | 99 ++++++++++++++++++++++++++++++++++ hw/char/meson.build | 1 + include/hw/char/esp32_uart.h | 10 ++++ include/hw/char/esp32c3_uart.h | 36 +++++++++++++ 5 files changed, 161 insertions(+), 8 deletions(-) create mode 100644 hw/char/esp32c3_uart.c create mode 100644 include/hw/char/esp32c3_uart.h diff --git a/hw/char/esp32_uart.c b/hw/char/esp32_uart.c index c8c27275666d..311a07764239 100644 --- a/hw/char/esp32_uart.c +++ b/hw/char/esp32_uart.c @@ -349,18 +349,19 @@ static void esp32_uart_realize(DeviceState *dev, Error **errp) } -static const MemoryRegionOps uart_ops = { - .read = uart_read, - .write = uart_write, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - static void esp32_uart_init(Object *obj) { ESP32UARTState *s = ESP32_UART(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + ESP32UARTClass *class = ESP32_UART_GET_CLASS(obj); - memory_region_init_io(&s->iomem, obj, &uart_ops, s, + s->uart_ops = (MemoryRegionOps) { + .read = class->uart_read, + .write = class->uart_write, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + + memory_region_init_io(&s->iomem, obj, &s->uart_ops, s, TYPE_ESP32_UART, UART_REG_CNT * sizeof(uint32_t)); sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq); @@ -379,6 +380,11 @@ static Property esp32_uart_properties[] = { static void esp32_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ESP32UARTClass *class = ESP32_UART_CLASS(klass); + + /* Populate the virtual attributes and methods here (if any) */ + class->uart_write = uart_write; + class->uart_read = uart_read; dc->reset = esp32_uart_reset; dc->realize = esp32_uart_realize; @@ -390,7 +396,8 @@ static const TypeInfo esp32_uart_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ESP32UARTState), .instance_init = esp32_uart_init, - .class_init = esp32_uart_class_init + .class_init = esp32_uart_class_init, + .class_size = sizeof(ESP32UARTClass) }; static void esp32_uart_register_types(void) diff --git a/hw/char/esp32c3_uart.c b/hw/char/esp32c3_uart.c new file mode 100644 index 000000000000..ed503d94c387 --- /dev/null +++ b/hw/char/esp32c3_uart.c @@ -0,0 +1,99 @@ +/* + * ESP32C3 UART emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This implementation overrides the ESP32 UARt one, check it out first. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/module.h" +#include "qapi/error.h" +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/char/esp32c3_uart.h" +#include "hw/misc/esp32c3_rtc_cntl.h" + +static uint64_t esp32c3_uart_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3UARTClass *class = ESP32C3_UART_GET_CLASS(opaque); + /* Nothing special to do at the moment here, but it is possible to override the + * parent's read function behavior. */ + + return class->parent_uart_read(opaque, addr, size); +} + +static void esp32c3_uart_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3UARTClass *class = ESP32C3_UART_GET_CLASS(opaque); + + /* Same as above */ + class->parent_uart_write(opaque, addr, value, size); +} + +static void esp32c3_uart_init(Object *obj) +{ + /* No need to call parent's class function, this is done automatically by the QOM, even before + * calling the current function. */ +} + +static void esp32c3_uart_reset(DeviceState *dev) +{ + /* Nothing special to do at the moment here, call the parent reset */ + ESP32C3UARTClass* esp32c3_class = ESP32C3_UART_GET_CLASS(dev); + + esp32c3_class->parent_reset(dev); +} + +static void esp32c3_uart_realize(DeviceState *dev, Error **errp) +{ + // ESP32C3UARTState* esp32c3 = ESP32C3_UART(dev); + ESP32C3UARTClass* esp32c3_class = ESP32C3_UART_GET_CLASS(dev); + + /* Call the realize function of the parent class: ESP32UARTClass */ + esp32c3_class->parent_realize(dev, errp); +} + +static void esp32c3_uart_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + ESP32C3UARTClass* esp32c3 = ESP32C3_UART_CLASS(klass); + ESP32UARTClass* esp32 = ESP32_UART_CLASS(klass); + + /* Set our class' parent_realize field to the current realize function, set by the + * parent class initializer. + * After doing this, it will be necessary for our function, esp32c3_uart_realize, + * to manually call the parent's one. */ + device_class_set_parent_realize(dc, esp32c3_uart_realize, &esp32c3->parent_realize); + + /* Let's do the same thing for the reset function */ + device_class_set_parent_reset(dc, esp32c3_uart_reset, &esp32c3->parent_reset); + + /* Override the UART operations functions */ + esp32c3->parent_uart_write = esp32->uart_write; + esp32c3->parent_uart_read = esp32->uart_read; + esp32->uart_write = esp32c3_uart_write; + esp32->uart_read = esp32c3_uart_read; +} + +static const TypeInfo esp32c3_uart_info = { + .name = TYPE_ESP32C3_UART, + .parent = TYPE_ESP32_UART, + .instance_size = sizeof(ESP32C3UARTState), + .instance_init = esp32c3_uart_init, + .class_init = esp32c3_uart_class_init, + .class_size = sizeof(ESP32C3UARTClass) +}; + +static void esp32c3_uart_register_types(void) +{ + type_register_static(&esp32c3_uart_info); +} + +type_init(esp32c3_uart_register_types) diff --git a/hw/char/meson.build b/hw/char/meson.build index 17385b58036a..5123262053c2 100644 --- a/hw/char/meson.build +++ b/hw/char/meson.build @@ -33,6 +33,7 @@ softmmu_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c')) softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c')) softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c')) softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_uart.c')) +softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32_uart.c', 'esp32c3_uart.c')) specific_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c')) specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c')) diff --git a/include/hw/char/esp32_uart.h b/include/hw/char/esp32_uart.h index 1f0a7bb21b49..f46af5303bef 100644 --- a/include/hw/char/esp32_uart.h +++ b/include/hw/char/esp32_uart.h @@ -9,6 +9,8 @@ #define UART_FIFO_LENGTH 128 #define TYPE_ESP32_UART "esp_soc.uart" +#define ESP32_UART_GET_CLASS(obj) OBJECT_GET_CLASS(ESP32UARTClass, obj, TYPE_ESP32_UART) +#define ESP32_UART_CLASS(klass) OBJECT_CLASS_CHECK(ESP32UARTClass, klass, TYPE_ESP32_UART) #define ESP32_UART(obj) OBJECT_CHECK(ESP32UARTState, (obj), TYPE_ESP32_UART) REG32(UART_FIFO, 0x0) @@ -92,5 +94,13 @@ typedef struct ESPUARTState { guint tx_watch_handle; uint32_t reg[UART_REG_CNT]; + MemoryRegionOps uart_ops; } ESP32UARTState; +typedef struct ESPUARTClass { + SysBusDeviceClass parent_class; + + /* Virtual attributes/methods */ + void (*uart_write)(void *opaque, hwaddr addr, uint64_t value, unsigned int size); + uint64_t (*uart_read)(void *opaque, hwaddr addr, unsigned int size); +} ESP32UARTClass; diff --git a/include/hw/char/esp32c3_uart.h b/include/hw/char/esp32c3_uart.h new file mode 100644 index 000000000000..6c98662f5c9d --- /dev/null +++ b/include/hw/char/esp32c3_uart.h @@ -0,0 +1,36 @@ +#pragma once + +#include "esp32_uart.h" + + +#define TYPE_ESP32C3_UART "esp32c3_soc.uart" +/* This macro can be used to "convert" a generic object into a more specific object, here ESP32C3UARTState. + * For example, it can convert a DeviceState to a ESP32C3UARTState */ +#define ESP32C3_UART(obj) OBJECT_CHECK(ESP32C3UARTState, (obj), TYPE_ESP32C3_UART) +/* This one can be used to get the class of a given object. + * For example, it can give the ESP32UARTClass type structure out of a DeviceState or a + * ESP32C3UARTState structure. */ +#define ESP32C3_UART_GET_CLASS(obj) OBJECT_GET_CLASS(ESP32C3UARTClass, obj, TYPE_ESP32C3_UART) +/* Finally, this macro is used to convert a generic class to ESP32C3UARTClass. + * For example, it can be used to convert an ObjectClass to a ESP32C3UARTClass*/ +#define ESP32C3_UART_CLASS(klass) OBJECT_CLASS_CHECK(ESP32C3UARTClass, klass, TYPE_ESP32C3_UART) + +typedef struct ESP32C3UARTState { + ESP32UARTState parent; + +} ESP32C3UARTState; + +typedef struct ESP32C3UARTClass { + ESP32UARTClass parent_class; + + /* These function pointers will be during class init, they will be populated + * by device_class_set_parent_* functions. They can then be called in the + * respective class methods: realize and reset. */ + DeviceRealize parent_realize; + DeviceReset parent_reset; + + /* Virtual attributes/methods overriden */ + void (*parent_uart_write)(void *opaque, hwaddr addr, uint64_t value, unsigned int size); + uint64_t (*parent_uart_read)(void *opaque, hwaddr addr, unsigned int size); +} ESP32C3UARTClass; + From 3324f82e2b9798191666e4f37faf286b28e9a885 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:33:29 +0800 Subject: [PATCH 31/56] hw/gpio: implement ESP32-C3 GPIO C3 GPIO overrides ESP32 GPIO driver and modifies the boot strap pin --- hw/gpio/esp32_gpio.c | 10 +++++-- hw/gpio/esp32c3_gpio.c | 49 ++++++++++++++++++++++++++++++++++ hw/gpio/meson.build | 1 + include/hw/gpio/esp32_gpio.h | 7 ++++- include/hw/gpio/esp32c3_gpio.h | 24 +++++++++++++++++ 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 hw/gpio/esp32c3_gpio.c create mode 100644 include/hw/gpio/esp32c3_gpio.h diff --git a/hw/gpio/esp32_gpio.c b/hw/gpio/esp32_gpio.c index 190576499837..84aefd4ce06a 100644 --- a/hw/gpio/esp32_gpio.c +++ b/hw/gpio/esp32_gpio.c @@ -60,6 +60,9 @@ static void esp32_gpio_init(Object *obj) Esp32GpioState *s = ESP32_GPIO(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + /* Set the default value for the strap_mode property */ + object_property_set_int(obj, "strap_mode", ESP32_STRAP_MODE_FLASH_BOOT, &error_fatal); + memory_region_init_io(&s->iomem, obj, &uart_ops, s, TYPE_ESP32_GPIO, 0x1000); sysbus_init_mmio(sbd, &s->iomem); @@ -67,7 +70,9 @@ static void esp32_gpio_init(Object *obj) } static Property esp32_gpio_properties[] = { - DEFINE_PROP_UINT32("strap_mode", Esp32GpioState, strap_mode, ESP32_STRAP_MODE_FLASH_BOOT), + /* The strap_mode needs to be explicitly set in the instance init, thus, set + * the default value to 0. */ + DEFINE_PROP_UINT32("strap_mode", Esp32GpioState, strap_mode, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -85,7 +90,8 @@ static const TypeInfo esp32_gpio_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Esp32GpioState), .instance_init = esp32_gpio_init, - .class_init = esp32_gpio_class_init + .class_init = esp32_gpio_class_init, + .class_size = sizeof(Esp32GpioClass), }; static void esp32_gpio_register_types(void) diff --git a/hw/gpio/esp32c3_gpio.c b/hw/gpio/esp32c3_gpio.c new file mode 100644 index 000000000000..1e842381f212 --- /dev/null +++ b/hw/gpio/esp32c3_gpio.c @@ -0,0 +1,49 @@ +/* + * ESP32-C3 GPIO emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/gpio/esp32c3_gpio.h" + + +static void esp32c3_gpio_init(Object *obj) +{ + /* Set the default value for the property */ + object_property_set_int(obj, "strap_mode", ESP32C3_STRAP_MODE_FLASH_BOOT, &error_fatal); +} + +/* If we need to override any function from the parent (reset, realize, ...), it shall be done + * in this class_init function */ +static void esp32c3_gpio_class_init(ObjectClass *klass, void *data) +{ +} + +static const TypeInfo esp32c3_gpio_info = { + .name = TYPE_ESP32C3_GPIO, + .parent = TYPE_ESP32_GPIO, + .instance_size = sizeof(ESP32C3GPIOState), + .instance_init = esp32c3_gpio_init, + .class_init = esp32c3_gpio_class_init, + .class_size = sizeof(ESP32C3GPIOClass), +}; + +static void esp32c3_gpio_register_types(void) +{ + type_register_static(&esp32c3_gpio_info); +} + +type_init(esp32c3_gpio_register_types) diff --git a/hw/gpio/meson.build b/hw/gpio/meson.build index ed4a9c99be1d..25aef3f82f2f 100644 --- a/hw/gpio/meson.build +++ b/hw/gpio/meson.build @@ -13,3 +13,4 @@ softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_gpio.c')) softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_gpio.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_GPIO', if_true: files('sifive_gpio.c')) softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_gpio.c')) +softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32_gpio.c', 'esp32c3_gpio.c')) diff --git a/include/hw/gpio/esp32_gpio.h b/include/hw/gpio/esp32_gpio.h index 38632c3c08f1..163b41aa6b5a 100644 --- a/include/hw/gpio/esp32_gpio.h +++ b/include/hw/gpio/esp32_gpio.h @@ -5,7 +5,9 @@ #include "hw/registerfields.h" #define TYPE_ESP32_GPIO "esp32.gpio" -#define ESP32_GPIO(obj) OBJECT_CHECK(Esp32GpioState, (obj), TYPE_ESP32_GPIO) +#define ESP32_GPIO(obj) OBJECT_CHECK(Esp32GpioState, (obj), TYPE_ESP32_GPIO) +#define ESP32_GPIO_GET_CLASS(obj) OBJECT_GET_CLASS(Esp32GpioClass, obj, TYPE_ESP32_GPIO) +#define ESP32_GPIO_CLASS(klass) OBJECT_CLASS_CHECK(Esp32GpioClass, klass, TYPE_ESP32_GPIO) REG32(GPIO_STRAP, 0x0038) @@ -20,3 +22,6 @@ typedef struct Esp32GpioState { uint32_t strap_mode; } Esp32GpioState; +typedef struct Esp32GpioClass { + SysBusDeviceClass parent_class; +} Esp32GpioClass; diff --git a/include/hw/gpio/esp32c3_gpio.h b/include/hw/gpio/esp32c3_gpio.h new file mode 100644 index 000000000000..6fe8b72bd764 --- /dev/null +++ b/include/hw/gpio/esp32c3_gpio.h @@ -0,0 +1,24 @@ +#pragma once + +#include "hw/sysbus.h" +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "esp32_gpio.h" + +#define TYPE_ESP32C3_GPIO "esp32c3.gpio" +#define ESP32C3_GPIO(obj) OBJECT_CHECK(ESP32C3GPIOState, (obj), TYPE_ESP32C3_GPIO) +#define ESP32C3_GPIO_GET_CLASS(obj) OBJECT_GET_CLASS(ESP32C3GPIOClass, obj, TYPE_ESP32C3_GPIO) +#define ESP32C3_GPIO_CLASS(klass) OBJECT_CLASS_CHECK(ESP32C3GPIOClass, klass, TYPE_ESP32C3_GPIO) + +/* Bootstrap options for ESP32-C3 (4-bit) */ +#define ESP32C3_STRAP_MODE_FLASH_BOOT 0x8 /* SPI Boot */ +#define ESP32C3_STRAP_MODE_UART_BOOT 0x2 /* Diagnostic Mode0+UART0 download Mode */ +#define ESP32C3_STRAP_MODE_USB_BOOT 0x0 /* Diagnostic Mode1+USB download Mode */ + +typedef struct ESP32C3State { + Esp32GpioState parent; +} ESP32C3GPIOState; + +typedef struct ESP32C3GPIOClass { + Esp32GpioClass parent; +} ESP32C3GPIOClass; From 036ba9bc4e10147fa64d8e72d2d3a5bcaa0145f9 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:37:04 +0800 Subject: [PATCH 32/56] hw/timer: implement ESP32-C3 Timer Groups All the features are supported --- hw/timer/esp32c3_timg.c | 740 ++++++++++++++++++++++++++++++++ hw/timer/meson.build | 1 + include/hw/timer/esp32c3_timg.h | 255 +++++++++++ 3 files changed, 996 insertions(+) create mode 100644 hw/timer/esp32c3_timg.c create mode 100644 include/hw/timer/esp32c3_timg.h diff --git a/hw/timer/esp32c3_timg.c b/hw/timer/esp32c3_timg.c new file mode 100644 index 000000000000..a7f684a5f5c3 --- /dev/null +++ b/hw/timer/esp32c3_timg.c @@ -0,0 +1,740 @@ +/* + * ESP32-C3 "Timer Group" peripheral + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/registerfields.h" +#include "hw/boards.h" +#include "hw/timer/esp32c3_timg.h" + +#define TIMG_DEBUG 0 +#define TIMG_WARNING 0 + +#define FIELD_CHANGED(value1, value2, reg, field) \ + ((value1) & R_ ## reg ## _ ## field ## _MASK) != ((value2) & R_ ## reg ## _ ## field ## _MASK) + +/** + * Helper to load a 32-bit low value and a 22-bit high value into a 64-bit value + */ +static inline uint64_t load_low(uint64_t reg, uint32_t low) +{ + return (reg & (0xffffffff00000000)) | (low & UINT32_MAX); +} + +static inline uint64_t load_high(uint64_t reg, uint32_t high) +{ + return (reg & UINT32_MAX) | ((uint64_t) (high & 0x3fffff) << 32); +} + + +/** + * @brief Update the value of a counter according the QEMU virtual timer. + */ +static int64_t esp32c3_virtual_counter_update(ESP32C3VirtualCounter *counter) +{ + const int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + const int64_t elapsed_ns = now - counter->base; + const int64_t ticks = (elapsed_ns * (counter->frequency / 1000)) / 1000000; + counter->value += ticks; + counter->base = now; + return counter->value; +} + +static inline QEMUTimer* esp32c3_virtual_counter_get_timer(ESP32C3VirtualCounter *counter) +{ + return &counter->timer; +} + +static void esp32c3_virtual_counter_alarm_in_ticks(ESP32C3VirtualCounter *counter, int64_t ticks) +{ + int64_t delay_ns = (ticks * (1000000000UL / counter->frequency)); + const int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + /* This function will reschedule the clock if it was already scheduled */ + counter->base = now; + counter->value = 0; + timer_mod_ns(&counter->timer, now + delay_ns); +} + +/** + * Update the time base of the timer without updating the counter value. + * This shall be used when the counter has just been re-enabled, and the elapsed time since it was disabled + * must not be taken into account. + */ +static void esp32c3_virtual_counter_reenabled(ESP32C3VirtualCounter *counter) +{ + counter->base = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +static void esp32c3_virtual_counter_reset(ESP32C3VirtualCounter* counter) +{ + timer_del(&counter->timer); + counter->base = 0; + counter->value = 0; +} + + +/** + * @brief Function called when an update of the RTC Calibration register is requested + * Perform the required calibration simulation here and update the register. + */ +static void esp32c3_timg_rtc_cali_update(ESP32C3TimgState *s, uint32_t value) +{ + const uint32_t osc_freq_arr[] = { + [ESP32C3_TIMG_CALI_RC_SLOW_CLK] = ESP32C3_RC_SLOW_FREQ, + [ESP32C3_TIMG_CALI_RC_FAST_DIV_CLK] = ESP32C3_RC_FAST_DIV_FREQ, + [ESP32C3_TIMG_CALI_XTAL32K_CLK] = ESP32C3_XTAL32K_FREQ + }; + /* Copy the new value to the register but keep RDY bit to 0 (read-only) */ + value &= ~(R_TIMG_RTCCALICFG_RDY_MASK); + + /* Check if a start (one-time or periodic) was triggered */ + if (value & (R_TIMG_RTCCALICFG_START_MASK | R_TIMG_RTCCALICFG_START_CYCLING_MASK)) { + + /* Get the clock that is being calibrated */ + const uint32_t clk = FIELD_EX32(value, TIMG_RTCCALICFG, CLK_SEL); + const uint32_t freq = osc_freq_arr[clk]; + + /* And the counter that should be reached by this clock */ + const uint32_t max_count = FIELD_EX32(value, TIMG_RTCCALICFG, MAX); + + /* Calculate how many clock cycle it would require to the XTAL_CLK to reach this count */ + const uint32_t xtal_count = (ESP32C3_XTAL_CLK * max_count) / freq; + + /* Save this count in the RTC Calibration register 1 */ + s->rtc.rtc_cali_cfg_result = xtal_count << R_TIMG_RTCCALICFG1_VALUE_SHIFT; + + value |= R_TIMG_RTCCALICFG_RDY_MASK; + + /* Clear the timeout register */ + s->rtc.rtc_cali_cfg_timeout &= ~(R_TIMG_RTCCALICFG2_TIMEOUT_MASK); + } + + s->rtc.rtc_cali_cfg = value; +} + +/** + * @brief Function called when an update on the timeout register occur. + */ +static void esp32c3_timg_rtc_cali_check_timeout(ESP32C3TimgState *s, uint32_t value) +{ + /* Let's simplify the process of timeout generation, if the timeout reset count is smaller + * than the max cali count divided by a constant, generate a timeout */ + const uint32_t count = FIELD_EX32(s->rtc.rtc_cali_cfg, TIMG_RTCCALICFG, MAX); + const uint32_t rst_cnt = FIELD_EX32(value, TIMG_RTCCALICFG2, TIMEOUT_RST_CNT); + + s->rtc.rtc_cali_cfg_timeout = value & ~(R_TIMG_RTCCALICFG2_TIMEOUT_MASK); + + if (rst_cnt == 0 || (rst_cnt < count / 10)) + { + s->rtc.rtc_cali_cfg_timeout |= R_TIMG_RTCCALICFG2_TIMEOUT_MASK; + } +} + +/** + * Functions related to Watchdog + */ + +static inline uint64_t esp32c3_wdt_ext_clk_frequency(ESP32C3WdtState* wdt) +{ + return FIELD_EX32(wdt->config0, TIMG_WDTCONFIG0, USE_XTAL) ? ESP32C3_XTAL_CLK : ESP32C3_APB_CLK; +} + +static inline bool esp32c3_wdt_is_writable(ESP32C3WdtState* wdt) +{ + return wdt->wkey == ESP32C3_WDT_DEFAULT_WKEY; +} + +static inline bool esp32c3_wdt_enabled(ESP32C3WdtState* wdt) +{ + return FIELD_EX32(wdt->config0, TIMG_T0CONFIG, EN) ? 1 : 0; +} + + +static void esp32c3_wdt_cb(void* opaque) +{ + ESP32C3WdtState* wdt = (ESP32C3WdtState*) opaque; + ESP32C3WdtStageConf conf = wdt->stage_conf[wdt->current_stage]; + + /* Check which action must be taken for the current stage */ + if (conf == ESP32C3_WDT_INTERRUPT) { + wdt->raw_st = 1; + if (wdt->int_enabled) { + qemu_irq_raise(wdt->interrupt_irq); + } + } else if (conf == ESP32C3_WDT_RESET_CPU || conf == ESP32C3_WDT_RESET_SYS) { + qemu_irq_raise(wdt->reset_irq); + /* Do not schedule anything if we have to reset the machine */ + return; + } + + const int new_stage = (wdt->current_stage + 1) % ESP32C3_WDT_STAGE_COUNT; + wdt->current_stage = new_stage; + esp32c3_virtual_counter_alarm_in_ticks(&wdt->counter, wdt->stage[new_stage]); +} + +static void esp32c3_wdt_update_prescaler(ESP32C3WdtState* wdt, uint32_t value) +{ + if (FIELD_EX32(value, TIMG_WDTCONFIG1, DIVCNT_RST) || value == 0) { + /* Avoid any divide-by-0 error in the code below */ + wdt->prescaler = 1; + } else { + wdt->prescaler = FIELD_EX32(value, TIMG_WDTCONFIG1, CLK_PRESCALE); + } + + /* Recalculate the frequency out of the new prescaler and current clock */ + wdt->counter.frequency = esp32c3_wdt_ext_clk_frequency(wdt) / wdt->prescaler; + + /* In theory we should reschedule the timer if it is currently running. + * In practice, let's say that this behavior is invalid and do not reschedule it. */ +} + +static void esp32c3_wdt_update_stage(ESP32C3WdtState* wdt, int index, uint32_t value, bool verify) +{ + wdt->stage[index] = value; + + /* If the updated stage is the current one and the watchdog is enabled, reprogram the timer */ + if (esp32c3_wdt_enabled(wdt) && wdt->current_stage == index && verify) { + /* Update the counter of the running timer, so that we can adjust the alarm */ + int64_t counter_value = esp32c3_virtual_counter_update(&wdt->counter); + int64_t diff = (int64_t) value - counter_value; + if (diff <= 0) { + /* If the difference is negative, the new limit is smaller than the current value, + * manually trigger the alarm. */ + esp32c3_wdt_cb(wdt); + } else { + /* The new alarm is set to happen in `diff` ticks, reschedule the alarm */ + esp32c3_virtual_counter_alarm_in_ticks(&wdt->counter, diff); + } + } +} + +static void esp32c3_wdt_feed(ESP32C3WdtState* wdt) +{ + if (esp32c3_wdt_enabled(wdt)) { + wdt->current_stage = 0; + esp32c3_virtual_counter_alarm_in_ticks(&wdt->counter, wdt->stage[0]); + } +} + +static void esp32c3_wdt_update_config(ESP32C3WdtState* wdt, uint32_t value) +{ + /* If the WDT is protected return */ + if (!esp32c3_wdt_is_writable(wdt)) { + return; + } + + const uint32_t former_conf = wdt->config0; + /* Clean the reserved bits */ + wdt->config0 = value & ~(R_TIMG_WDTCONFIG0_CONF_UPDATE_EN_MASK | 0x7ff); + + const bool enabled = FIELD_EX32(value, TIMG_WDTCONFIG0, EN) ? true : false; + const bool enabled_changed = FIELD_EX32(former_conf, TIMG_WDTCONFIG0, EN) != enabled; + + if (FIELD_EX32(value, TIMG_WDTCONFIG0, CONF_UPDATE_EN)) { + /* If the prescaler value or the source clock changed update the timer */ + if ((FIELD_EX32(wdt->prescaler_mirror, TIMG_WDTCONFIG1, CLK_PRESCALE) != wdt->prescaler) || + (FIELD_EX32(former_conf, TIMG_WDTCONFIG0, USE_XTAL) != FIELD_EX32(value, TIMG_WDTCONFIG0, USE_XTAL))) + { + esp32c3_wdt_update_prescaler(wdt, wdt->prescaler_mirror); + } + + /* Update the stage configuration mirror */ + wdt->stage_conf[0] = FIELD_EX32(value, TIMG_WDTCONFIG0, STG0); + wdt->stage_conf[1] = FIELD_EX32(value, TIMG_WDTCONFIG0, STG1); + wdt->stage_conf[2] = FIELD_EX32(value, TIMG_WDTCONFIG0, STG2); + wdt->stage_conf[3] = FIELD_EX32(value, TIMG_WDTCONFIG0, STG3); + + /* Update the stage values */ + for (int i = 0; i < ESP32C3_WDT_STAGE_COUNT; i++) { + /* Only reprogram the timer if the enable flag didn't change */ + esp32c3_wdt_update_stage(wdt, i, wdt->stage_mirror[i], enabled && !enabled_changed); + } + } + + /* Check if the enabled bit changed */ + if (enabled_changed) { + if (enabled) { + wdt->config0 |= R_TIMG_WDTCONFIG0_EN_MASK; + /* Timer has just been (re-)enabled, schedule the timer */ + esp32c3_virtual_counter_alarm_in_ticks(&wdt->counter, wdt->stage[0]); + } else { + wdt->config0 &= ~R_TIMG_WDTCONFIG0_EN_MASK; + /* Disable the timer! */ + timer_del(&wdt->counter.timer); + } + } +} + +/** + * Functions related to T0 timer registers + */ +static void esp32c3_t0_update_counter(ESP32C3T0State* t) +{ + int64_t previous = t->counter.value; + int64_t current = esp32c3_virtual_counter_update(&t->counter); + int64_t delta = current - previous; + const bool increase = FIELD_EX32(t->config, TIMG_T0CONFIG, INCREASE) ? true : false; + if (increase) { + t->value_rel = (t->value_rel + delta) & ESP32C3_TIMG_T0_MAX_VALUE; + } else { + t->value_rel = (t->value_rel - delta) & ESP32C3_TIMG_T0_MAX_VALUE; + } +} + + +static void esp32c3_t0_cb(void* opaque) +{ + ESP32C3T0State* t = (ESP32C3T0State*) opaque; + + /* Update the value of the counter and disable the alarm timer */ + esp32c3_virtual_counter_reset(&t->counter); + esp32c3_virtual_counter_reenabled(&t->counter); + + /* In practice, the counter is bigger than the requested value, this is due to the fact + * that there is a cost of emulation and the (Linux) kernel timer may also be busy + * doing something else before scheduling the VM. Adjust the counter to the alarm value. */ + t->value_rel = t->alarm; + + /* If the counter is set to auto-reload, set its new value */ + if (FIELD_EX32(t->config, TIMG_T0CONFIG, AUTORELOAD)) { + t->value_rel = t->value_toload; + } + + /* Alarm was triggered, clear alarm bit, set the IRQ if interrupts enabled */ + t->config &= ~R_TIMG_T0CONFIG_ALARM_EN_MASK; + t->raw_st = true; + if (t->int_enabled) { + qemu_irq_raise(t->interrupt_irq); + } +} + + +static void esp32c3_t0_counter_flush(ESP32C3T0State* t) +{ + if (FIELD_EX32(t->config, TIMG_T0CONFIG, EN)) { + esp32c3_t0_update_counter(t); + } + + t->value_flushed = t->value_rel; +} + + +static void esp32c3_t0_alarm_update(ESP32C3T0State* t) +{ + + if (FIELD_EX32(t->config, TIMG_T0CONFIG, EN) && + FIELD_EX32(t->config, TIMG_T0CONFIG, ALARM_EN)) { + + const bool increase = FIELD_EX32(t->config, TIMG_T0CONFIG, INCREASE) ? true : false; + const bool decrease = !increase; + const uint64_t alarm = t->alarm; + + /* Update the current value of the relative counter */ + esp32c3_t0_update_counter(t); + + /* No matter if we increase or decrease the counter the time difference is the same */ + const uint64_t value = t->value_rel; + uint64_t diff = llabs(alarm - value); + const uint64_t limit = ESP32C3_TIMG_T0_LIMIT; + + /* Declare all the possible scenarios as explained in the TRM */ + const bool scenario1 = alarm > value && diff > limit; + const bool scenario2 = alarm > value && diff <= limit; + const bool scenario3 = value >= alarm && diff < limit; + const bool scenario4 = value >= alarm && diff >= limit; + const bool scenario5 = alarm < value && diff > limit; + const bool scenario6 = alarm < value && diff <= limit; + const bool scenario7 = value <= alarm && diff < limit; + const bool scenario8 = value <= alarm && diff >= limit; + + if ((increase && (scenario1 || scenario3)) || (decrease && (scenario5 || scenario7))) { + /* The alarm was programmed too late, trigger an interrupt manually */ + esp32c3_t0_cb(t); + } else if ((increase && scenario2) || (decrease && scenario6)) { + /* The alarm is in range and in the future, program its trigger */ + esp32c3_virtual_counter_alarm_in_ticks(&t->counter, diff); + } else { + assert(scenario4 || scenario8); + /* The alarm is in range, in the future, but requires the timer to overflow/underflow */ + const uint64_t high = MAX(alarm, value); + const uint64_t low = MIN(alarm, value); + /* Calculate the new (tick) difference between them */ + diff = (ESP32C3_TIMG_T0_MAX_VALUE + 1 - high) + low; + esp32c3_virtual_counter_alarm_in_ticks(&t->counter, diff); + } + + } +} + + +static void esp32c3_t0_counter_load(ESP32C3T0State* t) +{ + /* Update the counter so that the (time) base is up to date */ + esp32c3_t0_update_counter(t); + + /* Set the new counter */ + t->value_rel = t->value_toload; + + /* Reprogram the alarm if necessary */ + esp32c3_t0_alarm_update(t); +} + +static void esp32c3_t0_config_update(ESP32C3T0State* t0, uint32_t value) +{ + const uint32_t former_conf = t0->config; + /* Assign the new configuration while removing the write-only bits */ + t0->config = value & ~(R_TIMG_T0CONFIG_DIVCNT_RST_MASK); + + /* If the counter was enabled until now, update its value */ + if (former_conf & R_TIMG_T0CONFIG_EN_MASK) { + esp32c3_t0_update_counter(t0); + } + + /* Calculate the new frequency */ + const uint32_t new_divider = FIELD_EX32(value, TIMG_T0CONFIG, DIVIDER); + const uint64_t new_clk = FIELD_EX32(value, TIMG_T0CONFIG, USE_XTAL) ? ESP32C3_XTAL_CLK : ESP32C3_APB_CLK; + const uint64_t new_freq = new_clk / new_divider; + if (new_freq != t0->counter.frequency) { + t0->counter.frequency = new_freq; + } + + if (value & R_TIMG_T0CONFIG_DIVCNT_RST_MASK) { + esp32c3_virtual_counter_reset(&t0->counter); + esp32c3_t0_alarm_update(t0); + } + + /* If the alarm state just changed, we have to load it or disable it */ + if (FIELD_CHANGED(former_conf, value, TIMG_T0CONFIG, ALARM_EN)) { + if (value & R_TIMG_T0CONFIG_ALARM_EN_MASK) { + esp32c3_t0_alarm_update(t0); + } else { + timer_del(&t0->counter.timer); + } + } + + /* If the direction of the counter changed, reprogram the alarm. The function esp32c3_t0_alarm_update + * will check if the counter and alarm are enabled first, no need to do it here. */ + if (FIELD_CHANGED(former_conf, value, TIMG_T0CONFIG, INCREASE)) { + esp32c3_t0_alarm_update(t0); + } + + /* Finally, check if the counter state changed */ + if (FIELD_CHANGED(former_conf, value, TIMG_T0CONFIG, EN)) { + if (value & R_TIMG_T0CONFIG_EN_MASK) { + /* the counter was disabled, it has just been re-enabled, its value should not be updated, + * but the base time should be updated to now. */ + esp32c3_virtual_counter_reenabled(&t0->counter); + esp32c3_t0_alarm_update(t0); + } else { + /* In theory, we should update the counter before disabling its timer, but in practice, we + * already did that at the beginning of this function. Thus, the base time is correct. */ + timer_del(&t0->counter.timer); + } + } +} + + +/** + * Functions related to the hardware registers + */ +static uint64_t esp32c3_timg_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3TimgState *s = ESP32C3_TIMG(opaque); + + uint64_t r = 0; + switch (addr) { + case A_TIMG_RTCCALICFG: + r = s->rtc.rtc_cali_cfg; + break; + case A_TIMG_RTCCALICFG1: + r = s->rtc.rtc_cali_cfg_result; + break; + case A_TIMG_RTCCALICFG2: + r = s->rtc.rtc_cali_cfg_timeout; + break; + + + /* Timer (T0) related registers */ + case A_TIMG_T0CONFIG: + r = s->t0.config; + break; + case A_TIMG_T0LO: + r = s->t0.value_flushed & UINT32_MAX; + break; + case A_TIMG_T0HI: + r = s->t0.value_flushed >> 32; + break; + case A_TIMG_T0UPDATE: + /* Write-only register */ + break; + case A_TIMG_T0ALARMLO: + r = s->t0.alarm & UINT32_MAX; + break; + case A_TIMG_T0ALARMHI: + r = s->t0.alarm >> 32; + break; + case A_TIMG_T0LOADLO: + r = s->t0.value_toload & UINT32_MAX; + break; + case A_TIMG_T0LOADHI: + r = s->t0.value_toload >> 32; + break; + case A_TIMG_T0LOAD: + /* Write-only register */ + break; + + + /* Watchdog related registers */ + case A_TIMG_WDTCONFIG0: + r = s->wdt.config0; + break; + case A_TIMG_WDTCONFIG1: + r = s->wdt.prescaler_mirror & ~R_TIMG_WDTCONFIG1_DIVCNT_RST_MASK; + break; + case A_TIMG_WDTCONFIG2: + case A_TIMG_WDTCONFIG3: + case A_TIMG_WDTCONFIG4: + case A_TIMG_WDTCONFIG5: + r = s->wdt.stage_mirror[(addr - A_TIMG_WDTCONFIG2) / sizeof(uint32_t)]; + break; + case A_TIMG_WDTFEED: + /* This register is read-only, but avoid a warning */ + break; + case A_TIMG_WDTWPROTECT: + r = s->wdt.wkey; + break; + + case A_TIMG_INT_ENA_TIMG: + r |= s->wdt.int_enabled << R_TIMG_INT_ENA_TIMG_WDT_ENA_SHIFT; + r |= s->t0.int_enabled << R_TIMG_INT_ENA_TIMG_T0_ENA_SHIFT; + break; + case A_TIMG_INT_RAW_TIMG: + r |= s->wdt.raw_st << R_TIMG_INT_RAW_TIMG_WDT_RAW_SHIFT; + r |= s->t0.raw_st << R_TIMG_INT_RAW_TIMG_T0_RAW_SHIFT; + break; + case A_TIMG_INT_ST_TIMG: + r |= (s->wdt.int_enabled && s->wdt.raw_st) << R_TIMG_INT_ST_TIMG_WDT_ST_SHIFT; + r |= (s->t0.int_enabled && s->t0.raw_st) << R_TIMG_INT_ST_TIMG_T0_ST_SHIFT; + break; + + default: +#if TIMG_WARNING + warn_report("[TIMG] Unsupported read from %08lx\n", addr); +#endif + break; + } + +#if TIMG_DEBUG + info_report("[TIMG] Reading from %08lx (%08lx)\n", addr, r); +#endif + return r; +} + +static void esp32c3_timg_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3TimgState *s = ESP32C3_TIMG(opaque); + + switch(addr) { + case A_TIMG_RTCCALICFG: + esp32c3_timg_rtc_cali_update(s, value); + break; + case A_TIMG_RTCCALICFG2: + esp32c3_timg_rtc_cali_check_timeout(s, value); + break; + + /* Timer (T0) related registers */ + case A_TIMG_T0CONFIG: + esp32c3_t0_config_update(&s->t0, value); + break; + case A_TIMG_T0LO: + case A_TIMG_T0HI: + /* These registers are read-only but implement them to avoid getting a warning */ + break; + case A_TIMG_T0UPDATE: + esp32c3_t0_counter_flush(&s->t0); + break; + case A_TIMG_T0ALARMLO: + s->t0.alarm = load_low(s->t0.alarm, value); + esp32c3_t0_alarm_update(&s->t0); + break; + case A_TIMG_T0ALARMHI: + s->t0.alarm = load_high(s->t0.alarm, value); + esp32c3_t0_alarm_update(&s->t0); + break; + case A_TIMG_T0LOADLO: + s->t0.value_toload = load_low(s->t0.value_toload, value); + break; + case A_TIMG_T0LOADHI: + s->t0.value_toload = load_high(s->t0.value_toload, value); + break; + case A_TIMG_T0LOAD: + esp32c3_t0_counter_load(&s->t0); + break; + + + /* Watchdog related registers */ + case A_TIMG_WDTCONFIG0: + esp32c3_wdt_update_config(&s->wdt, value); + break; + case A_TIMG_WDTCONFIG1: + s->wdt.prescaler_mirror = value; + break; + case A_TIMG_WDTCONFIG2: + case A_TIMG_WDTCONFIG3: + case A_TIMG_WDTCONFIG4: + case A_TIMG_WDTCONFIG5: + s->wdt.stage_mirror[(addr - A_TIMG_WDTCONFIG2) / sizeof(uint32_t)] = value; + break; + case A_TIMG_WDTFEED: + esp32c3_wdt_feed(&s->wdt); + break; + case A_TIMG_WDTWPROTECT: + s->wdt.wkey = value; + break; + + /* Interrupt related registers */ + case A_TIMG_INT_ENA_TIMG: + s->wdt.int_enabled = FIELD_EX32(value, TIMG_INT_ENA_TIMG, WDT_ENA) ? true : false; + s->t0.int_enabled = FIELD_EX32(value, TIMG_INT_ENA_TIMG, T0_ENA) ? true : false; + break; + case A_TIMG_INT_CLR_TIMG: + if (FIELD_EX32(value, TIMG_INT_CLR_TIMG, WDT_CLR)) { + s->wdt.raw_st = 0; + qemu_irq_lower(s->wdt.interrupt_irq); + } + if (FIELD_EX32(value, TIMG_INT_CLR_TIMG, T0_CLR)) { + s->t0.raw_st = 0; + qemu_irq_lower(s->t0.interrupt_irq); + } + break; + case A_TIMG_INT_RAW_TIMG: + case A_TIMG_INT_ST_TIMG: + break; + + default: +#if TIMG_WARNING + warn_report("[TIMG] Unsupported write to %08lx (%08lx)\n", addr, value); +#endif + break; + } + +#if TIMG_DEBUG + info_report("[TIMG] Writing to %08lx = %08lx\n", addr, value); +#endif +} + + +static const MemoryRegionOps esp32c3_timg_ops = { + .read = esp32c3_timg_read, + .write = esp32c3_timg_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + + +static void esp32c3_timg_reset(DeviceState* ts) +{ + ESP32C3TimgState *s = ESP32C3_TIMG(ts); + + /* Reset watchdog */ + esp32c3_virtual_counter_reset(&s->wdt.counter); + s->wdt.config0 = 0; + s->wdt.wkey = ESP32C3_WDT_DEFAULT_WKEY; + s->wdt.current_stage = 0; + memset(&s->wdt.stage_conf, 0, sizeof(s->wdt.stage_conf)); + s->wdt.stage[0] = 0x26000000; + s->wdt.stage[1] = 0x7FFFFFFF; + s->wdt.stage[2] = 0x0FFFFFFF; + s->wdt.stage[3] = 0x0FFFFFFF; + s->wdt.prescaler = 0x100; + s->wdt.raw_st = 0; + s->wdt.int_enabled = 0; + + /* Reset Timer0 */ + esp32c3_virtual_counter_reset(&s->t0.counter); + s->t0.raw_st = 0; + s->t0.int_enabled = 0; + s->t0.value_rel = 0; + /* Set teh divider to 1 */ + s->t0.config = 1 << R_TIMG_T0CONFIG_DIVIDER_SHIFT; +} + + +static void esp32c3_timg_realize(DeviceState *dev, Error **errp) +{ +} + + +static void esp32c3_timg_init(Object *obj) +{ + ESP32C3TimgState *s = ESP32C3_TIMG(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_timg_ops, s, + TYPE_ESP32C3_TIMG, ESP32C3_TIMG_IO_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + + /* Set default value to calibration register */ + s->rtc.rtc_cali_cfg = 1 << R_TIMG_RTCCALICFG_MAX_SHIFT | + 1 << R_TIMG_RTCCALICFG_CLK_SEL_SHIFT | + 1 << R_TIMG_RTCCALICFG_START_CYCLING_SHIFT; + + /* Watchdog initialization */ + s->wdt.wkey = ESP32C3_WDT_DEFAULT_WKEY; + qdev_init_gpio_out_named(DEVICE(sbd), &s->wdt.reset_irq, ESP32C3_WDT_IRQ_RESET, 1); + qdev_init_gpio_out_named(DEVICE(sbd), &s->wdt.interrupt_irq, ESP32C3_WDT_IRQ_INTERRUPT, 1); + timer_init_ns(esp32c3_virtual_counter_get_timer(&s->wdt.counter), QEMU_CLOCK_VIRTUAL, esp32c3_wdt_cb, &s->wdt); + s->wdt.stage[0] = 0x26000000; + s->wdt.stage[1] = 0x7FFFFFFF; + s->wdt.stage[2] = 0x0FFFFFFF; + s->wdt.stage[3] = 0x0FFFFFFF; + s->wdt.prescaler = 0x100; + + + /* Timer T0 initialization */ + s->t0.config = 1 << R_TIMG_T0CONFIG_DIVIDER_SHIFT; + qdev_init_gpio_out_named(DEVICE(sbd), &s->t0.interrupt_irq, ESP32C3_T0_IRQ_INTERRUPT, 1); + timer_init_ns(esp32c3_virtual_counter_get_timer(&s->t0.counter), QEMU_CLOCK_VIRTUAL, esp32c3_t0_cb, &s->t0); +} + +static Property esp32c3_timg_properties[] = { + // DEFINE_PROP_BOOL("wdt_disable", ESP32C3TimgState, wdt_disable, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32c3_timg_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_timg_reset; + dc->realize = esp32c3_timg_realize; + device_class_set_props(dc, esp32c3_timg_properties); +} + +static const TypeInfo esp32c3_timg_info = { + .name = TYPE_ESP32C3_TIMG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3TimgState), + .instance_init = esp32c3_timg_init, + .class_init = esp32c3_timg_class_init +}; + +static void esp32c3_timg_register_types(void) +{ + type_register_static(&esp32c3_timg_info); +} + +type_init(esp32c3_timg_register_types) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index e6da9aa6af7a..52f10dfcd2a9 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -35,6 +35,7 @@ softmmu_ss.add(when: 'CONFIG_STELLARIS_GPTM', if_true: files('stellaris-gptm.c') softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c')) softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_frc_timer.c', 'esp32_timg.c')) +softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_timg.c')) specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c')) diff --git a/include/hw/timer/esp32c3_timg.h b/include/hw/timer/esp32c3_timg.h new file mode 100644 index 000000000000..8a920fd860cd --- /dev/null +++ b/include/hw/timer/esp32c3_timg.h @@ -0,0 +1,255 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" + + +#define TYPE_ESP32C3_TIMG "esp32c3.timg" +#define ESP32C3_TIMG(obj) OBJECT_CHECK(ESP32C3TimgState, (obj), TYPE_ESP32C3_TIMG) +#define ESP32C3_TIMG_GET_CLASS(obj) OBJECT_GET_CLASS(ESP32C3TimgState, obj, TYPE_ESP32C3_TIMG) +#define ESP32C3_TIMG_CLASS(klass) OBJECT_CLASS_CHECK(ESP32C3TimgState, klass, TYPE_ESP32C3_TIMG) + + +/** + * Size of the Timegroup I/O registers area + */ +#define ESP32C3_TIMG_IO_SIZE (A_TIMGCLK + 4) + +/** + * Values related to the TIMG T0 counter + */ +#define ESP32C3_TIMG_T0_MAX_VALUE ((1ULL << 54) - 1) +/* Limit value is used to calculate the distance between the alarm and the counter */ +#define ESP32C3_TIMG_T0_LIMIT (1ULL << 53) + +/** + * Value of each calibration clock available + */ +#define ESP32C3_TIMG_CALI_RC_SLOW_CLK 0 +#define ESP32C3_TIMG_CALI_RC_FAST_DIV_CLK 1 +#define ESP32C3_TIMG_CALI_XTAL32K_CLK 2 + +/** + * And their associated frequencies + */ +#define ESP32C3_APB_CLK 80000000UL +#define ESP32C3_XTAL_CLK 40000000UL +#define ESP32C3_RC_SLOW_FREQ 136000 +#define ESP32C3_RC_FAST_FREQ 17500000 +#define ESP32C3_RC_FAST_DIV_FREQ (ESP32C3_RC_FAST_FREQ / 256) +#define ESP32C3_XTAL32K_FREQ 32000 + + +/** + * Number of stages in the a single Watchdog timer + */ +#define ESP32C3_WDT_STAGE_COUNT 4 + +/** + * Default key value for the WKEY register. + */ +#define ESP32C3_WDT_DEFAULT_WKEY 0x50d83aa1 + +/** + * Define two names for the WDT's interrupt IRQ and reset IRQ respectively + */ +#define ESP32C3_WDT_IRQ_RESET "wdt-reset" +#define ESP32C3_WDT_IRQ_INTERRUPT "wdt-interrupt" + + +#define ESP32C3_T0_IRQ_INTERRUPT "t0-interrupt" + + +typedef enum { + ESP32C3_WDT_OFF = 0, + ESP32C3_WDT_INTERRUPT = 1, + ESP32C3_WDT_RESET_CPU = 2, + ESP32C3_WDT_RESET_SYS = 3, +} ESP32C3WdtStageConf; + + +typedef struct ESP32C3VirtualCounter { + QEMUTimer timer; + /* Timer current value in ticks */ + uint64_t value; + /* Time when the value was last updated */ + uint64_t base; + /* Frequency, in Hz, of the timer */ + uint64_t frequency; +} ESP32C3VirtualCounter; + + +typedef struct ESP32C3WdtState { + /* Store the configuration register as is, it will ease reads perform to it */ + uint32_t config0; + /* Only keep the prescaler field for the config1 register */ + uint32_t prescaler; + /* Value of each stage, in MWDT clock cycles! (CLK / Prescaler) */ + uint32_t stage[ESP32C3_WDT_STAGE_COUNT]; + /* Value used to protect writes to the registers */ + uint32_t wkey; + /* Raw status of the interrupt */ + int raw_st; + bool int_enabled; + + /* These are mirror values that are written by the software */ + uint32_t prescaler_mirror; + uint32_t stage_mirror[ESP32C3_WDT_STAGE_COUNT]; + + /* "Private" members, not accessible by the software */ + /* Mirror of the stages configuration */ + ESP32C3WdtStageConf stage_conf[ESP32C3_WDT_STAGE_COUNT]; + /* The stage is comprised between 0 and ESP32C3_WDT_STAGE_COUNT */ + int current_stage; + ESP32C3VirtualCounter counter; + qemu_irq reset_irq; + qemu_irq interrupt_irq; +} ESP32C3WdtState; + + +typedef struct ESP32C3T0State { + uint32_t config; + /* Register containing the alarm value */ + uint64_t alarm; + /* Relative value that will be inc/dec according to the configuration */ + uint64_t value_rel; + /* Register containing the current counter value after a flush request */ + uint64_t value_flushed; + /* Register containing the value to copy to the counter */ + uint64_t value_toload; + + /* Raw status of the interrupt */ + int raw_st; + bool int_enabled; + ESP32C3VirtualCounter counter; + qemu_irq interrupt_irq; +} ESP32C3T0State; + + +typedef struct ESP32C3RtcState { + uint32_t rtc_cali_cfg; + /* Register storing the result of calibration (RTCCALICFG1) */ + uint32_t rtc_cali_cfg_result; + /* Register storing the calibration timeout (RTCCALICFG2) */ + uint32_t rtc_cali_cfg_timeout; +} ESP32C3RtcState; + + +typedef struct ESP32C3TimgState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + ESP32C3T0State t0; + ESP32C3WdtState wdt; + ESP32C3RtcState rtc; +} ESP32C3TimgState; + + +REG32(TIMG_T0CONFIG, 0x0000) + FIELD(TIMG_T0CONFIG, EN, 31, 1) + FIELD(TIMG_T0CONFIG, INCREASE, 30, 1) + FIELD(TIMG_T0CONFIG, AUTORELOAD, 29, 1) + FIELD(TIMG_T0CONFIG, DIVIDER, 13, 16) + FIELD(TIMG_T0CONFIG, DIVCNT_RST, 12, 1) + FIELD(TIMG_T0CONFIG, ALARM_EN, 10, 1) + FIELD(TIMG_T0CONFIG, USE_XTAL, 9, 1) + +REG32(TIMG_T0LO, 0x0004) + FIELD(TIMG_T0LO, LO, 0, 32) + +REG32(TIMG_T0HI, 0x0008) + FIELD(TIMG_T0HI, HI, 0, 22) + +REG32(TIMG_T0UPDATE, 0x000c) + FIELD(TIMG_T0UPDATE, UPDATE, 31, 1) + +REG32(TIMG_T0ALARMLO, 0x0010) + FIELD(TIMG_T0ALARMLO, ALARM_LO, 0, 32) + +REG32(TIMG_T0ALARMHI, 0x0014) + FIELD(TIMG_T0ALARMHI, ALARM_HI, 0, 22) + +REG32(TIMG_T0LOADLO, 0x0018) + FIELD(TIMG_T0LOADLO, LOAD_LO, 0, 32) + +REG32(TIMG_T0LOADHI, 0x001c) + FIELD(TIMG_T0LOADHI, LOAD_HI, 0, 22) + +REG32(TIMG_T0LOAD, 0x0020) + FIELD(TIMG_T0LOAD, LOAD, 0, 32) + +REG32(TIMG_WDTCONFIG0, 0x0048) + FIELD(TIMG_WDTCONFIG0, EN, 31, 1) + FIELD(TIMG_WDTCONFIG0, STG0, 29, 2) + FIELD(TIMG_WDTCONFIG0, STG1, 27, 2) + FIELD(TIMG_WDTCONFIG0, STG2, 25, 2) + FIELD(TIMG_WDTCONFIG0, STG3, 23, 2) + FIELD(TIMG_WDTCONFIG0, CONF_UPDATE_EN, 22, 1) + FIELD(TIMG_WDTCONFIG0, USE_XTAL, 21, 1) + FIELD(TIMG_WDTCONFIG0, CPU_RESET_LENGTH, 18, 3) + FIELD(TIMG_WDTCONFIG0, SYS_RESET_LENGTH, 15, 3) + FIELD(TIMG_WDTCONFIG0, FLASHBOOT_MOD_EN, 14, 1) + FIELD(TIMG_WDTCONFIG0, PROCPU_RESET_EN, 13, 1) + FIELD(TIMG_WDTCONFIG0, APPCPU_RESET_EN, 12, 1) + +REG32(TIMG_WDTCONFIG1, 0x004c) + FIELD(TIMG_WDTCONFIG1, CLK_PRESCALE, 16, 16) + FIELD(TIMG_WDTCONFIG1, DIVCNT_RST, 0, 1) + +REG32(TIMG_WDTCONFIG2, 0x0050) + FIELD(TIMG_WDTCONFIG2, STG0_HOLD, 0, 32) + +REG32(TIMG_WDTCONFIG3, 0x0054) + FIELD(TIMG_WDTCONFIG3, STG1_HOLD, 0, 32) + +REG32(TIMG_WDTCONFIG4, 0x0058) + FIELD(TIMG_WDTCONFIG4, STG2_HOLD, 0, 32) + +REG32(TIMG_WDTCONFIG5, 0x005c) + FIELD(TIMG_WDTCONFIG5, STG3_HOLD, 0, 32) + +REG32(TIMG_WDTFEED, 0x0060) + FIELD(TIMG_WDTFEED, FEED, 0, 32) + +REG32(TIMG_WDTWPROTECT, 0x0064) + FIELD(TIMG_WDTWPROTECT, WKEY, 0, 32) + +REG32(TIMG_RTCCALICFG, 0x0068) + FIELD(TIMG_RTCCALICFG, START, 31, 1) + FIELD(TIMG_RTCCALICFG, MAX, 16, 15) + FIELD(TIMG_RTCCALICFG, RDY, 15, 1) + FIELD(TIMG_RTCCALICFG, CLK_SEL, 13, 2) + FIELD(TIMG_RTCCALICFG, START_CYCLING, 12, 1) + +REG32(TIMG_RTCCALICFG1, 0x006c) + FIELD(TIMG_RTCCALICFG1, VALUE, 7, 25) + FIELD(TIMG_RTCCALICFG1, CYCLING_DATA_VLD, 0, 1) + +REG32(TIMG_INT_ENA_TIMG, 0x0070) + FIELD(TIMG_INT_ENA_TIMG, WDT_ENA, 1, 1) + FIELD(TIMG_INT_ENA_TIMG, T0_ENA, 0, 1) + +REG32(TIMG_INT_RAW_TIMG, 0x0074) + FIELD(TIMG_INT_RAW_TIMG, WDT_RAW, 1, 1) + FIELD(TIMG_INT_RAW_TIMG, T0_RAW, 0, 1) + +REG32(TIMG_INT_ST_TIMG, 0x0078) + FIELD(TIMG_INT_ST_TIMG, WDT_ST, 1, 1) + FIELD(TIMG_INT_ST_TIMG, T0_ST, 0, 1) + +REG32(TIMG_INT_CLR_TIMG, 0x007c) + FIELD(TIMG_INT_CLR_TIMG, WDT_CLR, 1, 1) + FIELD(TIMG_INT_CLR_TIMG, T0_CLR, 0, 1) + +REG32(TIMG_RTCCALICFG2, 0x0080) + FIELD(TIMG_RTCCALICFG2, TIMEOUT_THRES, 7, 25) + FIELD(TIMG_RTCCALICFG2, TIMEOUT_RST_CNT, 3, 4) + FIELD(TIMG_RTCCALICFG2, TIMEOUT, 0, 1) + +REG32(TIMG_NTIMG_DATE, 0x00f8) + FIELD(TIMG_NTIMG_DATE, TIMG_NTIMGS_DATE, 0, 28) + +REG32(TIMGCLK, 0x00fc) + FIELD(TIMGCLK, CLK_EN, 31, 1) + FIELD(TIMGCLK, TIMER_CLK_IS_ACTIVE, 30, 1) + FIELD(TIMGCLK, WDT_CLK_IS_ACTIVE, 29, 1) From 96a20ccadbcb2c885deea80f7d9dfbe726476483 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:38:17 +0800 Subject: [PATCH 33/56] hw/timer: implement ESP32-C3 System Timer Systimer Timer is fully implemented --- hw/timer/esp32c3_systimer.c | 603 ++++++++++++++++++++++++++++ hw/timer/meson.build | 2 +- include/hw/timer/esp32c3_systimer.h | 231 +++++++++++ 3 files changed, 835 insertions(+), 1 deletion(-) create mode 100644 hw/timer/esp32c3_systimer.c create mode 100644 include/hw/timer/esp32c3_systimer.h diff --git a/hw/timer/esp32c3_systimer.c b/hw/timer/esp32c3_systimer.c new file mode 100644 index 000000000000..c3856561ec29 --- /dev/null +++ b/hw/timer/esp32c3_systimer.c @@ -0,0 +1,603 @@ +/* + * ESP32-C3 System Timer + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/registerfields.h" +#include "hw/boards.h" +#include "hw/timer/esp32c3_systimer.h" + + +#define TICKS_TO_NS(ticks) (((ticks) / ESP32C3_SYSTIMER_CNT_PER_US) * 1000) + +#define SYSTIMER_DEBUG 0 +#define SYSTIMER_WARNING 0 + +/** + * @brief Update the value of a counter according the QEMU virtual timer. + */ +static void esp32c3_systimer_update_counter(ESP32C3SysTimerCounter *counter) { + const int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + const int64_t elapsed_ns = now - counter->base; + const int64_t ticks = (elapsed_ns * (ESP32C3_SYSTIMER_CNT_CLK / 1000000)) / 1000; + counter->value = (counter->value + ticks) & ESP32C3_SYSTIMER_52BIT_MASK; + counter->base = now; +} + + +static void esp32c3_systimer_set_irqs(ESP32C3SysTimerState *s) +{ + for (int i = 0; i < ESP32C3_SYSTIMER_COMP_COUNT; i++) { + ESP32C3SysTimerComp* comparator = &s->comparators[i]; + /* Optimize a bit by not calling the interrupt module if the state didn't change */ + const int new_level = comparator->raw_st && comparator->int_enabled; + if (new_level != comparator->cur_irq_level) { + comparator->cur_irq_level = new_level; + qemu_set_irq(comparator->irq, new_level); + } + } +} + + +static void esp32c3_systimer_notify(ESP32C3SysTimerComp* comparator) +{ + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +#if SYSTIMER_DEBUG + static int64_t previous = 0; + info_report("Elapsed since last interrupt %ld ns\n", now - previous); + previous = now; +#endif + + /* Update the counter linked to the comparator */ + const uint32_t counter_idx = comparator->counter; + ESP32C3SysTimerState *s = comparator->systimer; + ESP32C3SysTimerCounter* counter = &s->counter[counter_idx]; + + if (counter->enabled) { + esp32c3_systimer_update_counter(counter); + } + + /* Set the IRQ line if anything changed */ + comparator->cur_irq_level = 1; + qemu_irq_raise(comparator->irq); + + /* Check if we have to reload the comparator's timer */ + if (counter->enabled && comparator->period_mode) { + /** + * If the timer is periodic, we have to compensate the delay that may have been taken + * by QEMU framework. Indeed, this timer may have been triggered too late (tenth of us) + * As such, compensate here by triggering the next timer earlier. + */ + const int64_t diff_ns = now - comparator->expire_time; + const int64_t target_ns = now + TICKS_TO_NS(comparator->period); + int64_t adjusted_target_ns = target_ns; + + if (diff_ns < target_ns) { + adjusted_target_ns = target_ns - diff_ns; + } + + comparator->expire_time = adjusted_target_ns; + timer_mod_ns(&comparator->qtimer, adjusted_target_ns); + } +} + + +/** + * @brief Function called when the configuration of the given comparator changed. + * It will reprogram the QEMU Timer according to the new parameters. The comparator + * must be enabled when this function is called. + */ +static void esp32c3_systimer_comparator_reprogram(ESP32C3SysTimerComp* comparator) +{ + assert(comparator->enabled); + + const uint32_t counter_idx = comparator->counter; + ESP32C3SysTimerState *s = comparator->systimer; + ESP32C3SysTimerCounter* counter = &s->counter[counter_idx]; + + /* Update the counter to get the latest value */ + esp32c3_systimer_update_counter(counter); + + /* If the counter we have to compare it to is not enabled, do not program any timer */ + if (!counter->enabled) { + /* "Disable" the timer */ + timer_del(&comparator->qtimer); + return; + } + + /** + * According to the TRM, if the comparator (alarm) is smaller than the counter value and the + * difference is bigger or equal to (2^51) - 1, the alarm is not triggered right now and the counter + * will have to overflow first before reached the comparator value. + */ + const int64_t count_val = counter->value; + const int64_t alarm = comparator->value; + const bool overflow_valid = alarm < count_val && count_val - alarm >= ((1ULL << 51) - 1); + + if (!comparator->period_mode && !overflow_valid && alarm <= count_val) { + timer_del(&comparator->qtimer); + esp32c3_systimer_notify(comparator); + return; + } + + /* Calculate in how many ns the counter would reach the comparator */ + uint64_t diff = 0; + + if (comparator->period_mode) { + diff = comparator->period; + } else if (overflow_valid) { + diff = ((ESP32C3_SYSTIMER_52BIT_MASK + 1) - count_val) + alarm; + } else { + diff = alarm - count_val; + } + + /* Calculate the number of ns the counter will take to reach the absolute count */ + const int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + const int64_t target_ns = now + TICKS_TO_NS(diff); + comparator->expire_time = target_ns; + timer_mod_ns(&comparator->qtimer, target_ns); +} + + +static uint32_t esp32c3_systimer_comparator_get_conf(ESP32C3SysTimerComp *comp) +{ + uint32_t reg = comp->period & R_SYSTIMER_TARGET0_CONF_PERIOD_MASK; + reg |= (comp->period_mode << R_SYSTIMER_TARGET0_CONF_PERIOD_MODE_SHIFT) & R_SYSTIMER_TARGET0_CONF_PERIOD_MODE_MASK; + reg |= (comp->counter << R_SYSTIMER_TARGET0_CONF_TIMER_UNIT_SEL_SHIFT) & R_SYSTIMER_TARGET0_CONF_TIMER_UNIT_SEL_MASK; + return reg; +} + + +static uint64_t esp32c3_systimer_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3SysTimerState *s = ESP32C3_SYSTIMER(opaque); + uint64_t r = 0; + + switch (addr) { + case A_SYSTIMER_CONF: + r = s->conf; + break; + case A_SYSTIMER_UNIT0_OP: + case A_SYSTIMER_UNIT1_OP: + /* Value is always synchronized and valid */ + r = R_SYSTIMER_UNIT0_OP_VALUE_VALID_MASK; + break; + + /* Registers linked to UNIT0 registers */ + case A_SYSTIMER_UNIT0_VALUE_HI: + r = SYSTIMER_GET_REG(s->counter[0].flushed, 32, R_SYSTIMER_UNIT0_VALUE_HI_TIMER_HI_MASK); + break; + case A_SYSTIMER_UNIT0_VALUE_LO: + r = SYSTIMER_GET_REG(s->counter[0].flushed, 0, R_SYSTIMER_UNIT0_VALUE_LO_TIMER_LO_MASK); + break; + case A_SYSTIMER_UNIT0_LOAD_HI: + r = SYSTIMER_GET_REG(s->counter[0].toload, 32, R_SYSTIMER_UNIT0_LOAD_HI_HI_MASK); + break; + case A_SYSTIMER_UNIT0_LOAD_LO: + r = SYSTIMER_GET_REG(s->counter[0].toload, 0, R_SYSTIMER_UNIT0_LOAD_LO_LO_MASK); + break; + + /* Same for UNIT1 */ + case A_SYSTIMER_UNIT1_VALUE_HI: + r = SYSTIMER_GET_REG(s->counter[1].flushed, 32, R_SYSTIMER_UNIT1_VALUE_HI_TIMER_HI_MASK); + break; + case A_SYSTIMER_UNIT1_VALUE_LO: + r = SYSTIMER_GET_REG(s->counter[1].flushed, 0, R_SYSTIMER_UNIT1_VALUE_LO_TIMER_LO_MASK); + break; + case A_SYSTIMER_UNIT1_LOAD_HI: + r = SYSTIMER_GET_REG(s->counter[1].toload, 32, R_SYSTIMER_UNIT1_LOAD_HI_HI_MASK); + break; + case A_SYSTIMER_UNIT1_LOAD_LO: + r = SYSTIMER_GET_REG(s->counter[1].toload, 0, R_SYSTIMER_UNIT1_LOAD_LO_LO_MASK); + break; + + /* Read back the value of the comparators */ + case A_SYSTIMER_TARGET0_HI: + r = SYSTIMER_GET_REG(s->comparators[0].value_toload, 32, R_SYSTIMER_TARGET0_HI_HI_MASK); + break; + case A_SYSTIMER_TARGET0_LO: + r = SYSTIMER_GET_REG(s->comparators[0].value_toload, 0, R_SYSTIMER_TARGET0_LO_LO_MASK); + break; + case A_SYSTIMER_TARGET0_CONF: + r = esp32c3_systimer_comparator_get_conf(&s->comparators[0]); + break; + + /* Registers linked to Comparator 1 */ + case A_SYSTIMER_TARGET1_HI: + r = SYSTIMER_GET_REG(s->comparators[1].value_toload, 32, R_SYSTIMER_TARGET1_HI_HI_MASK); + break; + case A_SYSTIMER_TARGET1_LO: + r = SYSTIMER_GET_REG(s->comparators[1].value_toload, 0, R_SYSTIMER_TARGET1_LO_LO_MASK); + break; + case A_SYSTIMER_TARGET1_CONF: + r = esp32c3_systimer_comparator_get_conf(&s->comparators[1]); + break; + + /* Registers linked to Comparator 2 */ + case A_SYSTIMER_TARGET2_HI: + r = SYSTIMER_GET_REG(s->comparators[2].value_toload, 32, R_SYSTIMER_TARGET2_HI_HI_MASK); + break; + case A_SYSTIMER_TARGET2_LO: + r = SYSTIMER_GET_REG(s->comparators[2].value_toload, 0, R_SYSTIMER_TARGET2_LO_LO_MASK); + break; + case A_SYSTIMER_TARGET2_CONF: + r = esp32c3_systimer_comparator_get_conf(&s->comparators[2]); + break; + + /* Interrupt related */ + case A_SYSTIMER_INT_RAW: + r = s->comparators[0].raw_st << R_SYSTIMER_INT_RAW_TARGET0_SHIFT + | s->comparators[1].raw_st << R_SYSTIMER_INT_RAW_TARGET1_SHIFT + | s->comparators[2].raw_st << R_SYSTIMER_INT_RAW_TARGET2_SHIFT; + break; + + case A_SYSTIMER_INT_ENA: + r = s->comparators[0].int_enabled << R_SYSTIMER_INT_ENA_TARGET0_SHIFT + | s->comparators[1].int_enabled << R_SYSTIMER_INT_ENA_TARGET1_SHIFT + | s->comparators[2].int_enabled << R_SYSTIMER_INT_ENA_TARGET2_SHIFT; + break; + + case A_SYSTIMER_INT_ST: + r = (s->comparators[0].raw_st & s->comparators[0].int_enabled) << R_SYSTIMER_INT_ST_TARGET0_SHIFT + | (s->comparators[1].raw_st & s->comparators[1].int_enabled) << R_SYSTIMER_INT_ST_TARGET1_SHIFT + | (s->comparators[2].raw_st & s->comparators[2].int_enabled) << R_SYSTIMER_INT_ST_TARGET2_SHIFT; + break; + + case A_SYSTIMER_INT_CLR: + /* This register is read-only */ + break; + + default: +#if SYSTIMER_WARNING + warn_report("[SYSTIMER] Unsupported read to %08lx\n", addr); +#endif + break; + } + +#if SYSTIMER_DEBUG + info_report("[SYSTIMER] Reading from %08lx (%08lx)\n", addr, r); +#endif + return r; +} + +/** + * @brief Function called when a guest program requests a flush of the internal + * counter inside a mirror register: `flushed`. + */ +static void esp32c3_systimer_flush_counter(ESP32C3SysTimerCounter *counter) +{ + /* If the counter is enabled, get its latest value */ + if (counter->enabled) { + esp32c3_systimer_update_counter(counter); + } + /* In any case, flush the value to send to the guest program */ + counter->flushed = counter->value; +} + +/** + * @brief Function called when the guest programs wants to replace the value + * of the given counter + */ +static void esp32c3_systimer_load_counter(ESP32C3SysTimerState *s, uint32_t index) +{ + ESP32C3SysTimerCounter* counter = &s->counter[index]; + + /* If the counter is enabled, update the internal value to the latest count. + * Even though the value will be replaced, this will also update the base time. */ + if (counter->enabled) { + esp32c3_systimer_update_counter(counter); + } + counter->value = counter->toload; + + /* If one of the comparator is enabled and depends on the current timer, reprogram it */ + for (int i = 0; i < ESP32C3_SYSTIMER_COMP_COUNT; i++) { + if (s->comparators[i].enabled && s->comparators[i].counter == index) { + esp32c3_systimer_comparator_reprogram(&s->comparators[i]); + } + } +} + + +static void esp32c3_systimer_comparator_conf(ESP32C3SysTimerComp* comparator, uint64_t value) +{ + uint32_t old_counter = comparator->counter; + comparator->period_mode = (value & R_SYSTIMER_TARGET0_CONF_PERIOD_MODE_MASK) ? 1 : 0; + comparator->counter = (value & R_SYSTIMER_TARGET0_CONF_TIMER_UNIT_SEL_MASK) ? 1 : 0; + comparator->period_toload = value & R_SYSTIMER_TARGET0_CONF_PERIOD_MASK; + + /* If the comparator is enabled while the counter to compare it to changed, reload the timer! */ + if (comparator->enabled && old_counter != comparator->counter) { + esp32c3_systimer_comparator_reprogram(comparator); + } +} + + +static void esp32c3_systimer_comparator_reload(ESP32C3SysTimerComp* comparator) +{ + comparator->period = comparator->period_toload; + comparator->value = comparator->value_toload; + + if (comparator->enabled) { + /* The period changed, reprogram the QEMU timer */ + esp32c3_systimer_comparator_reprogram(comparator); + } +} + + +static void esp32c3_systimer_conf_set(ESP32C3SysTimerState *s, uint64_t value) +{ + bool state[ESP32C3_SYSTIMER_COMP_COUNT] = { 0 }; + bool state_counter[ESP32C3_SYSTIMER_COUNTER_COUNT] = { 0 }; + + for (int i = 0; i < ESP32C3_SYSTIMER_COUNTER_COUNT; i++) { + state_counter[i] = s->counter[i].enabled; + } + s->counter[0].enabled = (value & R_SYSTIMER_CONF_TIMER_UNIT0_WORK_EN_MASK) ? 1 : 0; + s->counter[1].enabled = (value & R_SYSTIMER_CONF_TIMER_UNIT1_WORK_EN_MASK) ? 1 : 0; + s->counter[0].enabled_on_stall = (value & R_SYSTIMER_CONF_TIMER_UNIT0_CORE0_STALL_EN_MASK) ? 1 : 0; + s->counter[1].enabled_on_stall = (value & R_SYSTIMER_CONF_TIMER_UNIT1_CORE0_STALL_EN_MASK) ? 1 : 0; + + /* If the state of the counter changed while one of the comparator depends on it, reload it */ + for (int i = 0; i < ESP32C3_SYSTIMER_COMP_COUNT; i++) { + const int count_idx = s->comparators[i].counter; + + if (s->comparators[i].enabled && state_counter[count_idx] != s->counter[count_idx].enabled) { + esp32c3_systimer_comparator_reprogram(&s->comparators[i]); + } + } + + + /** + * Do the same thing for the comparators: assign the new state while checking if a change occurred, + * if that's the case, reprogram it. + */ + for (int i = 0; i < ESP32C3_SYSTIMER_COMP_COUNT; i++) { + state[i] = s->comparators[i].enabled; + } + + s->comparators[0].enabled = (value & R_SYSTIMER_CONF_TARGET0_WORK_EN_MASK) ? 1 : 0; + s->comparators[1].enabled = (value & R_SYSTIMER_CONF_TARGET1_WORK_EN_MASK) ? 1 : 0; + s->comparators[2].enabled = (value & R_SYSTIMER_CONF_TARGET2_WORK_EN_MASK) ? 1 : 0; + + for (int i = 0; i < ESP32C3_SYSTIMER_COMP_COUNT; i++) { + if (state[i] == s->comparators[i].enabled) { + continue; + } + + /* If the comparator has just been enabled, (re)program it. + * If it was enabled and it is now disabled, disable the QEMU timer. */ + if (s->comparators[i].enabled) { + esp32c3_systimer_comparator_reprogram(&s->comparators[i]); + } else { + timer_del(&s->comparators[i].qtimer); + } + } + + /* Ignore R_SYSTIMER_CONF_CLK_EN */ + s->conf = (uint32_t) value; +} + + +static void esp32c3_systimer_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3SysTimerState *s = ESP32C3_SYSTIMER(opaque); + (void) s; + + switch(addr) { + case A_SYSTIMER_CONF: + esp32c3_systimer_conf_set(s, value); + break; + case A_SYSTIMER_UNIT0_OP: + case A_SYSTIMER_UNIT1_OP: + /* Check if an update was requested on one of the timers */ + if (value & R_SYSTIMER_UNIT0_OP_UPDATE_MASK) { + /* Address is either 4 (unit0) or 8 (unit 1), get index by dividing by 8 */ + esp32c3_systimer_flush_counter(&s->counter[addr / 8]); + } + break; + + /* Registers linked to UNIT0 registers */ + case A_SYSTIMER_UNIT0_LOAD_HI: + systimer_set_reg(&s->counter[0].toload, value, R_SYSTIMER_UNIT0_LOAD_HI_HI_MASK, 32); + break; + case A_SYSTIMER_UNIT0_LOAD_LO: + systimer_set_reg(&s->counter[0].toload, value, R_SYSTIMER_UNIT0_LOAD_LO_LO_MASK, 0); + break; + case A_SYSTIMER_UNIT0_LOAD: + esp32c3_systimer_load_counter(s, 0); + break; + + /* Registers linked to UNIT1 registers */ + case A_SYSTIMER_UNIT1_LOAD_HI: + systimer_set_reg(&s->counter[1].toload, value, R_SYSTIMER_UNIT1_LOAD_HI_HI_MASK, 32); + break; + case A_SYSTIMER_UNIT1_LOAD_LO: + systimer_set_reg(&s->counter[1].toload, value, R_SYSTIMER_UNIT1_LOAD_LO_LO_MASK, 0); + break; + case A_SYSTIMER_UNIT1_LOAD: + esp32c3_systimer_load_counter(s, 1); + break; + + /* Registers linked to Comparator 0 */ + case A_SYSTIMER_TARGET0_HI: + systimer_set_reg(&s->comparators[0].value_toload, value, R_SYSTIMER_TARGET0_HI_HI_MASK, 32); + break; + case A_SYSTIMER_TARGET0_LO: + systimer_set_reg(&s->comparators[0].value_toload, value, R_SYSTIMER_TARGET0_LO_LO_MASK, 0); + break; + case A_SYSTIMER_TARGET0_CONF: + esp32c3_systimer_comparator_conf(&s->comparators[0], value); + break; + case A_SYSTIMER_COMP0_LOAD: + if (value & R_SYSTIMER_COMP0_LOAD_LOAD_MASK) { + esp32c3_systimer_comparator_reload(&s->comparators[0]); + } + break; + + /* Registers linked to Comparator 1 */ + case A_SYSTIMER_TARGET1_HI: + systimer_set_reg(&s->comparators[1].value_toload, value, R_SYSTIMER_TARGET1_HI_HI_MASK, 32); + break; + case A_SYSTIMER_TARGET1_LO: + systimer_set_reg(&s->comparators[1].value_toload, value, R_SYSTIMER_TARGET1_LO_LO_MASK, 0); + break; + case A_SYSTIMER_TARGET1_CONF: + esp32c3_systimer_comparator_conf(&s->comparators[1], value); + break; + case A_SYSTIMER_COMP1_LOAD: + if (value & R_SYSTIMER_COMP1_LOAD_LOAD_MASK) { + esp32c3_systimer_comparator_reload(&s->comparators[1]); + } + break; + + /* Registers linked to Comparator 2 */ + case A_SYSTIMER_TARGET2_HI: + systimer_set_reg(&s->comparators[2].value_toload, value, R_SYSTIMER_TARGET2_HI_HI_MASK, 32); + break; + case A_SYSTIMER_TARGET2_LO: + systimer_set_reg(&s->comparators[2].value_toload, value, R_SYSTIMER_TARGET2_LO_LO_MASK, 0); + break; + case A_SYSTIMER_TARGET2_CONF: + esp32c3_systimer_comparator_conf(&s->comparators[2], value); + break; + case A_SYSTIMER_COMP2_LOAD: + if (value & R_SYSTIMER_COMP2_LOAD_LOAD_MASK) { + esp32c3_systimer_comparator_reload(&s->comparators[2]); + } + break; + + /* Interrupt related */ + case A_SYSTIMER_INT_RAW: + case A_SYSTIMER_INT_ST: +#if SYSTIMER_WARNING + warn_report("[SYSTIMER] Unsupported write to INT RAW/ST registers\n"); +#endif + break; + + case A_SYSTIMER_INT_ENA: + s->comparators[0].int_enabled = FIELD_EX32(value, SYSTIMER_INT_ENA, TARGET0); + s->comparators[1].int_enabled = FIELD_EX32(value, SYSTIMER_INT_ENA, TARGET1); + s->comparators[2].int_enabled = FIELD_EX32(value, SYSTIMER_INT_ENA, TARGET2); + esp32c3_systimer_set_irqs(s); + break; + + case A_SYSTIMER_INT_CLR: + /* The formula (RAW & !CLR) results in 0 if both CLR and RAW were 1, else it keeps + * RAW unchanged. */ + s->comparators[0].raw_st &= ! FIELD_EX32(value, SYSTIMER_INT_CLR, TARGET0); + s->comparators[1].raw_st &= ! FIELD_EX32(value, SYSTIMER_INT_CLR, TARGET1); + s->comparators[2].raw_st &= ! FIELD_EX32(value, SYSTIMER_INT_CLR, TARGET2); + esp32c3_systimer_set_irqs(s); + break; + + default: +#if SYSTIMER_WARNING + warn_report("[SYSTIMER] Unsupported write to registers %08lx (%08lx)\n", addr, value); +#endif + break; + } + +#if SYSTIMER_DEBUG + info_report("[SYSTIMER] Writing to %08lx = %08lx\n", addr, value); +#endif +} + + +static const MemoryRegionOps esp32c3_systimer_ops = { + .read = esp32c3_systimer_read, + .write = esp32c3_systimer_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32c3_systimer_cb(void* opaque) +{ + ESP32C3SysTimerComp* comparator = (ESP32C3SysTimerComp*) opaque; + esp32c3_systimer_notify(comparator); +} + + +static void esp32c3_systimer_reset(DeviceState* ts) +{ + ESP32C3SysTimerState *s = ESP32C3_SYSTIMER(ts); + s->conf = 0; + for (int i = 0; i < ESP32C3_SYSTIMER_COMP_COUNT; i++) { + ESP32C3SysTimerComp* comp = &s->comparators[i]; + QEMUTimer qtimer = comp->qtimer; + qemu_irq irq = comp->irq; + + /* Disable all the timers/irq first */ + timer_del(&comp->qtimer); + qemu_irq_lower(comp->irq); + + /* Reset the data of the comparator */ + memset(comp, 0, sizeof(ESP32C3SysTimerComp)); + + /* Restore the former fields that were already initialized */ + comp->qtimer = qtimer; + comp->irq = irq; + comp->systimer = s; + } +} + + +static void esp32c3_systimer_realize(DeviceState *dev, Error **errp) +{ +} + + +static void esp32c3_systimer_init(Object *obj) +{ + ESP32C3SysTimerState *s = ESP32C3_SYSTIMER(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_systimer_ops, s, + TYPE_ESP32C3_SYSTIMER, ESP32C3_SYSTIMER_IO_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + + for (uint64_t i = 0; i < ESP32C3_SYSTIMER_COMP_COUNT; i++) { + s->comparators[i].systimer = s; + sysbus_init_irq(sbd, &s->comparators[i].irq); + timer_init_ns(&s->comparators[i].qtimer, QEMU_CLOCK_VIRTUAL, esp32c3_systimer_cb, &s->comparators[i]); + } +} + + +static void esp32c3_systimer_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_systimer_reset; + dc->realize = esp32c3_systimer_realize; +} + + +static const TypeInfo esp32c3_systimer_info = { + .name = TYPE_ESP32C3_SYSTIMER, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3SysTimerState), + .instance_init = esp32c3_systimer_init, + .class_init = esp32c3_systimer_class_init +}; + + +static void esp32c3_systimer_register_types(void) +{ + type_register_static(&esp32c3_systimer_info); +} + + +type_init(esp32c3_systimer_register_types) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 52f10dfcd2a9..e148cd1219a2 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -35,7 +35,7 @@ softmmu_ss.add(when: 'CONFIG_STELLARIS_GPTM', if_true: files('stellaris-gptm.c') softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c')) softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_frc_timer.c', 'esp32_timg.c')) -softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_timg.c')) +softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_timg.c', 'esp32c3_systimer.c')) specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c')) diff --git a/include/hw/timer/esp32c3_systimer.h b/include/hw/timer/esp32c3_systimer.h new file mode 100644 index 000000000000..495930fb8ba0 --- /dev/null +++ b/include/hw/timer/esp32c3_systimer.h @@ -0,0 +1,231 @@ +/* + * ESP32-C3 System Timer emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" + + +#define TYPE_ESP32C3_SYSTIMER "esp32c3.systimer" +#define ESP32C3_SYSTIMER(obj) OBJECT_CHECK(ESP32C3SysTimerState, (obj), TYPE_ESP32C3_SYSTIMER) +#define ESP32C3_SYSTIMER_GET_CLASS(obj) OBJECT_GET_CLASS(ESP32C3SysTimerState, obj, TYPE_ESP32C3_SYSTIMER) +#define ESP32C3_SYSTIMER_CLASS(klass) OBJECT_CLASS_CHECK(ESP32C3SysTimerState, klass, TYPE_ESP32C3_SYSTIMER) + + +/** + * Size of the System Timer I/O registers area + */ +#define ESP32C3_SYSTIMER_IO_SIZE (A_SYSTIMER_DATE + 4) + +/** + * Mask to get a 52 value out of a 64 bit value + */ +#define ESP32C3_SYSTIMER_52BIT_MASK ((1ULL << 52) - 1) + +/** + * Frequency of the CNT_CLK + */ +#define ESP32C3_SYSTIMER_CNT_CLK 16000000 + +/** + * Ticks per microsecond + */ +#define ESP32C3_SYSTIMER_CNT_PER_US (ESP32C3_SYSTIMER_CNT_CLK / 1000000) + +/** + * Macro to help updating part of a register/variable + */ +static inline void systimer_set_reg(uint64_t* reg, uint64_t value, uint64_t mask, uint64_t shift) +{ + const uint64_t new_val = (value & mask) << shift; + *reg = (*reg & ~(mask << shift)) | new_val; +} + +#define SYSTIMER_GET_REG(reg, shift, mask) (((reg) >> (shift)) & (mask)) + +/** + * Number of comparator in a single System Timer module + */ +#define ESP32C3_SYSTIMER_COMP_COUNT 3 + +/** + * Number of counters in a single System Time module + */ +#define ESP32C3_SYSTIMER_COUNTER_COUNT 2 + +/** + * Number of interrupt line of the System Time module + */ +#define ESP32C3_SYSTIMER_IRQ_COUNT (ESP32C3_SYSTIMER_COMP_COUNT) + + +typedef struct { + bool enabled; + /* Enabled on CPU stall */ + bool enabled_on_stall; + uint64_t value; // Internal counter that should be updated as often as possible + uint64_t toload; // Counter that can be loaded by the guest program + uint64_t flushed; // Mirror of the internal counter that can be seen by the guest program + /* Absolute time, in ns, when value was updated last */ + int64_t base; +} ESP32C3SysTimerCounter; + + +/* This typedef must be placed here as it will be used by the structure below */ +typedef struct ESP32C3SysTimerState ESP32C3SysTimerState; + +typedef struct { + uint64_t value; + uint64_t value_toload; + uint32_t period; + uint32_t period_toload; + /* Mark whether the comparator is enabled */ + bool enabled; + bool period_mode; + /* Raw status of the comparator: 1 if it reached the threshold, 0 else */ + bool raw_st; + bool int_enabled; + /* Index of the counter that is linked to the comparator */ + uint32_t counter; + /* The easiest way to implement timeout is by using one timer per comparator */ + QEMUTimer qtimer; + uint64_t expire_time; + qemu_irq irq; + int cur_irq_level; + /* Pointer to the owner */ + ESP32C3SysTimerState* systimer; +} ESP32C3SysTimerComp; + + +struct ESP32C3SysTimerState { + SysBusDevice parent_obj; + MemoryRegion iomem; + /* Mirror of the comparators and counters state, only used to speed up + * reading of A_SYSTIMER_CONF register */ + uint32_t conf; + ESP32C3SysTimerCounter counter[ESP32C3_SYSTIMER_COUNTER_COUNT]; + ESP32C3SysTimerComp comparators[ESP32C3_SYSTIMER_COMP_COUNT]; +}; + + +REG32(SYSTIMER_CONF, 0x0000) + FIELD(SYSTIMER_CONF, CLK_EN, 31, 1) + FIELD(SYSTIMER_CONF, TIMER_UNIT0_WORK_EN, 30, 1) + FIELD(SYSTIMER_CONF, TIMER_UNIT1_WORK_EN, 29, 1) + FIELD(SYSTIMER_CONF, TIMER_UNIT0_CORE0_STALL_EN, 28, 1) + FIELD(SYSTIMER_CONF, TIMER_UNIT0_CORE1_STALL_EN, 27, 1) + FIELD(SYSTIMER_CONF, TIMER_UNIT1_CORE0_STALL_EN, 26, 1) + FIELD(SYSTIMER_CONF, TIMER_UNIT1_CORE1_STALL_EN, 25, 1) + FIELD(SYSTIMER_CONF, TARGET0_WORK_EN, 24, 1) + FIELD(SYSTIMER_CONF, TARGET1_WORK_EN, 23, 1) + FIELD(SYSTIMER_CONF, TARGET2_WORK_EN, 22, 1) + +REG32(SYSTIMER_UNIT0_OP, 0x0004) + FIELD(SYSTIMER_UNIT0_OP, UPDATE, 30, 1) + FIELD(SYSTIMER_UNIT0_OP, VALUE_VALID, 29, 1) + +REG32(SYSTIMER_UNIT1_OP, 0x0008) + FIELD(SYSTIMER_UNIT1_OP, UPDATE, 30, 1) + FIELD(SYSTIMER_UNIT1_OP, VALID, 29, 1) + +REG32(SYSTIMER_UNIT0_LOAD_HI, 0x000C) + FIELD(SYSTIMER_UNIT0_LOAD_HI, HI, 0, 20) + +REG32(SYSTIMER_UNIT0_LOAD_LO, 0x0010) + FIELD(SYSTIMER_UNIT0_LOAD_LO, LO, 0, 32) + +REG32(SYSTIMER_UNIT1_LOAD_HI, 0x0014) + FIELD(SYSTIMER_UNIT1_LOAD_HI, HI, 0, 20) + +REG32(SYSTIMER_UNIT1_LOAD_LO, 0x0018) + FIELD(SYSTIMER_UNIT1_LOAD_LO, LO, 0, 32) + +REG32(SYSTIMER_TARGET0_HI, 0x001C) + FIELD(SYSTIMER_TARGET0_HI, HI, 0, 20) + +REG32(SYSTIMER_TARGET0_LO, 0x0020) + FIELD(SYSTIMER_TARGET0_LO, LO, 0, 32) + +REG32(SYSTIMER_TARGET1_HI, 0x0024) + FIELD(SYSTIMER_TARGET1_HI, HI, 0, 20) + +REG32(SYSTIMER_TARGET1_LO, 0x0028) + FIELD(SYSTIMER_TARGET1_LO, LO, 0, 32) + +REG32(SYSTIMER_TARGET2_HI, 0x002C) + FIELD(SYSTIMER_TARGET2_HI, HI, 0, 20) + +REG32(SYSTIMER_TARGET2_LO, 0x0030) + FIELD(SYSTIMER_TARGET2_LO, LO, 0, 32) + +REG32(SYSTIMER_TARGET0_CONF, 0x0034) + FIELD(SYSTIMER_TARGET0_CONF, TIMER_UNIT_SEL, 31, 1) + FIELD(SYSTIMER_TARGET0_CONF, PERIOD_MODE, 30, 1) + FIELD(SYSTIMER_TARGET0_CONF, PERIOD, 0, 26) + +REG32(SYSTIMER_TARGET1_CONF, 0x0038) + FIELD(SYSTIMER_TARGET1_CONF, TIMER_UNIT_SEL, 31, 1) + FIELD(SYSTIMER_TARGET1_CONF, PERIOD_MODE, 30, 1) + FIELD(SYSTIMER_TARGET1_CONF, PERIOD, 0, 26) + +REG32(SYSTIMER_TARGET2_CONF, 0x003C) + FIELD(SYSTIMER_TARGET2_CONF, TIMER_UNIT_SEL, 31, 1) + FIELD(SYSTIMER_TARGET2_CONF, PERIOD_MODE, 30, 1) + FIELD(SYSTIMER_TARGET2_CONF, PERIOD, 0, 26) + +REG32(SYSTIMER_UNIT0_VALUE_HI, 0x0040) + FIELD(SYSTIMER_UNIT0_VALUE_HI, TIMER_HI, 0, 20) + +REG32(SYSTIMER_UNIT0_VALUE_LO, 0x0044) + FIELD(SYSTIMER_UNIT0_VALUE_LO, TIMER_LO, 0, 32) + +REG32(SYSTIMER_UNIT1_VALUE_HI, 0x0048) + FIELD(SYSTIMER_UNIT1_VALUE_HI, TIMER_HI, 0, 20) + +REG32(SYSTIMER_UNIT1_VALUE_LO, 0x004C) + FIELD(SYSTIMER_UNIT1_VALUE_LO, TIMER_LO, 0, 32) + +REG32(SYSTIMER_COMP0_LOAD, 0x0050) + FIELD(SYSTIMER_COMP0_LOAD, LOAD, 0, 1) + +REG32(SYSTIMER_COMP1_LOAD, 0x0054) + FIELD(SYSTIMER_COMP1_LOAD, LOAD, 0, 1) + +REG32(SYSTIMER_COMP2_LOAD, 0x0058) + FIELD(SYSTIMER_COMP2_LOAD, LOAD, 0, 1) + +REG32(SYSTIMER_UNIT0_LOAD, 0x005C) + FIELD(SYSTIMER_UNIT0_LOAD, LOAD, 0, 1) + +REG32(SYSTIMER_UNIT1_LOAD, 0x0060) + FIELD(SYSTIMER_UNIT1_LOAD, LOAD, 0, 1) + +REG32(SYSTIMER_INT_ENA, 0x0064) + FIELD(SYSTIMER_INT_ENA, TARGET2, 2, 1) + FIELD(SYSTIMER_INT_ENA, TARGET1, 1, 1) + FIELD(SYSTIMER_INT_ENA, TARGET0, 0, 1) + +REG32(SYSTIMER_INT_RAW, 0x0068) + FIELD(SYSTIMER_INT_RAW, TARGET2, 2, 1) + FIELD(SYSTIMER_INT_RAW, TARGET1, 1, 1) + FIELD(SYSTIMER_INT_RAW, TARGET0, 0, 1) + +REG32(SYSTIMER_INT_CLR, 0x006c) + FIELD(SYSTIMER_INT_CLR, TARGET2, 2, 1) + FIELD(SYSTIMER_INT_CLR, TARGET1, 1, 1) + FIELD(SYSTIMER_INT_CLR, TARGET0, 0, 1) + +REG32(SYSTIMER_INT_ST, 0x0070) + FIELD(SYSTIMER_INT_ST, TARGET2, 2, 1) + FIELD(SYSTIMER_INT_ST, TARGET1, 1, 1) + FIELD(SYSTIMER_INT_ST, TARGET0, 0, 1) + +REG32(SYSTIMER_DATE, 0x00fc) + FIELD(SYSTIMER_DATE, DATE, 0, 28) From 127b8e4d5ef4c59effa76b7156dc4434437ba042 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:40:29 +0800 Subject: [PATCH 34/56] hw/ssi: implement ESP32-C3 SPI1 (SPI flash) --- hw/ssi/esp32c3_spi.c | 224 ++++++++++++++++++++++++++++++ hw/ssi/meson.build | 1 + include/hw/ssi/esp32c3_spi.h | 259 +++++++++++++++++++++++++++++++++++ 3 files changed, 484 insertions(+) create mode 100644 hw/ssi/esp32c3_spi.c create mode 100644 include/hw/ssi/esp32c3_spi.h diff --git a/hw/ssi/esp32c3_spi.c b/hw/ssi/esp32c3_spi.c new file mode 100644 index 000000000000..8acda425bb31 --- /dev/null +++ b/hw/ssi/esp32c3_spi.c @@ -0,0 +1,224 @@ +/* + * ESP32 SPI controller + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "sysemu/sysemu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/ssi/ssi.h" +#include "hw/ssi/esp32c3_spi.h" + +#define SPI1_DEBUG 0 +#define SPI1_WARNING 0 + +#define ESP32C3_SPI_FLASH_ID 0xc84016 + +static uint64_t esp32c3_spi_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3SpiState *s = ESP32C3_SPI(opaque); + + uint64_t r = 0; + switch (addr) { + case A_SPI_MEM_CMD: + r = 0; + break; + case A_SPI_MEM_ADDR: + r = s->mem_addr; + break; + case A_SPI_MEM_CTRL: + r = s->mem_ctrl; + break; + case A_SPI_MEM_USER: + r = s->mem_user; + break; + case A_SPI_MEM_W0...A_SPI_MEM_W15: + r = s->data_reg[(addr - A_SPI_MEM_W0) / sizeof(uint32_t)]; + break; + default: +#if SPI1_WARNING + warn_report("[SPI1] Unsupported read to 0x%lx\n", addr); +#endif + break; + } + +#if SPI1_DEBUG + info_report("[SPI1] Reading 0x%lx (0x%lx)\n", addr, r); +#endif + + return r; +} + + +static void esp32c3_spi_txrx_buffer(ESP32C3SpiState *s, + const void *tx, int tx_bytes, + void *rx, int rx_bytes) +{ + int bytes = MAX(tx_bytes, rx_bytes); + for (int i = 0; i < bytes; ++i) { + uint8_t byte = 0; + if (byte < tx_bytes) { + memcpy(&byte, tx + i, 1); + } + uint32_t res = ssi_transfer(s->spi, byte); + if (byte < rx_bytes) { + memcpy(rx + i, &res, 1); + } + } +} + + +static void esp32c3_spi_begin_transaction(ESP32C3SpiState *s) +{ + /* Check if we are in the command state */ + if (s->mem_user & R_SPI_MEM_USER_USR_COMMAND_MASK) { + /* Get the number of bytes to read from the device */ + uint32_t miso_len = FIELD_EX32(s->mem_miso_len, SPI_MEM_MISO_DLEN, USR_MISO_DBITLEN); + miso_len = (miso_len + 1) / 8; + /* and the number of bytes to write to the device */ + uint32_t mosi_len = FIELD_EX32(s->mem_mosi_len, SPI_MEM_MOSI_DLEN, USR_MOSI_DBITLEN); + mosi_len = (mosi_len + 1) / 8; + + /* Get the command and its length, in bytes */ + uint32_t command = FIELD_EX32(s->mem_user2, SPI_MEM_USER2, USR_COMMAND_VALUE); + uint32_t commands_len = FIELD_EX32(s->mem_user2, SPI_MEM_USER2, USR_COMMAND_BITLEN); + commands_len = (commands_len + 1) / 8; + + /* Get the address and its length, in bytes */ + uint32_t address = FIELD_EX32(s->mem_addr, SPI_MEM_ADDR, USR_ADDR_VALUE); + uint32_t address_len = FIELD_EX32(s->mem_user1, SPI_MEM_USER1, USR_ADDR_BITLEN); + address_len = (address_len + 1) / 8; + + qemu_set_irq(s->cs_gpio[0], 0); + esp32c3_spi_txrx_buffer(s, &command, commands_len, NULL, 0); + esp32c3_spi_txrx_buffer(s, &address, address_len, NULL, 0); + esp32c3_spi_txrx_buffer(s, s->data_reg, mosi_len, s->data_reg, miso_len); + qemu_set_irq(s->cs_gpio[0], 1); + } +} + + +static void esp32c3_spi_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3SpiState *s = ESP32C3_SPI(opaque); + uint32_t wvalue = (uint32_t) value; + + switch (addr) { + case A_SPI_MEM_CMD: + if (wvalue & R_SPI_MEM_CMD_FLASH_RDID_MASK) { + s->data_reg[0] = ESP32C3_SPI_FLASH_ID; + } else if(wvalue & R_SPI_MEM_CMD_USR_MASK) { + esp32c3_spi_begin_transaction(s); + } + break; + case A_SPI_MEM_ADDR: + s->mem_addr = wvalue; + break; + case A_SPI_MEM_CTRL: + s->mem_ctrl = wvalue; + break; + case A_SPI_MEM_USER: + s->mem_user = wvalue; + break; + case A_SPI_MEM_USER1: + s->mem_user1 = wvalue; + break; + case A_SPI_MEM_USER2: + s->mem_user2 = wvalue; + break; + case A_SPI_MEM_MISO_DLEN: + s->mem_miso_len = wvalue; + break; + case A_SPI_MEM_MOSI_DLEN: + s->mem_mosi_len = wvalue; + break; + case A_SPI_MEM_W0...A_SPI_MEM_W15: + s->data_reg[(addr - A_SPI_MEM_W0) / sizeof(uint32_t)] = wvalue; + break; + default: +#if SPI1_WARNING + warn_report("[SPI1] Unsupported write to 0x%lx (%08lx)\n", addr, value); +#endif + break; + } + +#if SPI1_DEBUG + info_report("[SPI1] Writing 0x%lx = %08lx\n", addr, value); +#endif +} + +/* Convert one of the hardware "bitlen" registers to a byte count */ +static inline int bitlen_to_bytes(uint32_t val) +{ + return (val + 1 + 7) / 8; /* bitlen registers hold number of bits, minus one */ +} + +static const MemoryRegionOps esp32c3_spi_ops = { + .read = esp32c3_spi_read, + .write = esp32c3_spi_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32c3_spi_reset(DeviceState *dev) +{ + ESP32C3SpiState *s = ESP32C3_SPI(dev); + memset(s->data_reg, 0, ESP32C3_SPI_BUF_WORDS * sizeof(uint32_t)); +} + +static void esp32c3_spi_realize(DeviceState *dev, Error **errp) +{ +} + +static void esp32c3_spi_init(Object *obj) +{ + ESP32C3SpiState *s = ESP32C3_SPI(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_spi_ops, s, + TYPE_ESP32C3_SPI, ESP32C3_SPI_IO_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + // sysbus_init_irq(sbd, &s->irq); + + s->spi = ssi_create_bus(DEVICE(s), "spi"); + qdev_init_gpio_out_named(DEVICE(s), &s->cs_gpio[0], SSI_GPIO_CS, ESP32C3_SPI_CS_COUNT); +} + +static Property esp32c3_spi_properties[] = { + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32c3_spi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_spi_reset; + dc->realize = esp32c3_spi_realize; + device_class_set_props(dc, esp32c3_spi_properties); +} + +static const TypeInfo esp32c3_spi_info = { + .name = TYPE_ESP32C3_SPI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3SpiState), + .instance_init = esp32c3_spi_init, + .class_init = esp32c3_spi_class_init +}; + +static void esp32c3_spi_register_types(void) +{ + type_register_static(&esp32c3_spi_info); +} + +type_init(esp32c3_spi_register_types) diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build index ed3dcb26cbd9..1428694ec1ae 100644 --- a/hw/ssi/meson.build +++ b/hw/ssi/meson.build @@ -11,4 +11,5 @@ softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-ospi.c')) softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('imx_spi.c')) softmmu_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_spi.c')) softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_spi.c')) +softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_spi.c')) softmmu_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_spi_host.c')) diff --git a/include/hw/ssi/esp32c3_spi.h b/include/hw/ssi/esp32c3_spi.h new file mode 100644 index 000000000000..53eb907e2f1e --- /dev/null +++ b/include/hw/ssi/esp32c3_spi.h @@ -0,0 +1,259 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/ssi/ssi.h" + +#define TYPE_ESP32C3_SPI "ssi.esp32c3.spi" +#define ESP32C3_SPI(obj) OBJECT_CHECK(ESP32C3SpiState, (obj), TYPE_ESP32C3_SPI) + +/** + * Size of the Timegroup I/O registers area + */ +#define ESP32C3_SPI_IO_SIZE (A_SPI_MEM_DATE + 4) + + +#define ESP32C3_SPI_BUF_WORDS 16 + +#define ESP32C3_SPI_CS_COUNT 3 + +typedef struct ESP32C3SpiState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + SSIBus *spi; + qemu_irq cs_gpio[ESP32C3_SPI_CS_COUNT]; + + uint32_t mem_cmd; + uint32_t mem_addr; + uint32_t mem_ctrl; + uint32_t mem_user; + uint32_t mem_user1; + uint32_t mem_user2; + uint32_t mem_miso_len; + uint32_t mem_mosi_len; + uint32_t data_reg[ESP32C3_SPI_BUF_WORDS]; +} ESP32C3SpiState; + + +REG32(SPI_MEM_CMD, 0x000) + FIELD(SPI_MEM_CMD, FLASH_READ, 31, 1) + FIELD(SPI_MEM_CMD, FLASH_WREN, 30, 1) + FIELD(SPI_MEM_CMD, FLASH_WRDI, 29, 1) + FIELD(SPI_MEM_CMD, FLASH_RDID, 28, 1) + FIELD(SPI_MEM_CMD, FLASH_RDSR, 27, 1) + FIELD(SPI_MEM_CMD, FLASH_WRSR, 26, 1) + FIELD(SPI_MEM_CMD, FLASH_PP, 25, 1) + FIELD(SPI_MEM_CMD, FLASH_SE, 24, 1) + FIELD(SPI_MEM_CMD, FLASH_BE, 23, 1) + FIELD(SPI_MEM_CMD, FLASH_CE, 22, 1) + FIELD(SPI_MEM_CMD, FLASH_DP, 21, 1) + FIELD(SPI_MEM_CMD, FLASH_RES, 20, 1) + FIELD(SPI_MEM_CMD, FLASH_HPM, 19, 1) + FIELD(SPI_MEM_CMD, USR, 18, 1) + FIELD(SPI_MEM_CMD, FLASH_PE, 17, 1) + FIELD(SPI_MEM_CMD, MSPI_ST, 4, 4) + FIELD(SPI_MEM_CMD, SPI1_MST_ST, 0, 4) + +REG32(SPI_MEM_ADDR, 0x004) + FIELD(SPI_MEM_ADDR, USR_ADDR_VALUE, 0, 32) + +REG32(SPI_MEM_CTRL, 0x008) + FIELD(SPI_MEM_CTRL, FREAD_QIO, 24, 1) + FIELD(SPI_MEM_CTRL, FREAD_DIO, 23, 1) + FIELD(SPI_MEM_CTRL, WRSR_2B, 22, 1) + FIELD(SPI_MEM_CTRL, WP_REG, 21, 1) + FIELD(SPI_MEM_CTRL, FREAD_QUAD, 20, 1) + FIELD(SPI_MEM_CTRL, D_POL, 19, 1) + FIELD(SPI_MEM_CTRL, Q_POL, 18, 1) + FIELD(SPI_MEM_CTRL, RESANDRES, 15, 1) + FIELD(SPI_MEM_CTRL, FREAD_DUAL, 14, 1) + FIELD(SPI_MEM_CTRL, FASTRD_MODE, 13, 1) + FIELD(SPI_MEM_CTRL, TX_CRC_EN, 11, 1) + FIELD(SPI_MEM_CTRL, FCS_CRC_EN, 10, 1) + FIELD(SPI_MEM_CTRL, FCMD_QUAD, 8, 1) + FIELD(SPI_MEM_CTRL, FCMD_DUAL, 7, 1) + FIELD(SPI_MEM_CTRL, FDUMMY_OUT, 3, 1) + +REG32(SPI_MEM_CTRL1, 0x00C) + FIELD(SPI_MEM_CTRL1, CS_HOLD_DLY_RES, 2, 10) + FIELD(SPI_MEM_CTRL1, CLK_MODE, 0, 2) + +REG32(SPI_MEM_CTRL2, 0x010) + FIELD(SPI_MEM_CTRL2, SYNC_RESET, 31, 1) + +REG32(SPI_MEM_CLOCK, 0x014) + FIELD(SPI_MEM_CLOCK, CLK_EQU_SYSCLK, 31, 1) + FIELD(SPI_MEM_CLOCK, CLKCNT_N, 16, 8) + FIELD(SPI_MEM_CLOCK, CLKCNT_H, 8, 8) + FIELD(SPI_MEM_CLOCK, CLKCNT_L, 0, 8) + +REG32(SPI_MEM_USER, 0x018) + FIELD(SPI_MEM_USER, USR_COMMAND, 31, 1) + FIELD(SPI_MEM_USER, USR_ADDR, 30, 1) + FIELD(SPI_MEM_USER, USR_DUMMY, 29, 1) + FIELD(SPI_MEM_USER, USR_MISO, 28, 1) + FIELD(SPI_MEM_USER, USR_MOSI, 27, 1) + FIELD(SPI_MEM_USER, USR_DUMMY_IDLE, 26, 1) + FIELD(SPI_MEM_USER, USR_MOSI_HIGHPART, 25, 1) + FIELD(SPI_MEM_USER, USR_MISO_HIGHPART, 24, 1) + FIELD(SPI_MEM_USER, FWRITE_QIO, 15, 1) + FIELD(SPI_MEM_USER, FWRITE_DIO, 14, 1) + FIELD(SPI_MEM_USER, FWRITE_QUAD, 13, 1) + FIELD(SPI_MEM_USER, FWRITE_DUAL, 12, 1) + FIELD(SPI_MEM_USER, CK_OUT_EDGE, 9, 1) + +REG32(SPI_MEM_USER1, 0x01C) + FIELD(SPI_MEM_USER1, USR_ADDR_BITLEN, 26, 6) + FIELD(SPI_MEM_USER1, USR_DUMMY_CYCLELEN, 0, 6) + +REG32(SPI_MEM_USER2, 0x020) + FIELD(SPI_MEM_USER2, USR_COMMAND_BITLEN, 28, 4) + FIELD(SPI_MEM_USER2, USR_COMMAND_VALUE, 0, 16) + +REG32(SPI_MEM_MOSI_DLEN, 0x024) + FIELD(SPI_MEM_MOSI_DLEN, USR_MOSI_DBITLEN, 0, 10) + +REG32(SPI_MEM_MISO_DLEN, 0x028) + FIELD(SPI_MEM_MISO_DLEN, USR_MISO_DBITLEN, 0, 10) + +REG32(SPI_MEM_RD_STATUS, 0x02C) + FIELD(SPI_MEM_RD_STATUS, WB_MODE, 16, 8) + FIELD(SPI_MEM_RD_STATUS, STATUS, 0, 16) + +REG32(SPI_MEM_MISC, 0x034) + FIELD(SPI_MEM_MISC, CS_KEEP_ACTIVE, 10, 1) + FIELD(SPI_MEM_MISC, CK_IDLE_EDGE, 9, 1) + FIELD(SPI_MEM_MISC, CS1_DIS, 1, 1) + FIELD(SPI_MEM_MISC, CS0_DIS, 0, 1) + +REG32(SPI_MEM_TX_CRC, 0x038) + FIELD(SPI_MEM_TX_CRC, TX_CRC_DATA, 0, 32) + +REG32(SPI_MEM_CACHE_FCTRL, 0x03C) + FIELD(SPI_MEM_CACHE_FCTRL, FADDR_QUAD, 8, 1) + FIELD(SPI_MEM_CACHE_FCTRL, FDOUT_QUAD, 7, 1) + FIELD(SPI_MEM_CACHE_FCTRL, FDIN_QUAD , 6, 1) + FIELD(SPI_MEM_CACHE_FCTRL, FADDR_DUAL, 5, 1) + FIELD(SPI_MEM_CACHE_FCTRL, FDOUT_DUAL, 4, 1) + FIELD(SPI_MEM_CACHE_FCTRL, FDIN_DUAL , 3, 1) + FIELD(SPI_MEM_CACHE_FCTRL, CACHE_USR_ADDR_4BYTE, 1, 1) + +REG32(SPI_MEM_W0, 0x058) + FIELD(SPI_MEM_W0, BUF0, 0, 32) + +REG32(SPI_MEM_W1, 0x05C) + FIELD(SPI_MEM_W1, BUF1, 0, 32) + +REG32(SPI_MEM_W2, 0x060) + FIELD(SPI_MEM_W2, BUF2, 0, 32) + +REG32(SPI_MEM_W3, 0x064) + FIELD(SPI_MEM_W3, BUF3, 0, 32) + +REG32(SPI_MEM_W4, 0x068) + FIELD(SPI_MEM_W4, BUF4, 0, 32) + +REG32(SPI_MEM_W5, 0x06C) + FIELD(SPI_MEM_W5, BUF5, 0, 32) + +REG32(SPI_MEM_W6, 0x070) + FIELD(SPI_MEM_W6, BUF6, 0, 32) + +REG32(SPI_MEM_W7, 0x074) + FIELD(SPI_MEM_W7, BUF7, 0, 32) + +REG32(SPI_MEM_W8, 0x078) + FIELD(SPI_MEM_W8, BUF8, 0, 32) + +REG32(SPI_MEM_W9, 0x07C) + FIELD(SPI_MEM_W9, BUF9, 0, 32) + +REG32(SPI_MEM_W10, 0x080) + FIELD(SPI_MEM_W10, BUF10, 0, 32) + +REG32(SPI_MEM_W11, 0x084) + FIELD(SPI_MEM_W11, BUF11, 0, 32) + +REG32(SPI_MEM_W12, 0x088) + FIELD(SPI_MEM_W12, BUF12, 0, 32) + +REG32(SPI_MEM_W13, 0x08C) + FIELD(SPI_MEM_W13, BUF13, 0, 32) + +REG32(SPI_MEM_W14, 0x090) + FIELD(SPI_MEM_W14, BUF14, 0, 32) + +REG32(SPI_MEM_W15, 0x094) + FIELD(SPI_MEM_W15, BUF15, 0, 32) + +REG32(SPI_MEM_FLASH_WAITI_CTRL, 0x098) + FIELD(SPI_MEM_FLASH_WAITI_CTRL, WAITI_DUMMY_CYCLELEN, 10, 6) + FIELD(SPI_MEM_FLASH_WAITI_CTRL, WAITI_CMD, 2, 8) + FIELD(SPI_MEM_FLASH_WAITI_CTRL, WAITI_DUMMY, 1, 1) + +REG32(SPI_MEM_FLASH_SUS_CTRL, 0x09C) + FIELD(SPI_MEM_FLASH_SUS_CTRL, SUS_TIMEOUT_CNT, 25, 7) + FIELD(SPI_MEM_FLASH_SUS_CTRL, PES_END_EN, 24, 1) + FIELD(SPI_MEM_FLASH_SUS_CTRL, PER_END_EN, 23, 1) + FIELD(SPI_MEM_FLASH_SUS_CTRL, SPI_FMEM_RD_SUS_2B, 22, 1) + FIELD(SPI_MEM_FLASH_SUS_CTRL, PESR_END_MSK, 6, 16) + FIELD(SPI_MEM_FLASH_SUS_CTRL, FLASH_PES_EN, 5, 1) + FIELD(SPI_MEM_FLASH_SUS_CTRL, PES_PER_EN, 4, 1) + FIELD(SPI_MEM_FLASH_SUS_CTRL, FLASH_PES_WAIT_EN, 3, 1) + FIELD(SPI_MEM_FLASH_SUS_CTRL, FLASH_PER_WAIT_EN, 2, 1) + FIELD(SPI_MEM_FLASH_SUS_CTRL, FLASH_PES, 1, 1) + FIELD(SPI_MEM_FLASH_SUS_CTRL, FLASH_PER, 0, 1) + +REG32(SPI_MEM_FLASH_SUS_CMD, 0x0A0) + FIELD(SPI_MEM_FLASH_SUS_CMD, WAIT_PESR_COMMAND, 16, 16) + FIELD(SPI_MEM_FLASH_SUS_CMD, FLASH_PES_COMMAND, 8, 8) + FIELD(SPI_MEM_FLASH_SUS_CMD, FLASH_PER_COMMAND, 0, 8) + +REG32(SPI_MEM_SUS_STATUS, 0x0A4) + FIELD(SPI_MEM_SUS_STATUS, SPI0_LOCK_EN, 7, 1) + FIELD(SPI_MEM_SUS_STATUS, FLASH_PES_DLY_128, 6, 1) + FIELD(SPI_MEM_SUS_STATUS, FLASH_PER_DLY_128, 5, 1) + FIELD(SPI_MEM_SUS_STATUS, FLASH_DP_DLY_128, 4, 1) + FIELD(SPI_MEM_SUS_STATUS, FLASH_RES_DLY_128, 3, 1) + FIELD(SPI_MEM_SUS_STATUS, FLASH_HPM_DLY_128, 2, 1) + FIELD(SPI_MEM_SUS_STATUS, WAIT_PESR_CMD_2B, 1, 1) + FIELD(SPI_MEM_SUS_STATUS, FLASH_SUS, 0, 1) + +REG32(SPI_MEM_TIMING_CALI, 0x0A8) + FIELD(SPI_MEM_TIMING_CALI, EXTRA_DUMMY_CYCLELEN, 2, 3) + FIELD(SPI_MEM_TIMING_CALI, TIMING_CALI, 1, 1) + +REG32(SPI_MEM_INT_ENA, 0x0C0) + FIELD(SPI_MEM_INT_ENA, MST_ST_END_INT_ENA, 4, 1) + FIELD(SPI_MEM_INT_ENA, SLV_ST_END_INT_ENA, 3, 1) + FIELD(SPI_MEM_INT_ENA, WPE_END_INT_ENA, 2, 1) + FIELD(SPI_MEM_INT_ENA, PES_END_INT_ENA, 1, 1) + FIELD(SPI_MEM_INT_ENA, PER_END_INT_ENA, 0, 1) + +REG32(SPI_MEM_INT_CLR, 0x0C4) + FIELD(SPI_MEM_INT_CLR, MST_ST_END_INT_CLR, 4, 1) + FIELD(SPI_MEM_INT_CLR, SLV_ST_END_INT_CLR, 3, 1) + FIELD(SPI_MEM_INT_CLR, WPE_END_INT_CLR, 2, 1) + FIELD(SPI_MEM_INT_CLR, PES_END_INT_CLR, 1, 1) + FIELD(SPI_MEM_INT_CLR, PER_END_INT_CLR, 0, 1) + +REG32(SPI_MEM_INT_RAW, 0x0C8) + FIELD(SPI_MEM_INT_RAW, MST_ST_END_INT_RAW, 4, 1) + FIELD(SPI_MEM_INT_RAW, SLV_ST_END_INT_RAW, 3, 1) + FIELD(SPI_MEM_INT_RAW, WPE_END_INT_RAW, 2, 1) + FIELD(SPI_MEM_INT_RAW, PES_END_INT_RAW, 1, 1) + FIELD(SPI_MEM_INT_RAW, PER_END_INT_RAW, 0, 1) + +REG32(SPI_MEM_INT_ST, 0x0CC) + FIELD(SPI_MEM_INT_ST, MST_ST_END_INT_ST, 4, 1) + FIELD(SPI_MEM_INT_ST, SLV_ST_END_INT_ST, 3, 1) + FIELD(SPI_MEM_INT_ST, WPE_END_INT_ST, 2, 1) + FIELD(SPI_MEM_INT_ST, PES_END_INT_ST, 1, 1) + FIELD(SPI_MEM_INT_ST, PER_END_INT_ST, 0, 1) + +REG32(SPI_MEM_CLOCK_GATE, 0x0DC) + FIELD(SPI_MEM_CLOCK_GATE, CLK_EN, 0, 1) + +REG32(SPI_MEM_DATE, 0x3FC) + FIELD(SPI_MEM_DATE, DATE, 0, 28) From 89dea91d8a7b369053efcc8be0d16d2d7ff76f9c Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:43:30 +0800 Subject: [PATCH 35/56] hw/riscv: implement ESP32-C3 clock and system registers --- hw/riscv/esp32c3_clk.c | 159 ++++++++++++++++++ hw/riscv/meson.build | 1 + include/hw/riscv/esp32c3_clk.h | 295 +++++++++++++++++++++++++++++++++ 3 files changed, 455 insertions(+) create mode 100644 hw/riscv/esp32c3_clk.c create mode 100644 include/hw/riscv/esp32c3_clk.h diff --git a/hw/riscv/esp32c3_clk.c b/hw/riscv/esp32c3_clk.c new file mode 100644 index 000000000000..25e51f941e60 --- /dev/null +++ b/hw/riscv/esp32c3_clk.c @@ -0,0 +1,159 @@ +/* + * ESP32-C3 CPU Clock and Reset emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/riscv/esp32c3_clk.h" + +#define CLOCK_DEBUG 0 +#define CLOCK_WARNING 0 + +static uint32_t esp32c3_read_cpu_intr(ESP32C3ClockState *s, uint32_t index) +{ + return (s->levels >> index) & 1; +} + + +static void esp32c3_write_cpu_intr(ESP32C3ClockState *s, uint32_t index, uint32_t value) +{ + const uint32_t field = FIELD_EX32(value, SYSTEM_CPU_INTR_FROM_CPU_0, CPU_INTR_FROM_CPU_0); + if (field) { + s->levels |= BIT(index); + qemu_set_irq(s->irqs[index], 1); + } else { + s->levels &= ~BIT(index); + qemu_set_irq(s->irqs[index], 0); + } +} + + +static uint64_t esp32c3_clock_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3ClockState *s = ESP32C3_CLOCK(opaque); + uint64_t r = 0; + + switch(addr) { + case A_SYSTEM_CPU_PER_CONF: + r = s->cpuperconf; + break; + case A_SYSTEM_SYSCLK_CONF: + r = s->sysclk; + break; + case A_SYSTEM_CPU_INTR_FROM_CPU_0: + case A_SYSTEM_CPU_INTR_FROM_CPU_1: + case A_SYSTEM_CPU_INTR_FROM_CPU_2: + case A_SYSTEM_CPU_INTR_FROM_CPU_3: + r = esp32c3_read_cpu_intr(s, (addr - A_SYSTEM_CPU_INTR_FROM_CPU_0) / sizeof(uint32_t)); + break; + default: +#if CLOCK_WARNING + warn_report("[CLOCK] Unsupported read from %08lx\n", addr); +#endif + break; + } + return r; +} + +static void esp32c3_clock_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) +{ + ESP32C3ClockState *s = ESP32C3_CLOCK(opaque); + + switch(addr) { + case A_SYSTEM_CPU_INTR_FROM_CPU_0: + case A_SYSTEM_CPU_INTR_FROM_CPU_1: + case A_SYSTEM_CPU_INTR_FROM_CPU_2: + case A_SYSTEM_CPU_INTR_FROM_CPU_3: + esp32c3_write_cpu_intr(s, (addr - A_SYSTEM_CPU_INTR_FROM_CPU_0) / sizeof(uint32_t), value); + break; + default: +#if CLOCK_WARNING + warn_report("[CLOCK] Unsupported write to %08lx (%08lx)\n", addr, value); +#endif + break; + } +} + +static const MemoryRegionOps esp32c3_clock_ops = { + .read = esp32c3_clock_read, + .write = esp32c3_clock_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32c3_clock_reset(DeviceState *dev) +{ + ESP32C3ClockState *s = ESP32C3_CLOCK(dev); + /* On board reset, set the proper clocks and dividers */ + s->sysclk = ( 1 << R_SYSTEM_SYSCLK_CONF_PRE_DIV_CNT_SHIFT) | + (ESP32C3_CLK_SEL_PLL << R_SYSTEM_SYSCLK_CONF_SOC_CLK_SEL_SHIFT) | + (40 << R_SYSTEM_SYSCLK_CONF_CLK_XTAL_FREQ_SHIFT) | + ( 1 << R_SYSTEM_SYSCLK_CONF_CLK_DIV_EN_SHIFT); + + /* Divider for PLL clock and APB frequency */ + s->cpuperconf = (ESP32C3_PERIOD_SEL_80 << R_SYSTEM_CPU_PER_CONF_CPUPERIOD_SEL_SHIFT) | + (ESP32C3_FREQ_SEL_PLL_480 << R_SYSTEM_CPU_PER_CONF_PLL_FREQ_SEL_SHIFT); + + /* Initialize the IRQs */ + s->levels = 0; + for (int i = 0 ; i < ESP32C3_SYSTEM_CPU_INTR_COUNT; i++) { + qemu_irq_lower(s->irqs[i]); + } +} + +static void esp32c3_clock_realize(DeviceState *dev, Error **errp) +{ + /* Initialize the registers */ + esp32c3_clock_reset(dev); +} + +static void esp32c3_clock_init(Object *obj) +{ + ESP32C3ClockState *s = ESP32C3_CLOCK(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_clock_ops, s, + TYPE_ESP32C3_CLOCK, A_SYSTEM_COMB_PVT_ERR_HVT_SITE3 + sizeof(uint32_t)); + sysbus_init_mmio(sbd, &s->iomem); + + /* Initialize the output IRQ lines used to manually trigger interrupts */ + for (uint64_t i = 0; i < ESP32C3_SYSTEM_CPU_INTR_COUNT; i++) { + sysbus_init_irq(sbd, &s->irqs[i]); + } +} + +static void esp32c3_clock_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_clock_reset; + dc->realize = esp32c3_clock_realize; +} + +static const TypeInfo esp32c3_cache_info = { + .name = TYPE_ESP32C3_CLOCK, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3ClockState), + .instance_init = esp32c3_clock_init, + .class_init = esp32c3_clock_class_init +}; + +static void esp32c3_cache_register_types(void) +{ + type_register_static(&esp32c3_cache_info); +} + +type_init(esp32c3_cache_register_types) diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 2f7ee81be3ca..5be783968fda 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -10,5 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c')) riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) +riscv_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_clk.c')) hw_arch += {'riscv': riscv_ss} diff --git a/include/hw/riscv/esp32c3_clk.h b/include/hw/riscv/esp32c3_clk.h new file mode 100644 index 000000000000..8a8d5bea7e8d --- /dev/null +++ b/include/hw/riscv/esp32c3_clk.h @@ -0,0 +1,295 @@ +/* + * ESP32-C3 CPU Clock and Reset + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32c3_reg.h" + +#define TYPE_ESP32C3_CLOCK "esp32c3.soc.clk" +#define ESP32C3_CLOCK(obj) OBJECT_CHECK(ESP32C3ClockState, (obj), TYPE_ESP32C3_CLOCK) + + +#define ESP32C3_SYSTEM_CPU_INTR_COUNT 4 + +/** + * Value for SYSTEM_SOC_CLK_SEL + */ +#define ESP32C3_CLK_SEL_XTAL 0 +#define ESP32C3_CLK_SEL_PLL 1 +#define ESP32C3_CLK_SEL_RCFAST 2 + +/** + * Values for SYSTEM_PLL_FREQ_SEL + */ +#define ESP32C3_FREQ_SEL_PLL_480 0 +#define ESP32C3_FREQ_SEL_PLL_320 1 + +/** + * Values for SYSTEM_CPUPERIOD_SEL +*/ +#define ESP32C3_PERIOD_SEL_80 0 +#define ESP32C3_PERIOD_SEL_160 1 + + +typedef struct ESP32C3ClockState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + /* Registers for clocks configuration and frequency dividers */ + uint32_t cpuperconf; + uint32_t sysclk; + + + /* IRQs for crosscore interrupts */ + qemu_irq irqs[ESP32C3_SYSTEM_CPU_INTR_COUNT]; + + /* Bitmap that keeps the level of the IRQs */ + uint32_t levels; +} ESP32C3ClockState; + + +REG32(SYSTEM_CPU_PERI_CLK_EN, 0x000) + FIELD(SYSTEM_CPU_PERI_CLK_EN, CLK_EN_DEDICATED_GPIO, 7, 1) + FIELD(SYSTEM_CPU_PERI_CLK_EN, CLK_EN_ASSIST_DEBUG, 6, 1) + +REG32(SYSTEM_CPU_PERI_RST_EN, 0x004) + FIELD(SYSTEM_CPU_PERI_RST_EN, RST_EN_DEDICATED_GPIO, 7, 1) + FIELD(SYSTEM_CPU_PERI_RST_EN, RST_EN_ASSIST_DEBUG, 6, 1) + +REG32(SYSTEM_CPU_PER_CONF, 0x008) + FIELD(SYSTEM_CPU_PER_CONF, CPU_WAITI_DELAY_NUM, 4, 4) + FIELD(SYSTEM_CPU_PER_CONF, CPU_WAIT_MODE_FORCE_ON, 3, 1) + FIELD(SYSTEM_CPU_PER_CONF, PLL_FREQ_SEL, 2, 1) + FIELD(SYSTEM_CPU_PER_CONF, CPUPERIOD_SEL, 0, 2) + +REG32(SYSTEM_MEM_PD_MASK, 0x00C) + FIELD(SYSTEM_MEM_PD_MASK, LSLP_MEM_PD_MASK, 0, 1) + +REG32(SYSTEM_PERIP_CLK_EN0, 0x010) + FIELD(SYSTEM_PERIP_CLK_EN0, SPI4_CLK_EN, 31, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, ADC2_ARB_CLK_EN, 30, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, SYSTIMER_CLK_EN, 29, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, APB_SARADC_CLK_EN, 28, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, SPI3_DMA_CLK_EN, 27, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, PWM3_CLK_EN, 26, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, PWM2_CLK_EN, 25, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, UART_MEM_CLK_EN, 24, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, USB_DEVICE_CLK_EN, 23, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, SPI2_DMA_CLK_EN, 22, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, I2S1_CLK_EN, 21, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, PWM1_CLK_EN, 20, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, CAN_CLK_EN, 19, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, EXT1_CLK_EN, 18, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, PWM0_CLK_EN, 17, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, SPI3_CLK_EN, 16, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, TIMERGROUP1_CLK_EN, 15, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, EFUSE_CLK_EN, 14, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, TIMERGROUP_CLK_EN, 13, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, UHCI1_CLK_EN, 12, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, LEDC_CLK_EN, 11, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, PCNT_CLK_EN, 10, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, RMT_CLK_EN, 9, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, UHCI0_CLK_EN, 8, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, EXT0_CLK_EN, 7, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, SPI2_CLK_EN, 6, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, UART1_CLK_EN, 5, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, I2S0_CLK_EN, 4, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, WDG_CLK_EN, 3, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, UART_CLK_EN, 2, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, SPI01_CLK_EN, 1, 1) + FIELD(SYSTEM_PERIP_CLK_EN0, TIMERS_CLK_EN, 0, 1) + +REG32(SYSTEM_PERIP_CLK_EN1, 0x014) + FIELD(SYSTEM_PERIP_CLK_EN1, TSENS_CLK_EN, 10, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, UART2_CLK_EN, 9, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, LCD_CAM_CLK_EN, 8, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, SDIO_HOST_CLK_EN, 7, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, DMA_CLK_EN, 6, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, CRYPTO_HMAC_CLK_EN, 5, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, CRYPTO_DS_CLK_EN, 4, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, CRYPTO_RSA_CLK_EN, 3, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, CRYPTO_SHA_CLK_EN, 2, 1) + FIELD(SYSTEM_PERIP_CLK_EN1, CRYPTO_AES_CLK_EN, 1, 1) + +REG32(SYSTEM_PERIP_RST_EN0, 0x018) + FIELD(SYSTEM_PERIP_RST_EN0, SPI4_RST, 31, 1) + FIELD(SYSTEM_PERIP_RST_EN0, ADC2_ARB_RST, 30, 1) + FIELD(SYSTEM_PERIP_RST_EN0, SYSTIMER_RST, 29, 1) + FIELD(SYSTEM_PERIP_RST_EN0, APB_SARADC_RST, 28, 1) + FIELD(SYSTEM_PERIP_RST_EN0, SPI3_DMA_RST, 27, 1) + FIELD(SYSTEM_PERIP_RST_EN0, PWM3_RST, 26, 1) + FIELD(SYSTEM_PERIP_RST_EN0, PWM2_RST, 25, 1) + FIELD(SYSTEM_PERIP_RST_EN0, UART_MEM_RST, 24, 1) + FIELD(SYSTEM_PERIP_RST_EN0, USB_DEVICE_RST, 23, 1) + FIELD(SYSTEM_PERIP_RST_EN0, SPI2_DMA_RST, 22, 1) + FIELD(SYSTEM_PERIP_RST_EN0, I2S1_RST, 21, 1) + FIELD(SYSTEM_PERIP_RST_EN0, PWM1_RST, 20, 1) + FIELD(SYSTEM_PERIP_RST_EN0, CAN_RST, 19, 1) + FIELD(SYSTEM_PERIP_RST_EN0, EXT1_RST, 18, 1) + FIELD(SYSTEM_PERIP_RST_EN0, PWM0_RST, 17, 1) + FIELD(SYSTEM_PERIP_RST_EN0, SPI3_RST, 16, 1) + FIELD(SYSTEM_PERIP_RST_EN0, TIMERGROUP1_RST, 15, 1) + FIELD(SYSTEM_PERIP_RST_EN0, EFUSE_RST, 14, 1) + FIELD(SYSTEM_PERIP_RST_EN0, TIMERGROUP_RST, 13, 1) + FIELD(SYSTEM_PERIP_RST_EN0, UHCI1_RST, 12, 1) + FIELD(SYSTEM_PERIP_RST_EN0, LEDC_RST, 11, 1) + FIELD(SYSTEM_PERIP_RST_EN0, PCNT_RST, 10, 1) + FIELD(SYSTEM_PERIP_RST_EN0, RMT_RST, 9, 1) + FIELD(SYSTEM_PERIP_RST_EN0, UHCI0_RST, 8, 1) + FIELD(SYSTEM_PERIP_RST_EN0, EXT0_RST, 7, 1) + FIELD(SYSTEM_PERIP_RST_EN0, SPI2_RST, 6, 1) + FIELD(SYSTEM_PERIP_RST_EN0, UART1_RST, 5, 1) + FIELD(SYSTEM_PERIP_RST_EN0, I2S0_RST, 4, 1) + FIELD(SYSTEM_PERIP_RST_EN0, WDG_RST, 3, 1) + FIELD(SYSTEM_PERIP_RST_EN0, UART_RST, 2, 1) + FIELD(SYSTEM_PERIP_RST_EN0, SPI01_RST, 1, 1) + FIELD(SYSTEM_PERIP_RST_EN0, TIMERS_RST, 0, 1) + +REG32(SYSTEM_PERIP_RST_EN1, 0x01C) + FIELD(SYSTEM_PERIP_RST_EN1, TSENS_RST, 10, 1) + FIELD(SYSTEM_PERIP_RST_EN1, UART2_RST, 9, 1) + FIELD(SYSTEM_PERIP_RST_EN1, LCD_CAM_RST, 8, 1) + FIELD(SYSTEM_PERIP_RST_EN1, SDIO_HOST_RST, 7, 1) + FIELD(SYSTEM_PERIP_RST_EN1, DMA_RST, 6, 1) + FIELD(SYSTEM_PERIP_RST_EN1, CRYPTO_HMAC_RST, 5, 1) + FIELD(SYSTEM_PERIP_RST_EN1, CRYPTO_DS_RST, 4, 1) + FIELD(SYSTEM_PERIP_RST_EN1, CRYPTO_RSA_RST, 3, 1) + FIELD(SYSTEM_PERIP_RST_EN1, CRYPTO_SHA_RST, 2, 1) + FIELD(SYSTEM_PERIP_RST_EN1, CRYPTO_AES_RST, 1, 1) + +REG32(SYSTEM_BT_LPCK_DIV_INT, 0x020) + FIELD(SYSTEM_BT_LPCK_DIV_INT, BT_LPCK_DIV_NUM, 0, 12) + +REG32(SYSTEM_BT_LPCK_DIV_FRAC, 0x024) + FIELD(SYSTEM_BT_LPCK_DIV_FRAC, LPCLK_RTC_EN, 28, 1) + FIELD(SYSTEM_BT_LPCK_DIV_FRAC, LPCLK_SEL_XTAL32K, 27, 1) + FIELD(SYSTEM_BT_LPCK_DIV_FRAC, LPCLK_SEL_XTAL, 26, 1) + FIELD(SYSTEM_BT_LPCK_DIV_FRAC, LPCLK_SEL_8M, 25, 1) + FIELD(SYSTEM_BT_LPCK_DIV_FRAC, LPCLK_SEL_RTC_SLOW, 24, 1) + FIELD(SYSTEM_BT_LPCK_DIV_FRAC, BT_LPCK_DIV_A, 12, 12) + FIELD(SYSTEM_BT_LPCK_DIV_FRAC, BT_LPCK_DIV_B, 0, 12) + +REG32(SYSTEM_CPU_INTR_FROM_CPU_0, 0x028) + FIELD(SYSTEM_CPU_INTR_FROM_CPU_0, CPU_INTR_FROM_CPU_0, 0, 1) + +REG32(SYSTEM_CPU_INTR_FROM_CPU_1, 0x02C) + FIELD(SYSTEM_CPU_INTR_FROM_CPU_1, CPU_INTR_FROM_CPU_1, 0, 1) + +REG32(SYSTEM_CPU_INTR_FROM_CPU_2, 0x030) + FIELD(SYSTEM_CPU_INTR_FROM_CPU_2, CPU_INTR_FROM_CPU_2, 0, 1) + +REG32(SYSTEM_CPU_INTR_FROM_CPU_3, 0x034) + FIELD(SYSTEM_CPU_INTR_FROM_CPU_3, CPU_INTR_FROM_CPU_3, 0, 1) + +REG32(SYSTEM_RSA_PD_CTRL, 0x038) + FIELD(SYSTEM_RSA_PD_CTRL, RSA_MEM_FORCE_PD, 2, 1) + FIELD(SYSTEM_RSA_PD_CTRL, RSA_MEM_FORCE_PU, 1, 1) + FIELD(SYSTEM_RSA_PD_CTRL, RSA_MEM_PD, 0, 1) + +REG32(SYSTEM_EDMA_CTRL, 0x03C) + FIELD(SYSTEM_EDMA_CTRL, EDMA_RESET, 1, 1) + FIELD(SYSTEM_EDMA_CTRL, EDMA_CLK_ON, 0, 1) + +REG32(SYSTEM_CACHE_CONTROL, 0x040) + FIELD(SYSTEM_CACHE_CONTROL, DCACHE_RESET, 3, 1) + FIELD(SYSTEM_CACHE_CONTROL, DCACHE_CLK_ON, 2, 1) + FIELD(SYSTEM_CACHE_CONTROL, ICACHE_RESET, 1, 1) + FIELD(SYSTEM_CACHE_CONTROL, ICACHE_CLK_ON, 0, 1) + +REG32(SYSTEM_EXTERNAL_DEVICE_ENCRYPT_DECRYPT_CONTROL, 0x044) + FIELD(SYSTEM_EXTERNAL_DEVICE_ENCRYPT_DECRYPT_CONTROL, ENABLE_DOWNLOAD_MANUAL_ENCRYPT, 3, 1) + FIELD(SYSTEM_EXTERNAL_DEVICE_ENCRYPT_DECRYPT_CONTROL, ENABLE_DOWNLOAD_G0CB_DECRYPT, 2, 1) + FIELD(SYSTEM_EXTERNAL_DEVICE_ENCRYPT_DECRYPT_CONTROL, ENABLE_DOWNLOAD_DB_ENCRYPT, 1, 1) + FIELD(SYSTEM_EXTERNAL_DEVICE_ENCRYPT_DECRYPT_CONTROL, ENABLE_SPI_MANUAL_ENCRYPT, 0, 1) + +REG32(SYSTEM_RTC_FASTMEM_CONFIG, 0x048) + FIELD(SYSTEM_RTC_FASTMEM_CONFIG, RTC_MEM_CRC_FINISH, 31, 1) + FIELD(SYSTEM_RTC_FASTMEM_CONFIG, RTC_MEM_CRC_LEN, 20, 11) + FIELD(SYSTEM_RTC_FASTMEM_CONFIG, RTC_MEM_CRC_ADDR, 9, 11) + FIELD(SYSTEM_RTC_FASTMEM_CONFIG, RTC_MEM_CRC_START, 8, 1) + +REG32(SYSTEM_RTC_FASTMEM_CRC, 0x04C) + FIELD(SYSTEM_RTC_FASTMEM_CRC, RTC_MEM_CRC_RES, 0, 32) + +REG32(SYSTEM_REDUNDANT_ECO_CTRL, 0x050) + FIELD(SYSTEM_REDUNDANT_ECO_CTRL, REDUNDANT_ECO_RESULT, 1, 1) + FIELD(SYSTEM_REDUNDANT_ECO_CTRL, REDUNDANT_ECO_DRIVE, 0, 1) + +REG32(SYSTEM_CLOCK_GATE, 0x054) + FIELD(SYSTEM_CLOCK_GATE, CLK_EN, 0, 1) + +REG32(SYSTEM_SYSCLK_CONF, 0x058) + FIELD(SYSTEM_SYSCLK_CONF, CLK_DIV_EN, 19, 1) + FIELD(SYSTEM_SYSCLK_CONF, CLK_XTAL_FREQ, 12, 7) + FIELD(SYSTEM_SYSCLK_CONF, SOC_CLK_SEL, 10, 2) + FIELD(SYSTEM_SYSCLK_CONF, PRE_DIV_CNT, 0, 10) + +REG32(SYSTEM_MEM_PVT, 0x05C) + FIELD(SYSTEM_MEM_PVT, MEM_VT_SEL, 22, 2) + FIELD(SYSTEM_MEM_PVT, MEM_TIMING_ERR_CNT, 6, 16) + FIELD(SYSTEM_MEM_PVT, MEM_PVT_MONITOR_EN, 5, 1) + FIELD(SYSTEM_MEM_PVT, MEM_ERR_CNT_CLR, 4, 1) + FIELD(SYSTEM_MEM_PVT, MEM_PATH_LEN, 0, 4) + +REG32(SYSTEM_COMB_PVT_LVT_CONF, 0x060) + FIELD(SYSTEM_COMB_PVT_LVT_CONF, COMB_PVT_MONITOR_EN_LVT, 6, 1) + FIELD(SYSTEM_COMB_PVT_LVT_CONF, COMB_ERR_CNT_CLR_LVT, 5, 1) + FIELD(SYSTEM_COMB_PVT_LVT_CONF, COMB_PATH_LEN_LVT, 0, 5) + +REG32(SYSTEM_COMB_PVT_NVT_CONF, 0x064) + FIELD(SYSTEM_COMB_PVT_NVT_CONF, COMB_PVT_MONITOR_EN_NVT, 6, 1) + FIELD(SYSTEM_COMB_PVT_NVT_CONF, COMB_ERR_CNT_CLR_NVT, 5, 1) + FIELD(SYSTEM_COMB_PVT_NVT_CONF, COMB_PATH_LEN_NVT, 0, 5) + +REG32(SYSTEM_COMB_PVT_HVT_CONF, 0x068) + FIELD(SYSTEM_COMB_PVT_HVT_CONF, COMB_PVT_MONITOR_EN_HVT, 6, 1) + FIELD(SYSTEM_COMB_PVT_HVT_CONF, COMB_ERR_CNT_CLR_HVT, 5, 1) + FIELD(SYSTEM_COMB_PVT_HVT_CONF, COMB_PATH_LEN_HVT, 0, 5) + +REG32(SYSTEM_COMB_PVT_ERR_LVT_SITE0, 0x06C) + FIELD(SYSTEM_COMB_PVT_ERR_LVT_SITE0, COMB_TIMING_ERR_CNT_LVT_SITE0, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_NVT_SITE0, 0x070) + FIELD(SYSTEM_COMB_PVT_ERR_NVT_SITE0, COMB_TIMING_ERR_CNT_NVT_SITE0, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_HVT_SITE0, 0x074) + FIELD(SYSTEM_COMB_PVT_ERR_HVT_SITE0, COMB_TIMING_ERR_CNT_HVT_SITE0, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_LVT_SITE1, 0x078) + FIELD(SYSTEM_COMB_PVT_ERR_LVT_SITE1, COMB_TIMING_ERR_CNT_LVT_SITE1, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_NVT_SITE1, 0x07C) + FIELD(SYSTEM_COMB_PVT_ERR_NVT_SITE1, COMB_TIMING_ERR_CNT_NVT_SITE1, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_HVT_SITE1, 0x080) + FIELD(SYSTEM_COMB_PVT_ERR_HVT_SITE1, COMB_TIMING_ERR_CNT_HVT_SITE1, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_LVT_SITE2, 0x084) + FIELD(SYSTEM_COMB_PVT_ERR_LVT_SITE2, COMB_TIMING_ERR_CNT_LVT_SITE2, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_NVT_SITE2, 0x088) + FIELD(SYSTEM_COMB_PVT_ERR_NVT_SITE2, COMB_TIMING_ERR_CNT_NVT_SITE2, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_HVT_SITE2, 0x08C) + FIELD(SYSTEM_COMB_PVT_ERR_HVT_SITE2, COMB_TIMING_ERR_CNT_HVT_SITE2, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_LVT_SITE3, 0x090) + FIELD(SYSTEM_COMB_PVT_ERR_LVT_SITE3, COMB_TIMING_ERR_CNT_LVT_SITE3, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_NVT_SITE3, 0x094) + FIELD(SYSTEM_COMB_PVT_ERR_NVT_SITE3, COMB_TIMING_ERR_CNT_NVT_SITE3, 0, 16) + +REG32(SYSTEM_COMB_PVT_ERR_HVT_SITE3, 0x098) + FIELD(SYSTEM_COMB_PVT_ERR_HVT_SITE3, COMB_TIMING_ERR_CNT_HVT_SITE3, 0, 16) + +REG32(SYSTEM_SYSTEM_DATE, 0xFFC) + FIELD(SYSTEM_SYSTEM_DATE, SYSTEM_REG_DATE, 0, 28) From 791feae858a54afb7a75928184a5be343f7cd48e Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:44:53 +0800 Subject: [PATCH 36/56] hw/riscv: implement ESP32-C3 Interrupt Matrix All features are implemented, except level/edge trigger option. --- hw/riscv/esp32c3_intmatrix.c | 401 +++++++++++++++++++++++++++ hw/riscv/meson.build | 2 +- include/hw/riscv/esp32c3_intmatrix.h | 160 +++++++++++ 3 files changed, 562 insertions(+), 1 deletion(-) create mode 100644 hw/riscv/esp32c3_intmatrix.c create mode 100644 include/hw/riscv/esp32c3_intmatrix.h diff --git a/hw/riscv/esp32c3_intmatrix.c b/hw/riscv/esp32c3_intmatrix.c new file mode 100644 index 000000000000..58589268fb47 --- /dev/null +++ b/hw/riscv/esp32c3_intmatrix.c @@ -0,0 +1,401 @@ +/* + * ESP32-C3 Interrupt Matrix + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/queue.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/riscv/riscv_hart.h" +#include "hw/riscv/esp32c3_intmatrix.h" +#include "esp_cpu.h" + +#define INTMATRIX_DEBUG 0 +#define INTMATRIX_WARNING 0 + +#define BIT_SET(reg, bit) ((reg) & BIT(bit)) +#define CLEAR_BIT(reg, bit) do { (reg) &= ~BIT(bit); } while(0) +#define SET_BIT(reg, bit) do { (reg) |= BIT(bit); } while(0) + + +extern long esp32c3_get_real_int_cause(CPUState *cs); + + +/* Because the interrupts are asynchronous, there is a small chance that multiple interrupts + * are triggered at the same time, overlapping the first one. Use a FIFO structure to store + * all the events. This may not be required once the custom RISC-V core is implemented (which + * would serialize the incoming IRQs). */ +#define ESP32C3_IRQ_FIFO_LENGTH 8 + + +static void esp32c3_do_int(ESP32C3IntMatrixState *s, int line) +{ + qemu_irq_pulse(s->out_irqs[line]); +} + + +static int esp32c3_get_output_line_level(ESP32C3IntMatrixState *s, int line) +{ + int level_shared = 0; + + for (int i = 0; level_shared == 0 && i < ESP32C3_INT_MATRIX_INPUTS; i++) { + const uint_fast8_t mapped = s->irq_map[i]; + if (mapped == line && (s->irq_levels & BIT(i))) + { + level_shared |= 1; + } + } + + return level_shared; +} + +/** + * Try to clear the given interrupt from the pending bitmap. + * If the signal is shared with other interrupt sources, make sure all of them are low (0) + * before clearing the pending IRQ from the bitmap. + */ +static void esp32c3_intmatrix_clear_pending(ESP32C3IntMatrixState *s, int line) +{ + /* Check if another GPIO IRQ is sharing the same output line. They must all be low before + * clearing the pending bit. This is due to the fact that output lines + * can be shared on the ESP32-C3 */ + const int output_level = esp32c3_get_output_line_level(s, line); + if (!output_level) { + /* The output interrupt line is 0, so we can clear the pending flag */ + CLEAR_BIT(s->irq_pending, line); + } +} + + +/** + * Check if an interrupt can be triggered. + * This is the case if the interrupt matrix hasn't notified the CPU yet that an interrupt is incoming. + * Because interrupt handling is asynchronous in QEMU, if an interrupt occurs right now, MIE will not be set + * until the current TB (guest compiled block) terminates and CPU checks for the current interrupts. + * The problem is that, here, if another interrupt of a valid priority occurs before the current TB finished + * its execution (MIE still set), the interrupt will be accepted, put inside our IRQ FIFO and popped + * when the guest is still handling the previous interrupt which is not a valid state! + * As interrupts on the ESP32-C3 occur as soon as the interrupt line is raised, MIE is directly reset, forbidding + * any other interrupt to occur. The interrupt handler will raise the priority and re-enable it. + * Thus, make sure our FIFO is before triggering an interrupt, and ignore MIE flag which is meaningless. + */ +static bool esp32c3_intmatrix_can_trigger(ESP32C3IntMatrixState *s) +{ + return esp_cpu_accept_interrupts(s->cpu); +} + + +static void esp32c3_intmatrix_irq_handler(void *opaque, int n, int level) +{ + ESP32C3IntMatrixState *s = ESP32C3_INTMATRIX(opaque); + + /* Update the level mirror */ + assert(n <= ESP32C3_INT_MATRIX_INPUTS); + + if (level) { + SET_BIT(s->irq_levels, n); + } else { + CLEAR_BIT(s->irq_levels, n); + } + + const int line = s->irq_map[n]; + + /* If the line is not enable, don't do anything special, the level has been recorded already */ + if ((s->irq_enabled & BIT(line)) == 0) { + return; + } + + /* If the new level is high, check that the priority is equal or bigger than the threshold. + * If that's the case, we can execute the interrupt, else, mark it as pending. */ + if (level == 1) { +#if INTMATRIX_DEBUG + info_report("\x1b[31m[INTMATRIX] IRQ %d priority set to %d, CPU threshold %d \x1b[0m\n", + line, s->irq_prio[line], s->irq_thres); +#endif + + if (s->irq_prio[line] >= s->irq_thres && esp32c3_intmatrix_can_trigger(s)) { + esp32c3_do_int(s, line); + } else { + SET_BIT(s->irq_pending, line); + } + } else if (BIT_SET(s->irq_pending, line)) { + esp32c3_intmatrix_clear_pending(s, line); + } +} + + +static void esp32c3_intmatrix_irq_prio_changed(ESP32C3IntMatrixState* s, uint32_t line, uint8_t priority) +{ + const bool accept = esp32c3_intmatrix_can_trigger(s); + + if (accept && priority >= s->irq_thres && BIT_SET(s->irq_pending, line)) { + /* No need to clear the pending bit here. As soon as the interrupt source will be ACK by the + * software, its level will be update, as well as its pending state. */ + esp32c3_do_int(s, line); + } +} + + +static void esp32c3_intmatrix_core_prio_changed(ESP32C3IntMatrixState* s, uint64_t new_cpu_priority) +{ + uint64_t pending = s->irq_pending; + const bool accept = esp32c3_intmatrix_can_trigger(s); + + if (pending && accept) { + int64_t priority = -1; + uint_fast32_t line = 0; + + /* Clear all the interrupts that have a lower priority than the new CPU threshold */ + for (uint_fast32_t i = 1; i <= ESP32C3_CPU_INT_COUNT; i++) { + + const uint64_t line_prio = s->irq_prio[i]; + if (line_prio < new_cpu_priority) { + CLEAR_BIT(pending, i); + } + } + + /* No high level interrupt pending? */ + if (pending == 0) { + return; + } + + /* Look for the highest priority pending interrupt */ + for (uint_fast32_t i = 1; i <= ESP32C3_CPU_INT_COUNT; i++) { + const int64_t line_prio = (int64_t) s->irq_prio[i]; + if (BIT_SET(pending, i) && line_prio > priority) { + priority = line_prio; + line = i; + } + } + + /* Make sure a line was selected with its new priority */ + assert(line != 0); + assert(priority >= new_cpu_priority); + /* No need to clear the pending bit here. As soon as the interrupt source will be ACK by the + * software, its level will be update, as well as its pending state. */ + esp32c3_do_int(s, line); + } +} + + +/** + * This function is called when the status (enabled/disabled) of a line has just been changed. + * It will update the pending IRQ map. + */ +static void esp32c3_intmatrix_irq_status_changed(ESP32C3IntMatrixState* s, uint32_t line, int enabled) +{ + const bool accept = esp32c3_intmatrix_can_trigger(s); + + if (!enabled) { + + /* IRQ has just been disabled, if any interrupt is pending, clear it */ + CLEAR_BIT(s->irq_pending, line); + + } else if (esp32c3_get_output_line_level(s, line)) { + + /* IRQ has just been re-enabled, we have to check if any interrupt source is mapped to it, and + * if that's the case, check if their level is high, as we would need to potentially trigger an + * interrupt. */ + SET_BIT(s->irq_pending, line); + + if (accept) { + /* If the CPU can accept interrupt, trigger an interrupt now */ + esp32c3_do_int(s, line); + } + } +} + + +static uint64_t esp32c3_intmatrix_read(void* opaque, hwaddr addr, unsigned int size) +{ + ESP32C3IntMatrixState *s = ESP32C3_INTMATRIX(opaque); + const uint32_t index = addr / sizeof(uint32_t); + uint32_t r = 0; + + if (index <= 61) { + r = s->irq_map[index]; + } else if (index >= ESP32C3_INTMATRIX_IO_PRIO_START && index < ESP32C3_INTMATRIX_IO_PRIO_END) { + const uint32_t line = index - ESP32C3_INTMATRIX_IO_PRIO_START; + r = s->irq_prio[line]; + } else if (index == ESP32C3_INTMATRIX_IO_THRESH_REG) { + r = s->irq_thres; + } else if (index == ESP32C3_INTMATRIX_IO_ENABLE_REG) { + r = s->irq_enabled; + } else if (index == ESP32C3_INTMATRIX_IO_TYPE_REG) { + r = 0; + } else { +#if INTMATRIX_WARNING + /* Other registers are not supported yet */ + warn_report("[INTMATRIX] Unsupported read to %08lx\n", addr); +#endif + } + + return r; +} + +static void esp32c3_intmatrix_write(void* opaque, hwaddr addr, uint64_t value, unsigned int size) +{ + ESP32C3IntMatrixState *s = ESP32C3_INTMATRIX(opaque); + + const uint32_t index = addr / sizeof(uint32_t); + + if (index <= 61) { + + s->irq_map[index] = (value & 0x1f); +#if INTMATRIX_DEBUG + info_report("\x1b[31m[INTMATRIX] Mapping interrupt %d to CPU line %d\x1b[0m\n", index, s->irq_map[index]); +#endif + + } else if (index >= ESP32C3_INTMATRIX_IO_PRIO_START && index < ESP32C3_INTMATRIX_IO_PRIO_END) { + + const uint8_t priority = value & 0xf; + const uint32_t line = (index - ESP32C3_INTMATRIX_IO_PRIO_START) + 1; + s->irq_prio[line] = priority; +#if INTMATRIX_DEBUG + info_report("\x1b[31m[INTMATRIX] Priority of line %d set to %d\x1b[0m\n", line, priority); +#endif + /* Check if the new priority interrupts the CPU */ + esp32c3_intmatrix_irq_prio_changed(s, line, priority); + + } else if (index == ESP32C3_INTMATRIX_IO_THRESH_REG) { + + const uint8_t priority = value & 0xf; + + /** + * If the new priority is the same as the former one, nothing must be done. + * Else, this could result in an infinite loop. Let's say we have an interrupt source + * that is mapped to a CPU line, its threshold is 2, the CPU threshold is 3. + * When the interrupt source is asserted, no interrupt is triggered, because the line's + * priority is lower than the threshold but the its pending bit is set . + * As soon as the threshold is lowered to 2 or 1, the interrupt will be triggered because + * its pending bit is set. + * NOTE THAT THE PENDING BIT IS STILL SET BECAUSE THE SOURCE IS STILL ASSERTED! + * As such, if the CPU sets the threshold to the same value, the function + * `esp32c3_intmatrix_core_prio_changed` called below would re-schedule the same interrupt. + */ + if (priority != s->irq_thres) { + s->irq_thres = priority; +#if INTMATRIX_DEBUG + info_report("\x1b[31m[INTMATRIX] Setting CPU IRQ threshold to %d\x1b[0m\n", priority); +#endif + esp32c3_intmatrix_core_prio_changed(s, priority); + } + + } else if (index == ESP32C3_INTMATRIX_IO_ENABLE_REG) { + /* Check if any bit has changed status */ + uint64_t prev = s->irq_enabled; + s->irq_enabled = value; + /* Check which interrupt/bit changed + * Interrupts starts at 1, so we need to count up to ESP32C3_CPU_INT_COUNT */ + for (int i = 0; i <= ESP32C3_CPU_INT_COUNT; i++) { + const int new_st = value & BIT(i); + const int old_st = prev & BIT(i); + if (new_st != old_st) { + esp32c3_intmatrix_irq_status_changed(s, i, new_st ? 1 : 0); + } + } + } else if (index == ESP32C3_INTMATRIX_IO_TYPE_REG) { + if (value != 0) { +#if INTMATRIX_WARNING + warn_report("[INTMATRIX] Edge-triggered interrupts not supported\n"); +#endif + } + } else { +#if INTMATRIX_WARNING + /* Other registers are not supported yet */ + warn_report("[INTMATRIX] Unsupported write to %08lx (%08lx)\n", addr, value); +#endif + } +} + +static const MemoryRegionOps esp_intmatrix_ops = { + .read = esp32c3_intmatrix_read, + .write = esp32c3_intmatrix_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + + +static void esp32c3_intmatrix_reset(DeviceState *dev) +{ + ESP32C3IntMatrixState *s = ESP32C3_INTMATRIX(dev); + RISCVCPU *cpu = &s->cpu->parent_obj; + + memset(s->irq_map, 0, sizeof(s->irq_map)); + memset(s->irq_prio, 0, sizeof(s->irq_prio)); + s->irq_thres = 0; + s->irq_pending = 0; + s->irq_levels = 0; + s->irq_trigger = 0; + s->irq_enabled = 0; + for (int i = 0; i <= ESP32C3_CPU_INT_COUNT; i++) { + qemu_irq_lower(s->out_irqs[i]); + } + + /* Force the CPU to allow all interrupts */ + riscv_csr_write(&cpu->env, CSR_MIE, BIT(12) - 1); +} + + +static void esp32c3_intmatrix_realize(DeviceState *dev, Error **errp) +{ + esp32c3_intmatrix_reset(dev); +} + + +static void esp32c3_intmatrix_init(Object *obj) +{ + ESP32C3IntMatrixState *s = ESP32C3_INTMATRIX(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp_intmatrix_ops, s, + TYPE_ESP32C3_INTMATRIX, ESP32C3_INTMATRIX_IO_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + + qdev_init_gpio_in(DEVICE(s), esp32c3_intmatrix_irq_handler, ESP32C3_INT_MATRIX_INPUTS); + qdev_init_gpio_out_named(DEVICE(s), s->out_irqs, ESP32C3_INT_MATRIX_OUTPUT_NAME, ESP32C3_CPU_INT_COUNT + 1); +} + + +static Property esp32c3_intmatrix_properties[] = { + DEFINE_PROP_LINK("cpu", ESP32C3IntMatrixState, cpu, TYPE_ESP_RISCV_CPU, EspRISCVCPU*), + DEFINE_PROP_END_OF_LIST(), +}; + + +static void esp32c3_intmatrix_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_intmatrix_reset; + dc->realize = esp32c3_intmatrix_realize; + device_class_set_props(dc, esp32c3_intmatrix_properties); +} + + +static const TypeInfo esp32c3_intmatrix_info = { + .name = TYPE_ESP32C3_INTMATRIX, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3IntMatrixState), + .instance_init = esp32c3_intmatrix_init, + .class_init = esp32c3_intmatrix_class_init +}; + + +static void esp32c3_intmatrix_register_types(void) +{ + type_register_static(&esp32c3_intmatrix_info); +} + + +type_init(esp32c3_intmatrix_register_types) diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 5be783968fda..7b59b8b25ff7 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -10,6 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c')) riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) -riscv_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_clk.c')) +riscv_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_clk.c', 'esp32c3_intmatrix.c')) hw_arch += {'riscv': riscv_ss} diff --git a/include/hw/riscv/esp32c3_intmatrix.h b/include/hw/riscv/esp32c3_intmatrix.h new file mode 100644 index 000000000000..c822f8228be3 --- /dev/null +++ b/include/hw/riscv/esp32c3_intmatrix.h @@ -0,0 +1,160 @@ +/* + * ESP32-C3 Interrupt Matrix + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#pragma once + +#include "hw/riscv/riscv_hart.h" +#include "target/riscv/esp_cpu.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32c3_reg.h" + + +/** + * Number of inputs in the C3's Interrupt Matrix + */ +#define ESP32C3_INT_MATRIX_INPUTS 62 + +/** + * Name of the output lines of the Interrupt Matrix (that shall be connected to the CPU) + */ +#define ESP32C3_INT_MATRIX_OUTPUT_NAME "misc.esp32c3.intmatrix.out_irqs" + +/** + * Number of CPU peripheral interrupts on the C3. + * This can be considered the output of the interrupt matrix. + */ +#define ESP32C3_CPU_INT_COUNT (ESP_CPU_INT_LINES) + +#define TYPE_ESP32C3_INTMATRIX "misc.esp32c3.intmatrix" +#define ESP32C3_INTMATRIX(obj) OBJECT_CHECK(ESP32C3IntMatrixState, (obj), TYPE_ESP32C3_INTMATRIX) + +/** + * Size of the I/O region, in bytes, of the C3 Interrupt Matrix + */ +#define ESP32C3_INTMATRIX_IO_SIZE (0x800) + + +/** + * Index where priority registers start + */ +#define ESP32C3_INTMATRIX_IO_PRIO_START (0x118 / sizeof(uint32_t)) + +#define ESP32C3_INTMATRIX_IO_PRIO_END (0x190 / sizeof(uint32_t)) + +/** + * The following registers are not part of any "register table", contrarily + * to the priorities or mapping. + */ +#define ESP32C3_INTMATRIX_IO_ENABLE_REG (0x104 / sizeof(uint32_t)) + +#define ESP32C3_INTMATRIX_IO_TYPE_REG (0x108 / sizeof(uint32_t)) + +#define ESP32C3_INTMATRIX_IO_THRESH_REG (0x194 / sizeof(uint32_t)) + + +/* Bit value for the type of interrupt trigger */ +#define ESP322C3_INTMATRIX_TRIG_LEVEL 0 +#define ESP322C3_INTMATRIX_TRIG_EDGE 1 + +typedef struct ESP32C3IntMatrixState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + uint8_t irq_map[ESP32C3_INT_MATRIX_INPUTS]; + /* In the following fields, "interrupts" refer to the CPU lines (31) + * and not the peripheral source. */ + /* ESP32-C3 CPU has 31 interrupts numbered from 1 to 31 */ + uint8_t irq_prio[ESP32C3_CPU_INT_COUNT + 1]; + /* Current priority threshold of the CPU interrupts */ + uint8_t irq_thres; + /* Keep a bitmap of the pending interrupts */ + uint64_t irq_pending; + /* Bitmap that records the enabled/disabled interrupts */ + uint64_t irq_enabled; + /* Bitmap that records the type of trigger for interrupts */ + uint64_t irq_trigger; + + /* Fast mirror to access IRQ levels */ + uint64_t irq_levels; + EspRISCVCPU *cpu; + + /* Output IRQ used to notify the CPU, indexed from 1 to 31, so allocate one more */ + qemu_irq out_irqs[ESP32C3_CPU_INT_COUNT + 1]; +} ESP32C3IntMatrixState; + +_Static_assert(sizeof(uint64_t) * 8 >= ESP32C3_INT_MATRIX_INPUTS, + "A single 64-bit value must be able to represent a bitmap of all the interrupt sources"); + +typedef enum { + ETS_WIFI_MAC_INTR_SOURCE = 0, /**< interrupt of WiFi MAC, level*/ + ETS_WIFI_MAC_NMI_SOURCE, /**< interrupt of WiFi MAC, NMI, use if MAC have bug to fix in NMI*/ + ETS_WIFI_PWR_INTR_SOURCE, /**< */ + ETS_WIFI_BB_INTR_SOURCE, /**< interrupt of WiFi BB, level, we can do some calibartion*/ + ETS_BT_MAC_INTR_SOURCE, /**< will be cancelled*/ + ETS_BT_BB_INTR_SOURCE, /**< interrupt of BT BB, level*/ + ETS_BT_BB_NMI_SOURCE, /**< interrupt of BT BB, NMI, use if BB have bug to fix in NMI*/ + ETS_RWBT_INTR_SOURCE, /**< interrupt of RWBT, level*/ + ETS_RWBLE_INTR_SOURCE, /**< interrupt of RWBLE, level*/ + ETS_RWBT_NMI_SOURCE, /**< interrupt of RWBT, NMI, use if RWBT have bug to fix in NMI*/ + ETS_RWBLE_NMI_SOURCE, /**< interrupt of RWBLE, NMI, use if RWBT have bug to fix in NMI*/ + ETS_I2C_MASTER_SOURCE, /**< interrupt of I2C Master, level*/ + ETS_SLC0_INTR_SOURCE, /**< interrupt of SLC0, level*/ + ETS_SLC1_INTR_SOURCE, /**< interrupt of SLC1, level*/ + ETS_APB_CTRL_INTR_SOURCE, /**< interrupt of APB ctrl, ?*/ + ETS_UHCI0_INTR_SOURCE, /**< interrupt of UHCI0, level*/ + ETS_GPIO_INTR_SOURCE, /**< interrupt of GPIO, level*/ + ETS_GPIO_NMI_SOURCE, /**< interrupt of GPIO, NMI*/ + ETS_SPI1_INTR_SOURCE, /**< interrupt of SPI1, level, SPI1 is for flash read/write, do not use this*/ + ETS_SPI2_INTR_SOURCE, /**< interrupt of SPI2, level*/ + ETS_I2S1_INTR_SOURCE, /**< interrupt of I2S1, level*/ + ETS_UART0_INTR_SOURCE, /**< interrupt of UART0, level*/ + ETS_UART1_INTR_SOURCE, /**< interrupt of UART1, level*/ + ETS_LEDC_INTR_SOURCE, /**< interrupt of LED PWM, level*/ + ETS_EFUSE_INTR_SOURCE, /**< interrupt of efuse, level, not likely to use*/ + ETS_TWAI_INTR_SOURCE, /**< interrupt of can, level*/ + ETS_USB_SERIAL_JTAG_INTR_SOURCE, /**< interrupt of USJ, level*/ + ETS_RTC_CORE_INTR_SOURCE, /**< interrupt of rtc core, level, include rtc watchdog*/ + ETS_RMT_INTR_SOURCE, /**< interrupt of remote controller, level*/ + ETS_I2C_EXT0_INTR_SOURCE, /**< interrupt of I2C controller1, level*/ + ETS_TIMER1_INTR_SOURCE, + ETS_TIMER2_INTR_SOURCE, + ETS_TG0_T0_LEVEL_INTR_SOURCE, /**< interrupt of TIMER_GROUP0, TIMER0, level*/ + ETS_TG0_WDT_LEVEL_INTR_SOURCE, /**< interrupt of TIMER_GROUP0, WATCH DOG, level*/ + ETS_TG1_T0_LEVEL_INTR_SOURCE, /**< interrupt of TIMER_GROUP1, TIMER0, level*/ + ETS_TG1_WDT_LEVEL_INTR_SOURCE, /**< interrupt of TIMER_GROUP1, WATCHDOG, level*/ + ETS_CACHE_IA_INTR_SOURCE, /**< interrupt of Cache Invalid Access, LEVEL*/ + ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, /**< interrupt of system timer 0, EDGE*/ + ETS_SYSTIMER_TARGET1_EDGE_INTR_SOURCE, /**< interrupt of system timer 1, EDGE*/ + ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE, /**< interrupt of system timer 2, EDGE*/ + ETS_SPI_MEM_REJECT_CACHE_INTR_SOURCE, /**< interrupt of SPI0 Cache access and SPI1 access rejected, LEVEL*/ + ETS_ICACHE_PRELOAD0_INTR_SOURCE, /**< interrupt of ICache per load operation, LEVEL*/ + ETS_ICACHE_SYNC0_INTR_SOURCE, /**< interrupt of instruction cache sync done, LEVEL*/ + ETS_APB_ADC_INTR_SOURCE, /**< interrupt of APB ADC, LEVEL*/ + ETS_DMA_CH0_INTR_SOURCE, /**< interrupt of general DMA channel 0, LEVEL*/ + ETS_DMA_CH1_INTR_SOURCE, /**< interrupt of general DMA channel 1, LEVEL*/ + ETS_DMA_CH2_INTR_SOURCE, /**< interrupt of general DMA channel 2, LEVEL*/ + ETS_RSA_INTR_SOURCE, /**< interrupt of RSA accelerator, level*/ + ETS_AES_INTR_SOURCE, /**< interrupt of AES accelerator, level*/ + ETS_SHA_INTR_SOURCE, /**< interrupt of SHA accelerator, level*/ + ETS_FROM_CPU_INTR0_SOURCE, /**< interrupt0 generated from a CPU, level*/ /* Used for FreeRTOS */ + ETS_FROM_CPU_INTR1_SOURCE, /**< interrupt1 generated from a CPU, level*/ /* Used for FreeRTOS */ + ETS_FROM_CPU_INTR2_SOURCE, /**< interrupt2 generated from a CPU, level*/ + ETS_FROM_CPU_INTR3_SOURCE, /**< interrupt3 generated from a CPU, level*/ + ETS_ASSIST_DEBUG_INTR_SOURCE, /**< interrupt of Assist debug module, LEVEL*/ + ETS_DMA_APBPERI_PMS_INTR_SOURCE, + ETS_CORE0_IRAM0_PMS_INTR_SOURCE, + ETS_CORE0_DRAM0_PMS_INTR_SOURCE, + ETS_CORE0_PIF_PMS_INTR_SOURCE, + ETS_CORE0_PIF_PMS_SIZE_INTR_SOURCE, + ETS_BAK_PMS_VIOLATE_INTR_SOURCE, + ETS_CACHE_CORE0_ACS_INTR_SOURCE, + ETS_MAX_INTR_SOURCE, +} periph_interrupt_t; From f3348982cc370d9aa8cde910791ae17bc8cdd5f2 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:46:56 +0800 Subject: [PATCH 37/56] hw/misc: Implement ESP32-C3 Cache (SPI Flash) --- hw/misc/esp32c3_cache.c | 271 ++++++++++++++++++++++++ hw/misc/meson.build | 3 + include/hw/misc/esp32c3_cache.h | 352 ++++++++++++++++++++++++++++++++ 3 files changed, 626 insertions(+) create mode 100644 hw/misc/esp32c3_cache.c create mode 100644 include/hw/misc/esp32c3_cache.h diff --git a/hw/misc/esp32c3_cache.c b/hw/misc/esp32c3_cache.c new file mode 100644 index 000000000000..3ac8e1283dac --- /dev/null +++ b/hw/misc/esp32c3_cache.c @@ -0,0 +1,271 @@ +/* + * ESP32-C3 ICache emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/misc/esp32c3_cache.h" +#include "sysemu/block-backend-io.h" + + +#define CACHE_DEBUG 0 +#define CACHE_WARNING 0 + + +/** + * @brief Checks that the enable flag is enabled in the I/O register. If that's the case, + * `done` flag is returned and the `enable` flag is cleared from register. + * Else, 0 is returned. +*/ +static inline uint32_t check_and_reset_ena(uint32_t* hwreg, uint32_t ena_mask, uint32_t done_mask) +{ + uint32_t regval = *hwreg; + + if (regval & ena_mask) { + regval &= ~ena_mask; + regval |= done_mask; + *hwreg = regval; + } + + return regval; +} + + +static inline uint32_t esp32c3_read_mmu_value(ESP32C3CacheState *s, hwaddr reg_addr) +{ + /* Make the assumption that the address is aligned on sizeof(uint32_t) */ + const int index = reg_addr / sizeof(uint32_t); + return (uint32_t) s->mmu[index].val; +} + + +static inline void esp32c3_write_mmu_value(ESP32C3CacheState *s, hwaddr reg_addr, uint32_t value) +{ + /* Make the assumption that the address is aligned on sizeof(uint32_t) */ + const int index = reg_addr / sizeof(uint32_t); + /* Reserved bits shall always be 0 */ + ESP32C3MMUEntry e = { 0 }; + e.page_number = (uint8_t) (value & 0xff); + if (s->mmu[index].val != e.val) { + assert(s->flash_blk != NULL); + /* Update the cache (MemoryRegion) */ + const uint32_t virtual_address = index * ESP32C3_PAGE_SIZE; + /* The entry contains the index of the 64KB block from the flash memory */ + const uint32_t physical_address = e.page_number * ESP32C3_PAGE_SIZE; + uint8_t* cache_data = ((uint8_t*) memory_region_get_ram_ptr(&s->dcache)) + virtual_address; + + if (e.invalid) { + const uint32_t invalid_value = 0xdeadbeef; + uint32_t* cache_word_data = (uint32_t*) cache_data; + for (int i = 0; i < ESP32C3_PAGE_SIZE / sizeof(invalid_value); i++) { + cache_word_data[i] = invalid_value; + } + } else { + blk_pread(s->flash_blk, physical_address, ESP32C3_PAGE_SIZE, cache_data, 0); + } + + s->mmu[index].val = e.val; + } +} + + +static uint64_t esp32c3_cache_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3CacheState *s = ESP32C3_CACHE(opaque); + const hwaddr index = ESP32C3_CACHE_REG_IDX(addr); + uint64_t r = 0; + + if (addr & 0x3) { + /* Unaligned access, should we fail? */ + error_report("[QEMU] unaligned access to the cache registers\n"); + } + + switch(addr) { + case A_EXTMEM_ICACHE_CTRL: + r = s->icache_enable; + break; + /* For the following registers, mark the bit as done only if the feature was enabled */ + case A_EXTMEM_ICACHE_SYNC_CTRL: + r = check_and_reset_ena(&s->regs[index], + R_EXTMEM_ICACHE_SYNC_CTRL_INVALIDATE_ENA_MASK, + R_EXTMEM_ICACHE_SYNC_CTRL_SYNC_DONE_MASK); + break; + case A_EXTMEM_ICACHE_AUTOLOAD_CTRL: + r = check_and_reset_ena(&s->regs[index], + R_EXTMEM_ICACHE_AUTOLOAD_CTRL_AUTOLOAD_ENA_MASK, + R_EXTMEM_ICACHE_AUTOLOAD_CTRL_AUTOLOAD_DONE_MASK); + break; + case A_EXTMEM_ICACHE_PRELOAD_CTRL: + r = check_and_reset_ena(&s->regs[index], + R_EXTMEM_ICACHE_PRELOAD_CTRL_PRELOAD_ENA_MASK, + R_EXTMEM_ICACHE_PRELOAD_CTRL_PRELOAD_DONE_MASK); + break; + case A_EXTMEM_ICACHE_FREEZE: + r = s->regs[index]; + break; + case A_EXTMEM_CACHE_STATE: + /* Return the state of ICache as idle: + * 1: Idle + * 0: Busy/Not idle */ + r = 1 << R_EXTMEM_CACHE_STATE_ICACHE_STATE_SHIFT; + break; + case ESP32C3_MMU_TABLE_OFFSET ... (ESP32C3_MMU_TABLE_OFFSET + ESP32C3_MMU_SIZE): + r = esp32c3_read_mmu_value(s, addr - ESP32C3_MMU_TABLE_OFFSET); + break; + default: +#if CACHE_WARNING + warn_report("[CACHE] Unsupported read to 0x%lx\n", addr); +#endif + break; + } + +#if CACHE_DEBUG + info_report("[CACHE] Reading 0x%lx (0x%lx)\n", addr, r); +#endif + + return r; +} + +static void esp32c3_cache_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) +{ + ESP32C3CacheState *s = ESP32C3_CACHE(opaque); + + const hwaddr index = ESP32C3_CACHE_REG_IDX(addr); + + if (index < ESP32C3_CACHE_REG_COUNT) { + switch (addr) { + case A_EXTMEM_ICACHE_CTRL: + s->icache_enable = value & 1; + break; + case A_EXTMEM_ICACHE_FREEZE: + if (value & R_EXTMEM_ICACHE_FREEZE_ICACHE_FREEZE_ENA_MASK) { + /* Enable freeze, set DONE bit */ + s->regs[index] |= R_EXTMEM_ICACHE_FREEZE_ICACHE_FREEZE_DONE_MASK; + } else { + /* Disable freeze, clear DONE bit */ + s->regs[index] &= ~R_EXTMEM_ICACHE_FREEZE_ICACHE_FREEZE_DONE_MASK; + } + break; + default: + s->regs[index] = value; + break; + } + } else if (addr >= ESP32C3_MMU_TABLE_OFFSET) { + esp32c3_write_mmu_value(s, addr - ESP32C3_MMU_TABLE_OFFSET, value); + } + +#if CACHE_DEBUG + info_report("[CACHE] Writing 0x%lx = %08lx\n", addr, value); +#endif + +} + +static const MemoryRegionOps esp32c3_cache_ops = { + .read = esp32c3_cache_read, + .write = esp32c3_cache_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static bool esp32c3_cache_mem_accepts(void *opaque, hwaddr addr, + unsigned size, bool is_write, + MemTxAttrs attrs) +{ + /* Only accept operation in the cache if there are in READ access. + * TODO: Refuse any access to the cache if disable and trigger an exception. */ + return !is_write; +} + +static const MemoryRegionOps esp32c3_cache_mem_ops = { + .write = NULL, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid.accepts = esp32c3_cache_mem_accepts, +}; + +static void esp32c3_cache_reset(DeviceState *dev) +{ + ESP32C3CacheState *s = ESP32C3_CACHE(dev); + memset(s->regs, 0, ESP32C3_CACHE_REG_COUNT * sizeof(*s->regs)); + + /* Initialize the MMU with invalid entries */ + for (int i = 0; i < ESP32C3_MMU_TABLE_ENTRY_COUNT; i++) { + s->mmu[i].invalid = 1; + } + + /* On reset, autoload must be set to done (ready) */ + s->regs[ESP32C3_CACHE_REG_IDX(A_EXTMEM_ICACHE_AUTOLOAD_CTRL)] = R_EXTMEM_ICACHE_AUTOLOAD_CTRL_AUTOLOAD_DONE_MASK; + /* Same goes for the manual preload */ + s->regs[ESP32C3_CACHE_REG_IDX(A_EXTMEM_ICACHE_PRELOAD_CTRL)] = R_EXTMEM_ICACHE_PRELOAD_CTRL_PRELOAD_DONE_MASK; +} + +static void esp32c3_cache_realize(DeviceState *dev, Error **errp) +{ + /* Initialize the registers */ + esp32c3_cache_reset(dev); +} + +static void esp32c3_cache_init(Object *obj) +{ + ESP32C3CacheState *s = ESP32C3_CACHE(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + /* Since the cache I/O region and the MMU I/O region are adjacent, let's use the same MemoryRegion object + * for both, this will simplify the machine architecture. */ + memory_region_init_io(&s->iomem, obj, &esp32c3_cache_ops, s, + TYPE_ESP32C3_CACHE, TYPE_ESP32C3_CACHE_IO_SIZE + ESP32C3_MMU_SIZE); + + /* Initialize the data cache area first */ + s->dcache_base = ESP32C3_DCACHE_BASE; + memory_region_init_rom_device(&s->dcache, OBJECT(s), + &esp32c3_cache_mem_ops, s, + "cpu0-dcache", ESP32C3_EXTMEM_REGION_SIZE, &error_abort); + + /* Same goes for the instruction cache */ + s->icache_base = ESP32C3_ICACHE_BASE; + memory_region_init_alias(&s->icache, OBJECT(s), "cpu0-icache", &s->dcache, 0, ESP32C3_EXTMEM_REGION_SIZE); + + sysbus_init_mmio(sbd, &s->iomem); +} + +static Property esp32c3_cache_properties[] = { + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32c3_cache_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_cache_reset; + dc->realize = esp32c3_cache_realize; + device_class_set_props(dc, esp32c3_cache_properties); +} + +static const TypeInfo esp32c3_cache_info = { + .name = TYPE_ESP32C3_CACHE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3CacheState), + .instance_init = esp32c3_cache_init, + .class_init = esp32c3_cache_class_init +}; + +static void esp32c3_cache_register_types(void) +{ + type_register_static(&esp32c3_cache_info); +} + +type_init(esp32c3_cache_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index fd85a80ba48b..a37105ab7494 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -136,6 +136,9 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_flash_enc.c', 'ssi_psram.c' )) +softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files( + 'esp32c3_cache.c' +)) if gcrypt.found() softmmu_ss.add(when: [gcrypt, 'CONFIG_XTENSA_ESP32'], if_true: files( diff --git a/include/hw/misc/esp32c3_cache.h b/include/hw/misc/esp32c3_cache.h new file mode 100644 index 000000000000..72acfc09e5f1 --- /dev/null +++ b/include/hw/misc/esp32c3_cache.h @@ -0,0 +1,352 @@ +#pragma once + +#include "hw/misc/esp32c3_reg.h" +#include "hw/sysbus.h" +#include "hw/hw.h" +#include "hw/registerfields.h" + +#define TYPE_ESP32C3_CACHE "esp32c3.cache" +#define ESP32C3_CACHE(obj) OBJECT_CHECK(ESP32C3CacheState, (obj), TYPE_ESP32C3_CACHE) +#define ESP32C3_CACHE_GET_CLASS(obj) OBJECT_GET_CLASS(ESP32C3CacheState, obj, TYPE_ESP32C3_CACHE) +#define ESP32C3_CACHE_CLASS(klass) OBJECT_CLASS_CHECK(ESP32C3CacheState, klass, TYPE_ESP32C3_CACHE) + +#define ESP32C3_DCACHE_BASE 0x3c000000 +#define ESP32C3_ICACHE_BASE 0x42000000 + +/* The MMU is shared between by both the ICache and the DCache */ +#define ESP32C3_MMU_SIZE 0x200 + +/* Each MMU virtual page is 64KB big on the ESP32C3 */ +#define ESP32C3_PAGE_SIZE (64*1024) + +/* Offset of the MMU table in I/O memory range + * As the MMU table is mapped in the same MemoryRegion as the Cache I/O registers, its base offset + * will not be 0 */ +#define ESP32C3_MMU_TABLE_OFFSET (DR_REG_MMU_TABLE - DR_REG_EXTMEM_BASE) + +/* Number of entries count in the table size */ +#define ESP32C3_MMU_TABLE_ENTRY_COUNT (ESP32C3_MMU_SIZE/sizeof(uint32_t)) + +typedef union ESP32C3MMUEntry { + struct { + uint32_t reserved : 23; /* Must always be 0 */ + uint32_t invalid : 1; + uint32_t page_number : 8; + }; + uint32_t val; +} ESP32C3MMUEntry; + +_Static_assert(sizeof(ESP32C3MMUEntry) == sizeof(uint32_t), "MMU Entry size must be 4 bytes"); + +/** + * The external memory region on the ESP32-C3 is 2x8MB, but both regions are shared (data & instructions) + */ +#define ESP32C3_EXTMEM_REGION_SIZE 0x800000 + +/** + * The cache on ESP32-C3 has a size of 16KB, and the block size is 32 bytes (1024 blocks) + */ +#define ESP32C3_CACHE_BLOCK_SIZE 32 +#define ESP32C3_CACHE_BLOCK_COUNT 512 +#define ESP32C3_CACHE_SIZE (ESP32C3_CACHE_BLOCK_COUNT * ESP32C3_CACHE_BLOCK_SIZE) + +/** + * Size of the Cache I/O registers area + */ +#define TYPE_ESP32C3_CACHE_IO_SIZE 0x1000 + +/** + * Even though the size of the I/O range for extmem cache is 0x1000, the registers actually go + * up to 0x100. + */ +#define ESP32C3_CACHE_REG_COUNT (0x100 / sizeof(uint32_t)) + +/** + * Convert a register address to its index in the registers array + */ +#define ESP32C3_CACHE_REG_IDX(addr) ((addr) / sizeof(uint32_t)) + +typedef struct { + SysBusDevice parent; + BlockBackend *flash_blk; + MemoryRegion iomem; + + bool icache_enable; + hwaddr dcache_base; + hwaddr icache_base; + MemoryRegion dcache; + MemoryRegion icache; + + /* Registers for controlling the cache */ + uint32_t regs[ESP32C3_CACHE_REG_COUNT]; + + /* Define the MMU itself as an array, it shall be accessible from address ESP32C3_MMU_TABLE */ + ESP32C3MMUEntry mmu[ESP32C3_MMU_TABLE_ENTRY_COUNT]; +} ESP32C3CacheState; + +/* Assert that the size of the MMU table in the structure is of size ESP32C3_MMU_SIZE */ +_Static_assert(sizeof(ESP32C3CacheState) - offsetof(ESP32C3CacheState, mmu) == ESP32C3_MMU_SIZE, + "The size of `mmu` field in structure ESP32C3CacheState must be equal to ESP32C3_MMU_SIZE"); + + +REG32(EXTMEM_ICACHE_CTRL, 0x000) + FIELD(EXTMEM_ICACHE_CTRL, ENABLE, 0, 1) + +REG32(EXTMEM_ICACHE_CTRL1, 0x004) + FIELD(EXTMEM_ICACHE_CTRL1, SHUT_DBUS, 1, 1) + FIELD(EXTMEM_ICACHE_CTRL1, SHUT_IBUS, 0, 1) + +REG32(EXTMEM_ICACHE_TAG_POWER_CTRL, 0x008) + FIELD(EXTMEM_ICACHE_TAG_POWER_CTRL, TAG_MEM_FORCE_PU, 2, 1) + FIELD(EXTMEM_ICACHE_TAG_POWER_CTRL, TAG_MEM_FORCE_PD, 1, 1) + FIELD(EXTMEM_ICACHE_TAG_POWER_CTRL, TAG_MEM_FORCE_ON, 0, 1) + +REG32(EXTMEM_ICACHE_PRELOCK_CTRL, 0x00C) + FIELD(EXTMEM_ICACHE_PRELOCK_CTRL, PRELOCK_SCT1_EN, 1, 1) + FIELD(EXTMEM_ICACHE_PRELOCK_CTRL, PRELOCK_SCT0_EN, 0, 1) + +REG32(EXTMEM_ICACHE_PRELOCK_SCT0_ADDR, 0x010) + FIELD(EXTMEM_ICACHE_PRELOCK_SCT0_ADDR, PRELOCK_SCT0_ADDR, 0, 32) + +REG32(EXTMEM_ICACHE_PRELOCK_SCT1_ADDR, 0x014) + FIELD(EXTMEM_ICACHE_PRELOCK_SCT1_ADDR, PRELOCK_SCT1_ADDR, 0, 32) + +REG32(EXTMEM_ICACHE_PRELOCK_SCT_SIZE, 0x018) + FIELD(EXTMEM_ICACHE_PRELOCK_SCT_SIZE, PRELOCK_SCT0_SIZE, 16, 16) + FIELD(EXTMEM_ICACHE_PRELOCK_SCT_SIZE, PRELOCK_SCT1_SIZE, 0, 16) + +REG32(EXTMEM_ICACHE_LOCK_CTRL, 0x01C) + FIELD(EXTMEM_ICACHE_LOCK_CTRL, LOCK_DONE, 2, 1) + FIELD(EXTMEM_ICACHE_LOCK_CTRL, UNLOCK_ENA, 1, 1) + FIELD(EXTMEM_ICACHE_LOCK_CTRL, LOCK_ENA, 0, 1) + +REG32(EXTMEM_ICACHE_LOCK_ADDR, 0x020) + FIELD(EXTMEM_ICACHE_LOCK_ADDR, LOCK_ADDR, 0, 32) + +REG32(EXTMEM_ICACHE_LOCK_SIZE, 0x024) + FIELD(EXTMEM_ICACHE_LOCK_SIZE, LOCK_SIZE, 0, 16) + +REG32(EXTMEM_ICACHE_SYNC_CTRL, 0x028) + FIELD(EXTMEM_ICACHE_SYNC_CTRL, SYNC_DONE, 1, 1) + FIELD(EXTMEM_ICACHE_SYNC_CTRL, INVALIDATE_ENA, 0, 1) + +REG32(EXTMEM_ICACHE_SYNC_ADDR, 0x02C) + FIELD(EXTMEM_ICACHE_SYNC_ADDR, SYNC_ADDR, 0, 32) + +REG32(EXTMEM_ICACHE_SYNC_SIZE, 0x030) + FIELD(EXTMEM_ICACHE_SYNC_SIZE, SYNC_SIZE, 0, 23) + +REG32(EXTMEM_ICACHE_PRELOAD_CTRL, 0x034) + FIELD(EXTMEM_ICACHE_PRELOAD_CTRL, PRELOAD_ORDER, 2, 1) + FIELD(EXTMEM_ICACHE_PRELOAD_CTRL, PRELOAD_DONE, 1, 1) + FIELD(EXTMEM_ICACHE_PRELOAD_CTRL, PRELOAD_ENA, 0, 1) + +REG32(EXTMEM_ICACHE_PRELOAD_ADDR, 0x038) + FIELD(EXTMEM_ICACHE_PRELOAD_ADDR, PRELOAD_ADDR, 0, 32) + +REG32(EXTMEM_ICACHE_PRELOAD_SIZE, 0x03C) + FIELD(EXTMEM_ICACHE_PRELOAD_SIZE, PRELOAD_SIZE, 0, 16) + +REG32(EXTMEM_ICACHE_AUTOLOAD_CTRL, 0x040) + FIELD(EXTMEM_ICACHE_AUTOLOAD_CTRL, AUTOLOAD_RQST, 5, 2) + FIELD(EXTMEM_ICACHE_AUTOLOAD_CTRL, AUTOLOAD_ORDER, 4, 1) + FIELD(EXTMEM_ICACHE_AUTOLOAD_CTRL, AUTOLOAD_DONE, 3, 1) + FIELD(EXTMEM_ICACHE_AUTOLOAD_CTRL, AUTOLOAD_ENA, 2, 1) + FIELD(EXTMEM_ICACHE_AUTOLOAD_CTRL, AUTOLOAD_SCT1_ENA, 1, 1) + FIELD(EXTMEM_ICACHE_AUTOLOAD_CTRL, AUTOLOAD_SCT0_ENA, 0, 1) + +REG32(EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR, 0x044) + FIELD(EXTMEM_ICACHE_AUTOLOAD_SCT0_ADDR, AUTOLOAD_SCT0_ADDR, 0, 32) + +REG32(EXTMEM_ICACHE_AUTOLOAD_SCT0_SIZE, 0x048) + FIELD(EXTMEM_ICACHE_AUTOLOAD_SCT0_SIZE, AUTOLOAD_SCT0_SIZE, 0, 27) + +REG32(EXTMEM_ICACHE_AUTOLOAD_SCT1_ADDR, 0x04C) + FIELD(EXTMEM_ICACHE_AUTOLOAD_SCT1_ADDR, AUTOLOAD_SCT1_ADDR, 0, 32) + +REG32(EXTMEM_ICACHE_AUTOLOAD_SCT1_SIZE, 0x050) + FIELD(EXTMEM_ICACHE_AUTOLOAD_SCT1_SIZE, AUTOLOAD_SCT1_SIZE, 0, 27) + +REG32(EXTMEM_IBUS_TO_FLASH_START_VADDR, 0x054) + FIELD(EXTMEM_IBUS_TO_FLASH_START_VADDR, IBUS_TO_FLASH_START_VADDR, 0, 32) + +REG32(EXTMEM_IBUS_TO_FLASH_END_VADDR, 0x058) + FIELD(EXTMEM_IBUS_TO_FLASH_END_VADDR, IBUS_TO_FLASH_END_VADDR, 0, 32) + +REG32(EXTMEM_DBUS_TO_FLASH_START_VADDR, 0x05C) + FIELD(EXTMEM_DBUS_TO_FLASH_START_VADDR, DBUS_TO_FLASH_START_VADDR, 0, 32) + +REG32(EXTMEM_DBUS_TO_FLASH_END_VADDR, 0x060) + FIELD(EXTMEM_DBUS_TO_FLASH_END_VADDR, DBUS_TO_FLASH_END_VADDR, 0, 32) + +REG32(EXTMEM_CACHE_ACS_CNT_CLR, 0x064) + FIELD(EXTMEM_CACHE_ACS_CNT_CLR, DBUS_ACS_CNT_CLR, 1, 1) + FIELD(EXTMEM_CACHE_ACS_CNT_CLR, IBUS_ACS_CNT_CLR, 0, 1) + +REG32(EXTMEM_IBUS_ACS_MISS_CNT, 0x068) + FIELD(EXTMEM_IBUS_ACS_MISS_CNT, IBUS_ACS_MISS_CNT, 0, 32) + +REG32(EXTMEM_IBUS_ACS_CNT, 0x06C) + FIELD(EXTMEM_IBUS_ACS_CNT, IBUS_ACS_CNT, 0, 32) + +REG32(EXTMEM_DBUS_ACS_FLASH_MISS_CNT, 0x070) + FIELD(EXTMEM_DBUS_ACS_FLASH_MISS_CNT, DBUS_ACS_FLASH_MISS_CNT, 0, 32) + +REG32(EXTMEM_DBUS_ACS_CNT, 0x074) + FIELD(EXTMEM_DBUS_ACS_CNT, DBUS_ACS_CNT, 0, 32) + +REG32(EXTMEM_CACHE_ILG_INT_ENA, 0x078) + FIELD(EXTMEM_CACHE_ILG_INT_ENA, DBUS_CNT_OVF_INT_ENA, 8, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ENA, IBUS_CNT_OVF_INT_ENA, 7, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ENA, MMU_ENTRY_FAULT_INT_ENA, 5, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ENA, ICACHE_PRELOAD_OP_FAULT_INT_ENA, 1, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ENA, ICACHE_SYNC_OP_FAULT_INT_ENA, 0, 1) + +REG32(EXTMEM_CACHE_ILG_INT_CLR, 0x07C) + FIELD(EXTMEM_CACHE_ILG_INT_CLR, DBUS_CNT_OVF_INT_CLR, 8, 1) + FIELD(EXTMEM_CACHE_ILG_INT_CLR, IBUS_CNT_OVF_INT_CLR, 7, 1) + FIELD(EXTMEM_CACHE_ILG_INT_CLR, MMU_ENTRY_FAULT_INT_CLR, 5, 1) + FIELD(EXTMEM_CACHE_ILG_INT_CLR, ICACHE_PRELOAD_OP_FAULT_INT_CLR, 1, 1) + FIELD(EXTMEM_CACHE_ILG_INT_CLR, ICACHE_SYNC_OP_FAULT_INT_CLR, 0, 1) + +REG32(EXTMEM_CACHE_ILG_INT_ST, 0x080) + FIELD(EXTMEM_CACHE_ILG_INT_ST, DBUS_ACS_FLASH_MISS_CNT_OVF_ST, 10, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ST, DBUS_ACS_CNT_OVF_ST, 9, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ST, IBUS_ACS_MISS_CNT_OVF_ST, 8, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ST, IBUS_ACS_CNT_OVF_ST, 7, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ST, MMU_ENTRY_FAULT_ST, 5, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ST, ICACHE_PRELOAD_OP_FAULT_ST, 1, 1) + FIELD(EXTMEM_CACHE_ILG_INT_ST, ICACHE_SYNC_OP_FAULT_ST, 0, 1) + +REG32(EXTMEM_CORE0_ACS_CACHE_INT_ENA, 0x084) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ENA, CORE0_DBUS_WR_IC_INT_ENA, 5, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ENA, CORE0_DBUS_REJECT_INT_ENA, 4, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ENA, CORE0_DBUS_ACS_MSK_IC_INT_ENA, 3, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ENA, CORE0_IBUS_REJECT_INT_ENA, 2, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ENA, CORE0_IBUS_WR_IC_INT_ENA, 1, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ENA, CORE0_IBUS_ACS_MSK_IC_INT_ENA, 0, 1) + +REG32(EXTMEM_CORE0_ACS_CACHE_INT_CLR, 0x088) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_CLR, CORE0_DBUS_WR_IC_INT_CLR, 5, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_CLR, CORE0_DBUS_REJECT_INT_CLR, 4, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_CLR, CORE0_DBUS_ACS_MSK_IC_INT_CLR, 3, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_CLR, CORE0_IBUS_REJECT_INT_CLR, 2, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_CLR, CORE0_IBUS_WR_IC_INT_CLR, 1, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_CLR, CORE0_IBUS_ACS_MSK_IC_INT_CLR, 0, 1) + +REG32(EXTMEM_CORE0_ACS_CACHE_INT_ST, 0x08C) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ST, CORE0_DBUS_WR_ICACHE_ST, 5, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ST, CORE0_DBUS_REJECT_ST, 4, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ST, CORE0_DBUS_ACS_MSK_ICACHE_ST, 3, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ST, CORE0_IBUS_REJECT_ST, 2, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ST, CORE0_IBUS_WR_ICACHE_ST, 1, 1) + FIELD(EXTMEM_CORE0_ACS_CACHE_INT_ST, CORE0_IBUS_ACS_MSK_ICACHE_ST, 0, 1) + +REG32(EXTMEM_CORE0_DBUS_REJECT_ST, 0x090) + FIELD(EXTMEM_CORE0_DBUS_REJECT_ST, CORE0_DBUS_WORLD, 3, 1) + FIELD(EXTMEM_CORE0_DBUS_REJECT_ST, CORE0_DBUS_ATTR, 0, 3) + +REG32(EXTMEM_CORE0_DBUS_REJECT_VADDR, 0x094) + FIELD(EXTMEM_CORE0_DBUS_REJECT_VADDR, CORE0_DBUS_VADDR, 0, 32) + +REG32(EXTMEM_CORE0_IBUS_REJECT_ST, 0x098) + FIELD(EXTMEM_CORE0_IBUS_REJECT_ST, CORE0_IBUS_WORLD, 3, 1) + FIELD(EXTMEM_CORE0_IBUS_REJECT_ST, CORE0_IBUS_ATTR, 0, 3) + +REG32(EXTMEM_CORE0_IBUS_REJECT_VADDR, 0x09C) + FIELD(EXTMEM_CORE0_IBUS_REJECT_VADDR, CORE0_IBUS_VADDR, 0, 32) + +REG32(EXTMEM_CACHE_MMU_FAULT_CONTENT, 0x0A0) + FIELD(EXTMEM_CACHE_MMU_FAULT_CONTENT, CACHE_MMU_FAULT_CODE, 10, 4) + FIELD(EXTMEM_CACHE_MMU_FAULT_CONTENT, CACHE_MMU_FAULT_CONTENT, 0, 10) + +REG32(EXTMEM_CACHE_MMU_FAULT_VADDR, 0x0A4) + FIELD(EXTMEM_CACHE_MMU_FAULT_VADDR, CACHE_MMU_FAULT_VADDR, 0, 32) + +REG32(EXTMEM_CACHE_WRAP_AROUND_CTRL, 0x0A8) + FIELD(EXTMEM_CACHE_WRAP_AROUND_CTRL, CACHE_FLASH_WRAP_AROUND, 0, 1) + +REG32(EXTMEM_CACHE_MMU_POWER_CTRL, 0x0AC) + FIELD(EXTMEM_CACHE_MMU_POWER_CTRL, CACHE_MMU_MEM_FORCE_PU, 2, 1) + FIELD(EXTMEM_CACHE_MMU_POWER_CTRL, CACHE_MMU_MEM_FORCE_PD, 1, 1) + FIELD(EXTMEM_CACHE_MMU_POWER_CTRL, CACHE_MMU_MEM_FORCE_ON, 0, 1) + +REG32(EXTMEM_CACHE_STATE, 0x0B0) + FIELD(EXTMEM_CACHE_STATE, ICACHE_STATE, 0, 12) + +REG32(EXTMEM_CACHE_ENCRYPT_DECRYPT_RECORD_DISABLE, 0x0B4) + FIELD(EXTMEM_CACHE_ENCRYPT_DECRYPT_RECORD_DISABLE, RECORD_DISABLE_G0CB_DECRYPT, 1, 1) + FIELD(EXTMEM_CACHE_ENCRYPT_DECRYPT_RECORD_DISABLE, RECORD_DISABLE_DB_ENCRYPT, 0, 1) + +REG32(EXTMEM_CACHE_ENCRYPT_DECRYPT_CLK_FORCE_ON, 0x0B8) + FIELD(EXTMEM_CACHE_ENCRYPT_DECRYPT_CLK_FORCE_ON, CLK_FORCE_ON_CRYPT, 2, 1) + FIELD(EXTMEM_CACHE_ENCRYPT_DECRYPT_CLK_FORCE_ON, CLK_FORCE_ON_AUTO_CRYPT, 1, 1) + FIELD(EXTMEM_CACHE_ENCRYPT_DECRYPT_CLK_FORCE_ON, CLK_FORCE_ON_MANUAL_CRYPT, 0, 1) + +REG32(EXTMEM_CACHE_PRELOAD_INT_CTRL, 0x0BC) + FIELD(EXTMEM_CACHE_PRELOAD_INT_CTRL, ICACHE_PRELOAD_INT_CLR, 2, 1) + FIELD(EXTMEM_CACHE_PRELOAD_INT_CTRL, ICACHE_PRELOAD_INT_ENA, 1, 1) + FIELD(EXTMEM_CACHE_PRELOAD_INT_CTRL, ICACHE_PRELOAD_INT_ST, 0, 1) + +REG32(EXTMEM_CACHE_SYNC_INT_CTRL, 0x0C0) + FIELD(EXTMEM_CACHE_SYNC_INT_CTRL, ICACHE_SYNC_INT_CLR, 2, 1) + FIELD(EXTMEM_CACHE_SYNC_INT_CTRL, ICACHE_SYNC_INT_ENA, 1, 1) + FIELD(EXTMEM_CACHE_SYNC_INT_CTRL, ICACHE_SYNC_INT_ST, 0, 1) + +REG32(EXTMEM_CACHE_MMU_OWNER, 0x0C4) + FIELD(EXTMEM_CACHE_MMU_OWNER, CACHE_MMU_OWNER, 0, 4) + +REG32(EXTMEM_CACHE_CONF_MISC, 0x0C8) + FIELD(EXTMEM_CACHE_CONF_MISC, CACHE_TRACE_ENA, 2, 1) + FIELD(EXTMEM_CACHE_CONF_MISC, CACHE_IGNORE_SYNC_MMU_ENTRY_FAULT, 1, 1) + FIELD(EXTMEM_CACHE_CONF_MISC, CACHE_IGNORE_PRELOAD_MMU_ENTRY_FAULT, 0, 1) + +REG32(EXTMEM_ICACHE_FREEZE, 0x0CC) + FIELD(EXTMEM_ICACHE_FREEZE, ICACHE_FREEZE_DONE, 2, 1) + FIELD(EXTMEM_ICACHE_FREEZE, ICACHE_FREEZE_MODE, 1, 1) + FIELD(EXTMEM_ICACHE_FREEZE, ICACHE_FREEZE_ENA, 0, 1) + +REG32(EXTMEM_ICACHE_ATOMIC_OPERATE_ENA, 0x0D0) + FIELD(EXTMEM_ICACHE_ATOMIC_OPERATE_ENA, ICACHE_ATOMIC_OPERATE_ENA, 0, 1) + +REG32(EXTMEM_CACHE_REQUEST, 0x0D4) + FIELD(EXTMEM_CACHE_REQUEST, CACHE_REQUEST_BYPASS, 0, 1) + +REG32(EXTMEM_IBUS_PMS_TBL_LOCK, 0x0D8) + FIELD(EXTMEM_IBUS_PMS_TBL_LOCK, IBUS_PMS_LOCK, 0, 1) + +REG32(EXTMEM_IBUS_PMS_TBL_BOUNDARY0, 0x0DC) + FIELD(EXTMEM_IBUS_PMS_TBL_BOUNDARY0, IBUS_PMS_BOUNDARY0, 0, 12) + +REG32(EXTMEM_IBUS_PMS_TBL_BOUNDARY1, 0x0E0) + FIELD(EXTMEM_IBUS_PMS_TBL_BOUNDARY1, IBUS_PMS_BOUNDARY1, 0, 12) + +REG32(EXTMEM_IBUS_PMS_TBL_BOUNDARY2, 0x0E4) + FIELD(EXTMEM_IBUS_PMS_TBL_BOUNDARY2, IBUS_PMS_BOUNDARY2, 0, 12) + +REG32(EXTMEM_IBUS_PMS_TBL_ATTR, 0x0E8) + FIELD(EXTMEM_IBUS_PMS_TBL_ATTR, IBUS_PMS_SCT2_ATTR, 4, 4) + FIELD(EXTMEM_IBUS_PMS_TBL_ATTR, IBUS_PMS_SCT1_ATTR, 0, 4) + +REG32(EXTMEM_DBUS_PMS_TBL_LOCK, 0x0EC) + FIELD(EXTMEM_DBUS_PMS_TBL_LOCK, DBUS_PMS_LOCK, 0, 1) + +REG32(EXTMEM_DBUS_PMS_TBL_BOUNDARY0, 0x0F0) + FIELD(EXTMEM_DBUS_PMS_TBL_BOUNDARY0, DBUS_PMS_BOUNDARY0, 0, 12) + +REG32(EXTMEM_DBUS_PMS_TBL_BOUNDARY1, 0x0F4) + FIELD(EXTMEM_DBUS_PMS_TBL_BOUNDARY1, DBUS_PMS_BOUNDARY1, 0, 12) + +REG32(EXTMEM_DBUS_PMS_TBL_BOUNDARY2, 0x0F8) + FIELD(EXTMEM_DBUS_PMS_TBL_BOUNDARY2, DBUS_PMS_BOUNDARY2, 0, 12) + +REG32(EXTMEM_DBUS_PMS_TBL_ATTR, 0x0FC) + FIELD(EXTMEM_DBUS_PMS_TBL_ATTR, DBUS_PMS_SCT2_ATTR, 2, 2) + FIELD(EXTMEM_DBUS_PMS_TBL_ATTR, DBUS_PMS_SCT1_ATTR, 0, 2) + +REG32(EXTMEM_CLOCK_GATE, 0x100) + FIELD(EXTMEM_CLOCK_GATE, CLK_EN, 0, 1) + +REG32(EXTMEM_DATE, 0x3FC) + FIELD(EXTMEM_DATE, DATE, 0, 28) + From 14f8919e0472daadcf5200805f9855164e4b259f Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:47:56 +0800 Subject: [PATCH 38/56] hw/misc: Implement ESP32-C3 SHA --- crypto/meson.build | 1 + crypto/sha224-internal.c | 30 ++++++ crypto/sha224_i.h | 24 +++++ hw/misc/esp32c3_sha.c | 176 ++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 3 +- include/hw/misc/esp32c3_sha.h | 104 ++++++++++++++++++++ 6 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 crypto/sha224-internal.c create mode 100644 crypto/sha224_i.h create mode 100644 hw/misc/esp32c3_sha.c create mode 100644 include/hw/misc/esp32c3_sha.h diff --git a/crypto/meson.build b/crypto/meson.build index e35c633c8576..8b6bcc6cc7c4 100644 --- a/crypto/meson.build +++ b/crypto/meson.build @@ -53,6 +53,7 @@ util_ss.add(files('aes.c')) util_ss.add(files('sha512-internal.c')) util_ss.add(files('sha384-internal.c')) util_ss.add(files('sha256-internal.c')) +util_ss.add(files('sha224-internal.c')) util_ss.add(files('sha1-internal.c')) util_ss.add(files('init.c')) if gnutls.found() diff --git a/crypto/sha224-internal.c b/crypto/sha224-internal.c new file mode 100644 index 000000000000..98501f28bf9c --- /dev/null +++ b/crypto/sha224-internal.c @@ -0,0 +1,30 @@ +/* + * SHA-224 hash implementation and interface functions + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "sha224_i.h" + + +int sha224_compress(sha224_state *md, unsigned char *buf) +{ + return sha256_compress(md, buf); +} + + +void sha224_init(sha224_state *md) +{ + /** + * Initial values for SHA224 algorithm + */ + md->state[0] = 0xC1059ED8UL; + md->state[1] = 0x367CD507UL; + md->state[2] = 0x3070DD17UL; + md->state[3] = 0xF70E5939UL; + md->state[4] = 0xFFC00B31UL; + md->state[5] = 0x68581511UL; + md->state[6] = 0x64F98FA7UL; + md->state[7] = 0xBEFA4FA4UL; +} diff --git a/crypto/sha224_i.h b/crypto/sha224_i.h new file mode 100644 index 000000000000..e4c58f3fbd07 --- /dev/null +++ b/crypto/sha224_i.h @@ -0,0 +1,24 @@ +/* + * SHA-224 internal definitions + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA224_I_H +#define SHA224_I_H + +#include "qemu/osdep.h" +#include "sha256_i.h" + +/** + * @brief Size of SHA224 hash in bytes + */ +#define SHA224_HASH_SIZE 28 + +typedef struct sha256_state sha224_state; + +void sha224_init(sha224_state *md); +int sha224_compress(sha224_state *md, unsigned char *buf); + +#endif /* SHA224_I_H */ diff --git a/hw/misc/esp32c3_sha.c b/hw/misc/esp32c3_sha.c new file mode 100644 index 000000000000..12864f000718 --- /dev/null +++ b/hw/misc/esp32c3_sha.c @@ -0,0 +1,176 @@ +/* + * ESP32 SHA accelerator + * + * Copyright (c) 2019 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32c3_sha.h" + + +#define SHA_WARNING 0 + + +static ESP32C3HashAlg esp32c3_algs[] = { + [ESP32C3_SHA_1_MODE] = { + .init = (hash_init) sha1_init, + .compress = (hash_compress) sha1_compress, + .len = sizeof(struct sha1_state) + }, + [ESP32C3_SHA_224_MODE] = { + .init = (hash_init) sha224_init, + .compress = (hash_compress) sha224_compress, + .len = SHA224_HASH_SIZE + }, + [ESP32C3_SHA_256_MODE] = { + .init = (hash_init) sha256_init, + .compress = (hash_compress) sha256_compress, + .len = sizeof(struct sha256_state) + }, +}; + + +static void esp32c3_resume_hash(ESP32C3ShaState *s) +{ + /* TODO: we can imagine a scenario where the application wants to calculate the hash of a + * precalculated context, in that case, the application would fill the `hash` registers and + * call `continue` instead of using `start`. We don't support that for the moment. */ + assert(s->mode <= ESP32C3_SHA_256_MODE); + ESP32C3HashAlg alg = esp32c3_algs[s->mode]; + + assert(alg.compress); + + alg.compress(&s->context, (uint8_t*) s->message); + memcpy(s->hash, &s->context, alg.len); +} + + +static void esp32c3_start_hash(ESP32C3ShaState *s) +{ + ESP32C3HashAlg alg = esp32c3_algs[s->mode]; + + if (alg.init && alg.compress) { + alg.init(&s->context); + esp32c3_resume_hash(s); + } +} + + +static uint64_t esp32c3_sha_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3ShaState *s = ESP32C3_SHA(opaque); + hwaddr index = 0; + + uint64_t r = 0; + switch (addr) { + case A_SHA_MODE: + r = s->mode; + break; + case A_SHA_BUSY: + /* SHA driver is never busy as calculation happens synchronously */ + r = 0; + break; + case A_SHA_DATE: + /* Hardcode the version control register for now */ + r = 0x20190402; + break; + case A_SHA_H_MEM ... A_SHA_M_MEM - 1: + index = (addr - A_SHA_H_MEM) / sizeof(uint32_t); + r = __builtin_bswap32(s->hash[index]); + break; + case A_SHA_M_MEM ... ESP32C3_SHA_REGS_SIZE - 1: + index = (addr - A_SHA_M_MEM) / sizeof(uint32_t); + r = s->message[index]; + break; + case A_SHA_DMA_BLOCK_NUM: + case A_SHA_IRQ_ENA: + default: +#if SHA_WARNING + warn_report("[ESP32-C3] SHA DMA and IRQ unsupported for now, ignoring...\n"); +#endif + break; + } + + return r; +} + + +static void esp32c3_sha_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3ShaState *s = ESP32C3_SHA(opaque); + hwaddr index = 0; + + switch (addr) { + case A_SHA_MODE: + /* Make sure the value is always between 0 and 2 as the real hardware doesn't + * accept a value of 3. Choose SHA-1 by default in that case. */ + s->mode = (value & 0b11) % 3; + break; + case A_SHA_START: + esp32c3_start_hash(s); + break; + case A_SHA_CONTINUE: + esp32c3_resume_hash(s); + break; + case A_SHA_H_MEM ... A_SHA_M_MEM - 1: + index = (addr - A_SHA_H_MEM) / sizeof(uint32_t); + s->hash[index] = (uint32_t) value; + break; + case A_SHA_M_MEM ... ESP32C3_SHA_REGS_SIZE - 1: + index = (addr - A_SHA_M_MEM) / sizeof(uint32_t); + s->message[index] = (uint32_t) value; + break; + case A_SHA_DMA_BLOCK_NUM: + case A_SHA_DMA_START: + case A_SHA_DMA_CONTINUE: + case A_SHA_CLEAR_IRQ: + case A_SHA_IRQ_ENA: + default: +#if SHA_WARNING + /* Unsupported for now, do nothing */ + warn_report("[SHA] DMA and IRQ unsupported for now, ignoring\n"); +#endif + break; + } +} + +static const MemoryRegionOps esp32c3_sha_ops = { + .read = esp32c3_sha_read, + .write = esp32c3_sha_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32c3_sha_init(Object *obj) +{ + ESP32C3ShaState *s = ESP32C3_SHA(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_sha_ops, s, + TYPE_ESP32C3_SHA, ESP32C3_SHA_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static const TypeInfo esp32c3_sha_info = { + .name = TYPE_ESP32C3_SHA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3ShaState), + .instance_init = esp32c3_sha_init, +}; + +static void esp32c3_sha_register_types(void) +{ + type_register_static(&esp32c3_sha_info); +} + +type_init(esp32c3_sha_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index a37105ab7494..3cd7719d2ede 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -137,7 +137,8 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'ssi_psram.c' )) softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files( - 'esp32c3_cache.c' + 'esp32c3_cache.c', + 'esp32c3_sha.c' )) if gcrypt.found() diff --git a/include/hw/misc/esp32c3_sha.h b/include/hw/misc/esp32c3_sha.h new file mode 100644 index 000000000000..960147e38fd0 --- /dev/null +++ b/include/hw/misc/esp32c3_sha.h @@ -0,0 +1,104 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32c3_reg.h" +#include "crypto/sha256_i.h" +#include "crypto/sha224_i.h" +#include "crypto/sha1_i.h" + +#define TYPE_ESP32C3_SHA "misc.esp32c3.sha" +#define ESP32C3_SHA(obj) OBJECT_CHECK(ESP32C3ShaState, (obj), TYPE_ESP32C3_SHA) + +#define ESP32C3_SHA_REGS_SIZE (0xC0) + + +/** + * @brief Size of the message array, in bytes + */ +#define ESP32C3_MESSAGE_SIZE 64 +#define ESP32C3_MESSAGE_WORDS (ESP32C3_MESSAGE_SIZE / sizeof(uint32_t)) + + +/** + * @brief Mode configuration for the SHA_MODE register. + */ +typedef enum { + ESP32C3_SHA_1_MODE = 0, + ESP32C3_SHA_224_MODE = 1, + ESP32C3_SHA_256_MODE = 2, +} ESP32C3ShaMode; + + +typedef union { + struct sha256_state sha256; + struct sha1_state sha1; +} ESP32C3HashContext; + + +typedef void (*hash_init)(void *); +typedef void (*hash_compress)(void *, const uint8_t*); + +typedef struct { + hash_init init; + /* For all types of hash, the message to "compress" must be 64-byte long (16 words of 32 bits) */ + hash_compress compress; + /* Length of the context in bytes */ + size_t len; +} ESP32C3HashAlg; + + +typedef struct ESP32C3ShaState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + /* SHA mode selected by the application */ + ESP32C3ShaMode mode; + /* Context for the hash calculation */ + ESP32C3HashContext context; + + /* Resulted hash value */ + uint32_t hash[8]; + /* User data value */ + uint32_t message[ESP32C3_MESSAGE_WORDS]; +} ESP32C3ShaState; + + +REG32(SHA_MODE, 0x000) + FIELD(SHA_MODE, MODE, 0, 3) + +REG32(SHA_T_STRING, 0x004) + +REG32(SHA_T_LENGTH, 0x008) + +REG32(SHA_DMA_BLOCK_NUM, 0x00C) + FIELD(SHA_DMA_BLOCK_NUM, DMA_BLOCK_NUM, 0, 6) + +REG32(SHA_START, 0x010) + FIELD(SHA_START, START, 1, 31) + +REG32(SHA_CONTINUE, 0x014) + FIELD(SHA_CONTINUE, CONTINUE, 1, 31) + +REG32(SHA_BUSY, 0x018) + FIELD(SHA_BUSY, BUSY_STATE, 0, 1) + +REG32(SHA_DMA_START, 0x01C) + FIELD(SHA_DMA_START, DMA_START, 0, 1) + +REG32(SHA_DMA_CONTINUE, 0x020) + FIELD(SHA_DMA_CONTINUE, DMA_CONTINUE, 0, 1) + +REG32(SHA_CLEAR_IRQ, 0x024) + FIELD(SHA_CLEAR_IRQ, CLEAR_INTERRUPT, 0, 1) + +REG32(SHA_IRQ_ENA, 0x028) + FIELD(SHA_IRQ_ENA, INTERRUPT_ENA, 0, 1) + +REG32(SHA_DATE, 0x02C) + FIELD(SHA_DATE, DATE, 0, 30) + +REG32(SHA_H_MEM, 0x040) + +REG32(SHA_M_MEM, 0x080) From 5949e8748bd76a95e4432eeb89e8d3e9e0c0c68c Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:48:59 +0800 Subject: [PATCH 39/56] hw/misc: implement ESP32-C3 USB Serial JTAG as a stub The module doesn't do much at the moment, it is used as a stub --- hw/misc/esp32c3_jtag.c | 80 ++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 3 +- include/hw/misc/esp32c3_jtag.h | 26 +++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 hw/misc/esp32c3_jtag.c create mode 100644 include/hw/misc/esp32c3_jtag.h diff --git a/hw/misc/esp32c3_jtag.c b/hw/misc/esp32c3_jtag.c new file mode 100644 index 000000000000..2d09c5d6cef6 --- /dev/null +++ b/hw/misc/esp32c3_jtag.c @@ -0,0 +1,80 @@ +/* + * ESP32-C3 USB Serial JTAG emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32c3_jtag.h" + + +static uint64_t esp32c3_jtag_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3UsbJtagState *s = ESP32C3_JTAG(opaque); + (void) s; + return 0; +} + +static void esp32c3_jtag_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) +{ + ESP32C3UsbJtagState *s = ESP32C3_JTAG(opaque); + (void) s; +} + +static const MemoryRegionOps esp32c3_jtag_ops = { + .read = esp32c3_jtag_read, + .write = esp32c3_jtag_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32c3_jtag_reset(DeviceState *dev) +{ + (void) dev; +} + +static void esp32c3_jtag_realize(DeviceState *dev, Error **errp) +{ + (void) dev; + (void) errp; +} + +static void esp32c3_jtag_init(Object *obj) +{ + ESP32C3UsbJtagState *s = ESP32C3_JTAG(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_jtag_ops, s, + TYPE_ESP32C3_JTAG, ESP32C3_JTAG_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void esp32c3_jtag_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_jtag_reset; + dc->realize = esp32c3_jtag_realize; +} + +static const TypeInfo esp32c3_jtag_info = { + .name = TYPE_ESP32C3_JTAG, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3UsbJtagState), + .instance_init = esp32c3_jtag_init, + .class_init = esp32c3_jtag_class_init +}; + +static void esp32c3_jtag_types(void) +{ + type_register_static(&esp32c3_jtag_info); +} + +type_init(esp32c3_jtag_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 3cd7719d2ede..aefee11fca7c 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -138,7 +138,8 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( )) softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files( 'esp32c3_cache.c', - 'esp32c3_sha.c' + 'esp32c3_sha.c', + 'esp32c3_jtag.c' )) if gcrypt.found() diff --git a/include/hw/misc/esp32c3_jtag.h b/include/hw/misc/esp32c3_jtag.h new file mode 100644 index 000000000000..8ac6ebb58453 --- /dev/null +++ b/include/hw/misc/esp32c3_jtag.h @@ -0,0 +1,26 @@ +/* + * ESP32-C3 USB Serial JTAG emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" + +#define TYPE_ESP32C3_JTAG "misc.esp32c3.usb_serial_jtag" +#define ESP32C3_JTAG(obj) OBJECT_CHECK(ESP32C3UsbJtagState, (obj), TYPE_ESP32C3_JTAG) + +#define ESP32C3_JTAG_REGS_SIZE (0x84) + + +typedef struct ESP32C3UsbJtagState { + SysBusDevice parent_object; + MemoryRegion iomem; +} ESP32C3UsbJtagState; + From edad3a1df7d4e6cca3d45a8ad4237a611bdff850 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:49:57 +0800 Subject: [PATCH 40/56] hw/misc: implement ESP32-C3 RTC CNTL registers --- hw/misc/esp32c3_rtc_cntl.c | 141 ++++++++ hw/misc/meson.build | 3 +- include/hw/misc/esp32c3_rtc_cntl.h | 508 +++++++++++++++++++++++++++++ 3 files changed, 651 insertions(+), 1 deletion(-) create mode 100644 hw/misc/esp32c3_rtc_cntl.c create mode 100644 include/hw/misc/esp32c3_rtc_cntl.h diff --git a/hw/misc/esp32c3_rtc_cntl.c b/hw/misc/esp32c3_rtc_cntl.c new file mode 100644 index 000000000000..0255d0fb821b --- /dev/null +++ b/hw/misc/esp32c3_rtc_cntl.c @@ -0,0 +1,141 @@ +/* + * ESP32-C3 RTC CNTL + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/misc/esp32c3_rtc_cntl.h" + + +#define RTCCNTL_DEBUG 0 +#define RTCCNTL_WARNING 0 + + +static uint64_t esp32c3_rtc_cntl_read(void* opaque, hwaddr addr, unsigned int size) +{ + ESP32C3RtcCntlState *s = ESP32C3_RTC_CNTL(opaque); + uint64_t r = 0; + + switch(addr) { + case A_RTC_CNTL_RTC_OPTIONS0: + r = s->options0; + break; + case A_RTC_CNTL_RTC_RESET_STATE: + r = ESP32C3_POWERON_RESET; + break; + case A_RTC_CNTL_RTC_STORE4: + /* XTAL frequency: 40MHz, must be in both upper and lower half-word */ + r = 0x00280028; + break; + default: +#if RTCCNTL_WARNING + /* Other registers are not supported yet */ + warn_report("[RTCCNTL] Unsupported read to %08lx\n", addr); +#endif + break; + } + + return r; +} + + +static void esp32c3_rtc_cntl_write(void* opaque, hwaddr addr, uint64_t value, unsigned int size) +{ + ESP32C3RtcCntlState *s = ESP32C3_RTC_CNTL(opaque); + const uint32_t c_value = value; + + switch(addr) { + case A_RTC_CNTL_RTC_OPTIONS0: + CLEAR_BIT(value, R_RTC_CNTL_RTC_OPTIONS0_SW_SYS_RST_SHIFT); + CLEAR_BIT(value, R_RTC_CNTL_RTC_OPTIONS0_SW_PROCPU_RST_SHIFT); + s->options0 = value; + /* Check if we have to reset the CPU/machine */ + if (FIELD_EX32(c_value, RTC_CNTL_RTC_OPTIONS0, SW_SYS_RST) || + FIELD_EX32(c_value, RTC_CNTL_RTC_OPTIONS0, SW_PROCPU_RST)) { + qemu_irq_raise(s->cpu_reset); + } + break; + default: +#if RTCCNTL_WARNING + /* Other registers are not supported yet */ + warn_report("[RTCCNTL] Unsupported write to %08lx (%08lx)\n", addr, value); +#endif + break; + } +} + + +static const MemoryRegionOps esp_rtc_cntl_ops = { + .read = esp32c3_rtc_cntl_read, + .write = esp32c3_rtc_cntl_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + + +static void esp32c3_rtc_cntl_reset(DeviceState *dev) +{ + ESP32C3RtcCntlState *s = ESP32C3_RTC_CNTL(dev); + s->options0 = 0; + qemu_irq_lower(s->cpu_reset); +} + + +static void esp32c3_rtc_cntl_realize(DeviceState *dev, Error **errp) +{ + ESP32C3RtcCntlState *s = ESP32C3_RTC_CNTL(dev); + esp32c3_rtc_cntl_reset(dev); + (void) s; +} + + +static void esp32c3_rtc_cntl_init(Object *obj) +{ + ESP32C3RtcCntlState *s = ESP32C3_RTC_CNTL(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp_rtc_cntl_ops, s, + TYPE_ESP32C3_RTC_CNTL, ESP32C3_RTC_CNTL_IO_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + + /* Initialize the GPIO that will notify the CPU to reset itself */ + qdev_init_gpio_out_named(DEVICE(s), &s->cpu_reset, ESP32C3_RTC_CPU_RESET_GPIO, 1); +} + + +static void esp32c3_rtc_cntl_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_rtc_cntl_reset; + dc->realize = esp32c3_rtc_cntl_realize; +} + + +static const TypeInfo esp32c3_rtc_cntl_info = { + .name = TYPE_ESP32C3_RTC_CNTL, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3RtcCntlState), + .instance_init = esp32c3_rtc_cntl_init, + .class_init = esp32c3_rtc_cntl_class_init +}; + + +static void esp32c3_rtc_cntl_register_types(void) +{ + type_register_static(&esp32c3_rtc_cntl_info); +} + + +type_init(esp32c3_rtc_cntl_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index aefee11fca7c..baf8c7608885 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -139,7 +139,8 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files( 'esp32c3_cache.c', 'esp32c3_sha.c', - 'esp32c3_jtag.c' + 'esp32c3_jtag.c', + 'esp32c3_rtc_cntl.c' )) if gcrypt.found() diff --git a/include/hw/misc/esp32c3_rtc_cntl.h b/include/hw/misc/esp32c3_rtc_cntl.h new file mode 100644 index 000000000000..c7e97ccead5e --- /dev/null +++ b/include/hw/misc/esp32c3_rtc_cntl.h @@ -0,0 +1,508 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" + +#include "hw/misc/esp32c3_reg.h" + +#define TYPE_ESP32C3_RTC_CNTL "misc.esp32c3.rtc_cntl" +#define ESP32C3_RTC_CNTL(obj) OBJECT_CHECK(ESP32C3RtcCntlState, (obj), TYPE_ESP32C3_RTC_CNTL) + +#define BIT_SET(reg, bit) ((reg) & BIT(bit)) +#define CLEAR_BIT(reg, bit) do { (reg) &= ~BIT(bit); } while(0) +#define SET_BIT(reg, bit) do { (reg) |= BIT(bit); } while(0) + +#define ESP32C3_RTC_CPU_RESET_GPIO "cpu-reset" + +/** + * Size of the I/O space for the RTC CTNL. + */ +#define ESP32C3_RTC_CNTL_IO_SIZE (A_RTC_CNTL_DATE + 4) + + +typedef struct ESP32C3RtcCntlState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + uint32_t options0; + qemu_irq cpu_reset; + +} ESP32C3RtcCntlState; + + +typedef enum ESP32C3ResetReason { + ESP32C3_NO_MEAN = 0, + ESP32C3_POWERON_RESET = 1, /**<1, Vbat power on reset*/ + ESP32C3_RTC_SW_SYS_RESET = 3, /**<3, Software reset digital core*/ + ESP32C3_DEEPSLEEP_RESET = 5, /**<5, Deep Sleep reset digital core*/ + ESP32C3_TG0WDT_SYS_RESET = 7, /**<7, Timer Group0 Watch dog reset digital core*/ + ESP32C3_TG1WDT_SYS_RESET = 8, /**<8, Timer Group1 Watch dog reset digital core*/ + ESP32C3_RTCWDT_SYS_RESET = 9, /**<9, RTC Watch dog Reset digital core*/ + ESP32C3_INTRUSION_RESET = 10, /**<10, Instrusion tested to reset CPU*/ + ESP32C3_TG0WDT_CPU_RESET = 11, /**<11, Time Group0 reset CPU*/ + ESP32C3_RTC_SW_CPU_RESET = 12, /**<12, Software reset CPU*/ + ESP32C3_RTCWDT_CPU_RESET = 13, /**<13, RTC Watch dog Reset CPU*/ + ESP32C3_RTCWDT_BROWN_OUT_RESET = 15, /**<15, Reset when the vdd voltage is not stable*/ + ESP32C3_RTCWDT_RTC_RESET = 16, /**<16, RTC Watch dog reset digital core and rtc module*/ + ESP32C3_TG1WDT_CPU_RESET = 17, /**<17, Time Group1 reset CPU*/ + ESP32C3_SUPER_WDT_RESET = 18, /**<18, super watchdog reset digital core and rtc module*/ + ESP32C3_GLITCH_RTC_RESET = 19, /**<19, glitch reset digital core and rtc module*/ + ESP32C3_EFUSE_RESET = 20, /**<20, efuse reset digital core*/ + ESP32C3_USB_UART_CHIP_RESET = 21, /**<21, usb uart reset digital core and rtc module */ + ESP32C3_USB_JTAG_CHIP_RESET = 22, /**<22, usb jtag reset digital core and rtc module*/ + ESP32C3_POWER_GLITCH_RESET = 23, /**<23, power glitch reset digital core and rtc module*/ +} ESP32C3ResetReason; + +REG32(RTC_CNTL_RTC_OPTIONS0, 0x0000) + FIELD(RTC_CNTL_RTC_OPTIONS0, SW_SYS_RST, 31, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, DG_WRAP_FORCE_NORST, 30, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, DG_WRAP_FORCE_RST, 29, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, XTL_FORCE_PU, 13, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, XTL_FORCE_PD, 12, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, BBPLL_FORCE_PU, 11, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, BBPLL_FORCE_PD, 10, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, BBPLL_I2C_FORCE_PU, 9, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, BBPLL_I2C_FORCE_PD, 8, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, BB_I2C_FORCE_PU, 7, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, BB_I2C_FORCE_PD, 6, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, SW_PROCPU_RST, 5, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, SW_APPCPU_RST, 4, 1) + FIELD(RTC_CNTL_RTC_OPTIONS0, SW_STALL_PROCPU_C0, 2, 2) + +REG32(RTC_CNTL_RTC_SLP_TIMER0, 0x0004) + FIELD(RTC_CNTL_RTC_SLP_TIMER0, SLP_VAL_LO, 0, 32) + +REG32(RTC_CNTL_RTC_SLP_TIMER1, 0x0008) + FIELD(RTC_CNTL_RTC_SLP_TIMER1, RTC_MAIN_TIMER_ALARM_EN, 16, 1) + FIELD(RTC_CNTL_RTC_SLP_TIMER1, SLP_VAL_HI, 0, 16) + +REG32(RTC_CNTL_RTC_TIME_UPDATE, 0x000C) + FIELD(RTC_CNTL_RTC_TIME_UPDATE, RTC_TIME_UPDATE, 31, 1) + FIELD(RTC_CNTL_RTC_TIME_UPDATE, TIMER_SYS_RST, 29, 1) + FIELD(RTC_CNTL_RTC_TIME_UPDATE, TIMER_XTL_OFF, 28, 1) + FIELD(RTC_CNTL_RTC_TIME_UPDATE, TIMER_SYS_STALL, 27, 1) + +REG32(RTC_CNTL_RTC_TIME_LOW0, 0x0010) + FIELD(RTC_CNTL_RTC_TIME_LOW0, RTC_TIMER_VALUE0_LOW, 0, 32) + +REG32(RTC_CNTL_RTC_TIME_HIGH0, 0x0014) + FIELD(RTC_CNTL_RTC_TIME_HIGH0, RTC_TIMER_VALUE0_HIGH, 0, 16) + +REG32(RTC_CNTL_RTC_STATE0, 0x0018) + FIELD(RTC_CNTL_RTC_STATE0, SLEEP_EN, 31, 1) + FIELD(RTC_CNTL_RTC_STATE0, SLP_REJECT, 30, 1) + FIELD(RTC_CNTL_RTC_STATE0, SLP_WAKEUP, 29, 1) + FIELD(RTC_CNTL_RTC_STATE0, SDIO_ACTIVE_IND, 28, 1) + FIELD(RTC_CNTL_RTC_STATE0, APB2RTC_BRIDGE_SEL, 22, 1) + FIELD(RTC_CNTL_RTC_STATE0, RTC_SLP_REJECT_CAUSE_CLR, 1, 1) + FIELD(RTC_CNTL_RTC_STATE0, RTC_SW_CPU_INT, 0, 1) + +REG32(RTC_CNTL_RTC_TIMER1, 0x001C) + FIELD(RTC_CNTL_RTC_TIMER1, PLL_BUF_WAIT, 24, 8) + FIELD(RTC_CNTL_RTC_TIMER1, XTL_BUF_WAIT, 14, 10) + FIELD(RTC_CNTL_RTC_TIMER1, CK8M_WAIT, 6, 8) + FIELD(RTC_CNTL_RTC_TIMER1, CPU_STALL_WAIT, 1, 5) + FIELD(RTC_CNTL_RTC_TIMER1, CPU_STALL_EN, 0, 1) + +REG32(RTC_CNTL_RTC_TIMER2, 0x0020) + FIELD(RTC_CNTL_RTC_TIMER2, MIN_TIME_CK8M_OFF, 24, 8) + +REG32(RTC_CNTL_RTC_TIMER3, 0x0024) + +REG32(RTC_CNTL_RTC_TIMER4, 0x0028) + +REG32(RTC_CNTL_RTC_TIMER5, 0x002C) + FIELD(RTC_CNTL_RTC_TIMER5, MIN_SLP_VAL, 8, 8) + +REG32(RTC_CNTL_RTC_TIMER6, 0x0030) + +REG32(RTC_CNTL_RTC_ANA_CONF, 0x0034) + FIELD(RTC_CNTL_RTC_ANA_CONF, PLL_I2C_PU, 31, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, CKGEN_I2C_PU, 30, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, RFRX_PBUS_PU, 28, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, TXRF_I2C_PU, 27, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, PVTMON_PU, 26, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, PLLA_FORCE_PU, 24, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, PLLA_FORCE_PD, 23, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, SAR_I2C_PU, 22, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, GLITCH_RST_EN, 20, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, RESET_POR_FORCE_PU, 19, 1) + FIELD(RTC_CNTL_RTC_ANA_CONF, RESET_POR_FORCE_PD, 18, 1) + +REG32(RTC_CNTL_RTC_RESET_STATE, 0x0038) + FIELD(RTC_CNTL_RTC_RESET_STATE, RTC_DRESET_MASK_PROCPU, 25, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, RTC_DRESET_MASK_APPCPU, 24, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, JTAG_RESET_FLAG_CLR_APPCPU, 23, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, JTAG_RESET_FLAG_CLR_PROCPU, 22, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, JTAG_RESET_FLAG_APPCPU, 21, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, JTAG_RESET_FLAG_PROCPU, 20, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, OCD_HALT_ON_RESET_PROCPU, 19, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, OCD_HALT_ON_RESET_APPCPU, 18, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, ALL_RESET_FLAG_CLR_APPCPU, 17, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, ALL_RESET_FLAG_CLR_PROCPU, 16, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, ALL_RESET_FLAG_APPCPU, 15, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, ALL_RESET_FLAG_PROCPU, 14, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, STAT_VECTOR_SEL_PROCPU, 13, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, STAT_VECTOR_SEL_APPCPU, 12, 1) + FIELD(RTC_CNTL_RTC_RESET_STATE, RESET_CAUSE_PROCPU, 0, 6) + +REG32(RTC_CNTL_RTC_WAKEUP_STATE, 0x003C) + FIELD(RTC_CNTL_RTC_WAKEUP_STATE, RTC_WAKEUP_ENA, 15, 17) + +REG32(RTC_CNTL_INT_ENA_RTC, 0x0040) + FIELD(RTC_CNTL_INT_ENA_RTC, RTC_BBPLL_CAL_INT_ENA, 20, 1) + FIELD(RTC_CNTL_INT_ENA_RTC, RTC_GLITCH_DET_INT_ENA, 19, 1) + FIELD(RTC_CNTL_INT_ENA_RTC, RTC_XTAL32K_DEAD_INT_ENA, 16, 1) + FIELD(RTC_CNTL_INT_ENA_RTC, RTC_SWD_INT_ENA, 15, 1) + FIELD(RTC_CNTL_INT_ENA_RTC, RTC_MAIN_TIMER_INT_ENA, 10, 1) + FIELD(RTC_CNTL_INT_ENA_RTC, RTC_BROWN_OUT_INT_ENA, 9, 1) + FIELD(RTC_CNTL_INT_ENA_RTC, RTC_WDT_INT_ENA, 3, 1) + FIELD(RTC_CNTL_INT_ENA_RTC, SLP_REJECT_INT_ENA, 1, 1) + FIELD(RTC_CNTL_INT_ENA_RTC, SLP_WAKEUP_INT_ENA, 0, 1) + +REG32(RTC_CNTL_INT_RAW_RTC, 0x0044) + FIELD(RTC_CNTL_INT_RAW_RTC, RTC_BBPLL_CAL_INT_RAW, 20, 1) + FIELD(RTC_CNTL_INT_RAW_RTC, RTC_GLITCH_DET_INT_RAW, 19, 1) + FIELD(RTC_CNTL_INT_RAW_RTC, RTC_XTAL32K_DEAD_INT_RAW, 16, 1) + FIELD(RTC_CNTL_INT_RAW_RTC, RTC_SWD_INT_RAW, 15, 1) + FIELD(RTC_CNTL_INT_RAW_RTC, RTC_MAIN_TIMER_INT_RAW, 10, 1) + FIELD(RTC_CNTL_INT_RAW_RTC, RTC_BROWN_OUT_INT_RAW, 9, 1) + FIELD(RTC_CNTL_INT_RAW_RTC, RTC_WDT_INT_RAW, 3, 1) + FIELD(RTC_CNTL_INT_RAW_RTC, SLP_REJECT_INT_RAW, 1, 1) + FIELD(RTC_CNTL_INT_RAW_RTC, SLP_WAKEUP_INT_RAW, 0, 1) + +REG32(RTC_CNTL_INT_ST_RTC, 0x0048) + FIELD(RTC_CNTL_INT_ST_RTC, RTC_BBPLL_CAL_INT_ST, 20, 1) + FIELD(RTC_CNTL_INT_ST_RTC, RTC_GLITCH_DET_INT_ST, 19, 1) + FIELD(RTC_CNTL_INT_ST_RTC, RTC_XTAL32K_DEAD_INT_ST, 16, 1) + FIELD(RTC_CNTL_INT_ST_RTC, RTC_SWD_INT_ST, 15, 1) + FIELD(RTC_CNTL_INT_ST_RTC, RTC_MAIN_TIMER_INT_ST, 10, 1) + FIELD(RTC_CNTL_INT_ST_RTC, RTC_BROWN_OUT_INT_ST, 9, 1) + FIELD(RTC_CNTL_INT_ST_RTC, RTC_WDT_INT_ST, 3, 1) + FIELD(RTC_CNTL_INT_ST_RTC, SLP_REJECT_INT_ST, 1, 1) + FIELD(RTC_CNTL_INT_ST_RTC, SLP_WAKEUP_INT_ST, 0, 1) + +REG32(RTC_CNTL_INT_CLR_RTC, 0x004C) + FIELD(RTC_CNTL_INT_CLR_RTC, RTC_BBPLL_CAL_INT_CLR, 20, 1) + FIELD(RTC_CNTL_INT_CLR_RTC, RTC_GLITCH_DET_INT_CLR, 19, 1) + FIELD(RTC_CNTL_INT_CLR_RTC, RTC_XTAL32K_DEAD_INT_CLR, 16, 1) + FIELD(RTC_CNTL_INT_CLR_RTC, RTC_SWD_INT_CLR, 15, 1) + FIELD(RTC_CNTL_INT_CLR_RTC, RTC_MAIN_TIMER_INT_CLR, 10, 1) + FIELD(RTC_CNTL_INT_CLR_RTC, RTC_BROWN_OUT_INT_CLR, 9, 1) + FIELD(RTC_CNTL_INT_CLR_RTC, RTC_WDT_INT_CLR, 3, 1) + FIELD(RTC_CNTL_INT_CLR_RTC, SLP_REJECT_INT_CLR, 1, 1) + FIELD(RTC_CNTL_INT_CLR_RTC, SLP_WAKEUP_INT_CLR, 0, 1) + +REG32(RTC_CNTL_RTC_STORE0, 0x0050) + FIELD(RTC_CNTL_RTC_STORE0, RTC_SCRATCH0, 0, 32) + +REG32(RTC_CNTL_RTC_STORE1, 0x0054) + FIELD(RTC_CNTL_RTC_STORE1, RTC_SCRATCH1, 0, 32) + +REG32(RTC_CNTL_RTC_STORE2, 0x0058) + FIELD(RTC_CNTL_RTC_STORE2, RTC_SCRATCH2, 0, 32) + +REG32(RTC_CNTL_RTC_STORE3, 0x005C) + FIELD(RTC_CNTL_RTC_STORE3, RTC_SCRATCH3, 0, 32) + +REG32(RTC_CNTL_RTC_EXT_XTL_CONF, 0x0060) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTL_EXT_CTR_EN, 31, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTL_EXT_CTR_LV, 30, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, RTC_XTAL32K_GPIO_SEL, 23, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, RTC_WDT_STATE, 20, 3) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, DAC_XTAL_32K, 17, 3) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XPD_XTAL_32K, 16, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, DRES_XTAL_32K, 13, 3) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, DGM_XTAL_32K, 10, 3) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, DBUF_XTAL_32K, 9, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, ENCKINIT_XTAL_32K, 8, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTAL32K_XPD_FORCE, 7, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTAL32K_AUTO_RETURN, 6, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTAL32K_AUTO_RESTART, 5, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTAL32K_AUTO_BACKUP, 4, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTAL32K_EXT_CLK_FO, 3, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTAL32K_WDT_RESET, 2, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTAL32K_WDT_CLK_FO, 1, 1) + FIELD(RTC_CNTL_RTC_EXT_XTL_CONF, XTAL32K_WDT_EN, 0, 1) + +REG32(RTC_CNTL_RTC_EXT_WAKEUP_CONF, 0x0064) + FIELD(RTC_CNTL_RTC_EXT_WAKEUP_CONF, GPIO_WAKEUP_FILTER, 31, 1) + +REG32(RTC_CNTL_RTC_SLP_REJECT_CONF, 0x0068) + FIELD(RTC_CNTL_RTC_SLP_REJECT_CONF, DEEP_SLP_REJECT_EN, 31, 1) + FIELD(RTC_CNTL_RTC_SLP_REJECT_CONF, LIGHT_SLP_REJECT_EN, 30, 1) + FIELD(RTC_CNTL_RTC_SLP_REJECT_CONF, RTC_SLEEP_REJECT_ENA, 12, 17) + +REG32(RTC_CNTL_RTC_CPU_PERIOD_CONF, 0x006C) + FIELD(RTC_CNTL_RTC_CPU_PERIOD_CONF, RTC_CPUPERIOD_SEL, 30, 2) + FIELD(RTC_CNTL_RTC_CPU_PERIOD_CONF, RTC_CPUSEL_CONF, 29, 1) + +REG32(RTC_CNTL_RTC_CLK_CONF, 0x0070) + FIELD(RTC_CNTL_RTC_CLK_CONF, ANA_CLK_RTC_SEL, 30, 2) + FIELD(RTC_CNTL_RTC_CLK_CONF, FAST_CLK_RTC_SEL, 29, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, XTAL_GLOBAL_FORCE_NOGATING, 28, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, XTAL_GLOBAL_FORCE_GATING, 27, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, CK8M_FORCE_PU, 26, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, CK8M_FORCE_PD, 25, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, CK8M_DFREQ, 17, 8) + FIELD(RTC_CNTL_RTC_CLK_CONF, CK8M_FORCE_NOGATING, 16, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, XTAL_FORCE_NOGATING, 15, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, CK8M_DIV_SEL, 12, 3) + FIELD(RTC_CNTL_RTC_CLK_CONF, DIG_CLK8M_EN, 10, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, DIG_CLK8M_D256_EN, 9, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, DIG_XTAL32K_EN, 8, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, ENB_CK8M_DIV, 7, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, ENB_CK8M, 6, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, CK8M_DIV, 4, 2) + FIELD(RTC_CNTL_RTC_CLK_CONF, CK8M_DIV_SEL_VLD, 3, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, EFUSE_CLK_FORCE_NOGATING, 2, 1) + FIELD(RTC_CNTL_RTC_CLK_CONF, EFUSE_CLK_FORCE_GATING, 1, 1) + +REG32(RTC_CNTL_RTC_SLOW_CLK_CONF, 0x0074) + FIELD(RTC_CNTL_RTC_SLOW_CLK_CONF, RTC_SLOW_CLK_NEXT_EDGE, 31, 1) + FIELD(RTC_CNTL_RTC_SLOW_CLK_CONF, RTC_ANA_CLK_DIV, 23, 8) + FIELD(RTC_CNTL_RTC_SLOW_CLK_CONF, RTC_ANA_CLK_DIV_VLD, 22, 1) + +REG32(RTC_CNTL_RTC_SDIO_CONF, 0x0078) + +REG32(RTC_CNTL_RTC_BIAS_CONF, 0x007C) + +REG32(RTC_CNTL_RTC, 0x0080) + FIELD(RTC_CNTL_RTC, RTC_REGULATOR_FORCE_PU, 31, 1) + FIELD(RTC_CNTL_RTC, RTC_REGULATOR_FORCE_PD, 30, 1) + FIELD(RTC_CNTL_RTC, RTC_DBOOST_FORCE_PU, 29, 1) + FIELD(RTC_CNTL_RTC, RTC_DBOOST_FORCE_PD, 28, 1) + FIELD(RTC_CNTL_RTC, SCK_DCAP, 14, 8) + FIELD(RTC_CNTL_RTC, DIG_REG_CAL_EN, 7, 1) + +REG32(RTC_CNTL_RTC_PWC, 0x0084) + FIELD(RTC_CNTL_RTC_PWC, RTC_PAD_FORCE_HOLD, 21, 1) + +REG32(RTC_CNTL_DIG_PWC, 0x0088) + FIELD(RTC_CNTL_DIG_PWC, DG_WRAP_PD_EN, 31, 1) + FIELD(RTC_CNTL_DIG_PWC, WIFI_PD_EN, 30, 1) + FIELD(RTC_CNTL_DIG_PWC, CPU_TOP_PD_EN, 29, 1) + FIELD(RTC_CNTL_DIG_PWC, DG_PERI_PD_EN, 28, 1) + FIELD(RTC_CNTL_DIG_PWC, BT_PD_EN, 27, 1) + FIELD(RTC_CNTL_DIG_PWC, CPU_TOP_FORCE_PU, 22, 1) + FIELD(RTC_CNTL_DIG_PWC, CPU_TOP_FORCE_PD, 21, 1) + FIELD(RTC_CNTL_DIG_PWC, DG_WRAP_FORCE_PU, 20, 1) + FIELD(RTC_CNTL_DIG_PWC, DG_WRAP_FORCE_PD, 19, 1) + FIELD(RTC_CNTL_DIG_PWC, WIFI_FORCE_PU, 18, 1) + FIELD(RTC_CNTL_DIG_PWC, WIFI_FORCE_PD, 17, 1) + FIELD(RTC_CNTL_DIG_PWC, RTC_FASTMEM_FORCE_LPU, 16, 1) + FIELD(RTC_CNTL_DIG_PWC, RTC_FASTMEM_FORCE_LPD, 15, 1) + FIELD(RTC_CNTL_DIG_PWC, DG_PERI_FORCE_PU, 14, 1) + FIELD(RTC_CNTL_DIG_PWC, DG_PERI_FORCE_PD, 13, 1) + FIELD(RTC_CNTL_DIG_PWC, BT_FORCE_PU, 12, 1) + FIELD(RTC_CNTL_DIG_PWC, BT_FORCE_PD, 11, 1) + FIELD(RTC_CNTL_DIG_PWC, LSLP_MEM_FORCE_PU, 4, 1) + FIELD(RTC_CNTL_DIG_PWC, LSLP_MEM_FORCE_PD, 3, 1) + FIELD(RTC_CNTL_DIG_PWC, VDD_SPI_PWR_FORCE, 2, 1) + FIELD(RTC_CNTL_DIG_PWC, VDD_SPI_PWR_DRV, 0, 2) + +REG32(RTC_CNTL_DIG_ISO, 0x008C) + FIELD(RTC_CNTL_DIG_ISO, DG_WRAP_FORCE_NOISO, 31, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_WRAP_FORCE_ISO, 30, 1) + FIELD(RTC_CNTL_DIG_ISO, WIFI_FORCE_NOISO, 29, 1) + FIELD(RTC_CNTL_DIG_ISO, WIFI_FORCE_ISO, 28, 1) + FIELD(RTC_CNTL_DIG_ISO, CPU_TOP_FORCE_NOISO, 27, 1) + FIELD(RTC_CNTL_DIG_ISO, CPU_TOP_FORCE_ISO, 26, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_PERI_FORCE_NOISO, 25, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_PERI_FORCE_ISO, 24, 1) + FIELD(RTC_CNTL_DIG_ISO, BT_FORCE_NOISO, 23, 1) + FIELD(RTC_CNTL_DIG_ISO, BT_FORCE_ISO, 22, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_PAD_FORCE_HOLD, 15, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_PAD_FORCE_UNHOLD, 14, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_PAD_FORCE_ISO, 13, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_PAD_FORCE_NOISO, 12, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_PAD_AUTOHOLD_EN, 11, 1) + FIELD(RTC_CNTL_DIG_ISO, CLR_DG_PAD_AUTOHOLD, 10, 1) + FIELD(RTC_CNTL_DIG_ISO, DG_PAD_AUTOHOLD, 9, 1) + +REG32(RTC_CNTL_RTC_WDTCONFIG0, 0x0090) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_EN, 31, 1) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_STG0, 28, 3) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_STG1, 25, 3) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_STG2, 22, 3) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_STG3, 19, 3) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_CPU_RESET_LENGTH, 16, 3) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_SYS_RESET_LENGTH, 13, 3) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_FLASHBOOT_MOD_EN, 12, 1) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_PROCPU_RESET_EN, 11, 1) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_APPCPU_RESET_EN, 10, 1) + FIELD(RTC_CNTL_RTC_WDTCONFIG0, WDT_PAUSE_IN_SLP, 9, 1) + +REG32(RTC_CNTL_RTC_WDTCONFIG1, 0x0094) + FIELD(RTC_CNTL_RTC_WDTCONFIG1, WDT_STG0_HOLD, 0, 32) + +REG32(RTC_CNTL_RTC_WDTCONFIG2, 0x0098) + FIELD(RTC_CNTL_RTC_WDTCONFIG2, WDT_STG1_HOLD, 0, 32) + +REG32(RTC_CNTL_RTC_WDTCONFIG3, 0x009C) + FIELD(RTC_CNTL_RTC_WDTCONFIG3, WDT_STG2_HOLD, 0, 32) + +REG32(RTC_CNTL_RTC_WDTCONFIG4, 0x00A0) + FIELD(RTC_CNTL_RTC_WDTCONFIG4, WDT_STG3_HOLD, 0, 32) + +REG32(RTC_CNTL_RTC_WDTFEED, 0x00A4) + FIELD(RTC_CNTL_RTC_WDTFEED, RTC_WDT_FEED, 31, 1) + +REG32(RTC_CNTL_RTC_WDTWPROTECT, 0x00A8) + FIELD(RTC_CNTL_RTC_WDTWPROTECT, WDT_WKEY, 0, 32) + +REG32(RTC_CNTL_RTC_SWD_CONF, 0x00AC) + FIELD(RTC_CNTL_RTC_SWD_CONF, SWD_AUTO_FEED_EN, 31, 1) + FIELD(RTC_CNTL_RTC_SWD_CONF, SWD_DISABLE, 30, 1) + FIELD(RTC_CNTL_RTC_SWD_CONF, SWD_FEED, 29, 1) + FIELD(RTC_CNTL_RTC_SWD_CONF, SWD_RST_FLAG_CLR, 28, 1) + FIELD(RTC_CNTL_RTC_SWD_CONF, SWD_SIGNAL_WIDTH, 18, 10) + FIELD(RTC_CNTL_RTC_SWD_CONF, SWD_BYPASS_RST, 17, 1) + FIELD(RTC_CNTL_RTC_SWD_CONF, SWD_FEED_INT, 1, 1) + FIELD(RTC_CNTL_RTC_SWD_CONF, SWD_RESET_FLAG, 0, 1) + +REG32(RTC_CNTL_RTC_SWD_WPROTECT, 0x00B0) + FIELD(RTC_CNTL_RTC_SWD_WPROTECT, SWD_WKEY, 0, 32) + +REG32(RTC_CNTL_RTC_SW_CPU_STALL, 0x00B4) + FIELD(RTC_CNTL_RTC_SW_CPU_STALL, SW_STALL_PROCPU_C1, 26, 6) + FIELD(RTC_CNTL_RTC_SW_CPU_STALL, SW_STALL_APPCPU_C1, 20, 6) + +REG32(RTC_CNTL_RTC_STORE4, 0x00B8) + FIELD(RTC_CNTL_RTC_STORE4, RTC_SCRATCH4, 0, 32) + +REG32(RTC_CNTL_RTC_STORE5, 0x00BC) + FIELD(RTC_CNTL_RTC_STORE5, RTC_SCRATCH5, 0, 32) + +REG32(RTC_CNTL_RTC_STORE6, 0x00C0) + FIELD(RTC_CNTL_RTC_STORE6, RTC_SCRATCH6, 0, 32) + +REG32(RTC_CNTL_RTC_STORE7, 0x00C4) + FIELD(RTC_CNTL_RTC_STORE7, RTC_SCRATCH7, 0, 32) + +REG32(RTC_CNTL_RTC_LOW_POWER_ST, 0x00C8) + FIELD(RTC_CNTL_RTC_LOW_POWER_ST, RTC_RDY_FOR_WAKEUP, 19, 1) + +REG32(RTC_CNTL_RTC_DIAG0, 0x00CC) + +REG32(RTC_CNTL_RTC_PAD_HOLD, 0x00D0) + FIELD(RTC_CNTL_RTC_PAD_HOLD, RTC_GPIO_PIN5_HOLD, 5, 1) + FIELD(RTC_CNTL_RTC_PAD_HOLD, RTC_GPIO_PIN4_HOLD, 4, 1) + FIELD(RTC_CNTL_RTC_PAD_HOLD, RTC_GPIO_PIN3_HOLD, 3, 1) + FIELD(RTC_CNTL_RTC_PAD_HOLD, RTC_GPIO_PIN2_HOLD, 2, 1) + FIELD(RTC_CNTL_RTC_PAD_HOLD, RTC_GPIO_PIN1_HOLD, 1, 1) + FIELD(RTC_CNTL_RTC_PAD_HOLD, RTC_GPIO_PIN0_HOLD, 0, 1) + +REG32(RTC_CNTL_DIG_PAD_HOLD, 0x00D4) + FIELD(RTC_CNTL_DIG_PAD_HOLD, DIG_PAD_HOLD, 0, 32) + +REG32(RTC_CNTL_RTC_BROWN_OUT, 0x00D8) + FIELD(RTC_CNTL_RTC_BROWN_OUT, RTC_BROWN_OUT_DET, 31, 1) + FIELD(RTC_CNTL_RTC_BROWN_OUT, BROWN_OUT_ENA, 30, 1) + FIELD(RTC_CNTL_RTC_BROWN_OUT, BROWN_OUT_CNT_CLR, 29, 1) + FIELD(RTC_CNTL_RTC_BROWN_OUT, BROWN_OUT_ANA_RST_EN, 28, 1) + FIELD(RTC_CNTL_RTC_BROWN_OUT, BROWN_OUT_RST_SEL, 27, 1) + FIELD(RTC_CNTL_RTC_BROWN_OUT, BROWN_OUT_RST_ENA, 26, 1) + FIELD(RTC_CNTL_RTC_BROWN_OUT, BROWN_OUT_RST_WAIT, 16, 10) + FIELD(RTC_CNTL_RTC_BROWN_OUT, BROWN_OUT_PD_RF_ENA, 15, 1) + FIELD(RTC_CNTL_RTC_BROWN_OUT, BROWN_OUT_CLOSE_FLASH_ENA, 14, 1) + +REG32(RTC_CNTL_RTC_TIME_LOW1, 0x00DC) + FIELD(RTC_CNTL_RTC_TIME_LOW1, RTC_TIMER_VALUE1_LOW, 0, 32) + +REG32(RTC_CNTL_RTC_TIME_HIGH1, 0x00E0) + FIELD(RTC_CNTL_RTC_TIME_HIGH1, RTC_TIMER_VALUE1_HIGH, 0, 16) + +REG32(RTC_CNTL_RTC_XTAL32K_CLK_FACTOR, 0x00E4) + FIELD(RTC_CNTL_RTC_XTAL32K_CLK_FACTOR, XTAL32K_CLK_FACTOR, 0, 32) + +REG32(RTC_CNTL_RTC_XTAL32K_CONF, 0x00E8) + FIELD(RTC_CNTL_RTC_XTAL32K_CONF, XTAL32K_STABLE_THRES, 28, 4) + FIELD(RTC_CNTL_RTC_XTAL32K_CONF, XTAL32K_WDT_TIMEOUT, 20, 8) + FIELD(RTC_CNTL_RTC_XTAL32K_CONF, XTAL32K_RESTART_WAIT, 4, 16) + FIELD(RTC_CNTL_RTC_XTAL32K_CONF, XTAL32K_RETURN_WAIT, 0, 4) + +REG32(RTC_CNTL_RTC_USB_CONF, 0x00EC) + FIELD(RTC_CNTL_RTC_USB_CONF, IO_MUX_RESET_DISABLE, 18, 1) + +REG32(RTC_CNTL_RTC_SLP_REJECT_CAUSE, 0x00F0) + FIELD(RTC_CNTL_RTC_SLP_REJECT_CAUSE, REJECT_CAUSE, 0, 18) + +REG32(RTC_CNTL_RTC_OPTION1, 0x00F4) + FIELD(RTC_CNTL_RTC_OPTION1, FORCE_DOWNLOAD_BOOT, 0, 1) + +REG32(RTC_CNTL_RTC_SLP_WAKEUP_CAUSE, 0x00F8) + FIELD(RTC_CNTL_RTC_SLP_WAKEUP_CAUSE, WAKEUP_CAUSE, 0, 17) + +REG32(RTC_CNTL_RTC_ULP_CP_TIMER_1, 0x00FC) + FIELD(RTC_CNTL_RTC_ULP_CP_TIMER_1, ULP_CP_TIMER_SLP_CYCLE, 8, 24) + +REG32(RTC_CNTL_INT_ENA_RTC_W1TS, 0x0100) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, RTC_BBPLL_CAL_INT_ENA_W1TS, 20, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, RTC_GLITCH_DET_INT_ENA_W1TS, 19, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, RTC_XTAL32K_DEAD_INT_ENA_W1TS, 16, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, RTC_SWD_INT_ENA_W1TS, 15, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, RTC_MAIN_TIMER_INT_ENA_W1TS, 10, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, RTC_BROWN_OUT_INT_ENA_W1TS, 9, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, RTC_WDT_INT_ENA_W1TS, 3, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, SLP_REJECT_INT_ENA_W1TS, 1, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TS, SLP_WAKEUP_INT_ENA_W1TS, 0, 1) + +REG32(RTC_CNTL_INT_ENA_RTC_W1TC, 0x0104) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, RTC_BBPLL_CAL_INT_ENA_W1TC, 20, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, RTC_GLITCH_DET_INT_ENA_W1TC, 19, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, RTC_XTAL32K_DEAD_INT_ENA_W1TC, 16, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, RTC_SWD_INT_ENA_W1TC, 15, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, RTC_MAIN_TIMER_INT_ENA_W1TC, 10, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, RTC_BROWN_OUT_INT_ENA_W1TC, 9, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, RTC_WDT_INT_ENA_W1TC, 3, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, SLP_REJECT_INT_ENA_W1TC, 1, 1) + FIELD(RTC_CNTL_INT_ENA_RTC_W1TC, SLP_WAKEUP_INT_ENA_W1TC, 0, 1) + +REG32(RTC_CNTL_RTC_CNTL_RETENTION_CTRL, 0x0108) + FIELD(RTC_CNTL_RTC_CNTL_RETENTION_CTRL, RETENTION_WAIT, 27, 5) + FIELD(RTC_CNTL_RTC_CNTL_RETENTION_CTRL, RETENTION_EN, 26, 1) + FIELD(RTC_CNTL_RTC_CNTL_RETENTION_CTRL, RETENTION_CLKOFF_WAIT, 22, 4) + FIELD(RTC_CNTL_RTC_CNTL_RETENTION_CTRL, RETENTION_DONE_WAIT, 19, 3) + FIELD(RTC_CNTL_RTC_CNTL_RETENTION_CTRL, RETENTION_CLK_SEL, 18, 1) + +REG32(RTC_CNTL_RTC_FIB_SEL, 0x010C) + FIELD(RTC_CNTL_RTC_FIB_SEL, RTC_FIB_SEL, 0, 3) + +REG32(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, 0x0110) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN0_WAKEUP_ENABLE, 31, 1) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN1_WAKEUP_ENABLE, 30, 1) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN2_WAKEUP_ENABLE, 29, 1) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN3_WAKEUP_ENABLE, 28, 1) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN4_WAKEUP_ENABLE, 27, 1) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN5_WAKEUP_ENABLE, 26, 1) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN0_INT_TYPE, 23, 3) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN1_INT_TYPE, 20, 3) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN2_INT_TYPE, 17, 3) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN3_INT_TYPE, 14, 3) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN4_INT_TYPE, 11, 3) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN5_INT_TYPE, 8, 3) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_PIN_CLK_GATE, 7, 1) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_WAKEUP_STATUS_CLR, 6, 1) + FIELD(RTC_CNTL_RTC_CNTL_GPIO_WAKEUP, RTC_GPIO_WAKEUP_STATUS, 0, 6) + +REG32(RTC_CNTL_RTC_CNTL_DBG_SEL, 0x0114) + +REG32(RTC_CNTL_RTC_CNTL_DBG_MAP, 0x0118) + +REG32(RTC_CNTL_RTC_CNTL_SENSOR_CTRL, 0x011C) + FIELD(RTC_CNTL_RTC_CNTL_SENSOR_CTRL, FORCE_XPD_SAR, 30, 2) + FIELD(RTC_CNTL_RTC_CNTL_SENSOR_CTRL, SAR2_PWDET_CCT, 27, 3) + +REG32(RTC_CNTL_RTC_CNTL_DBG_SAR_SEL, 0x0120) + FIELD(RTC_CNTL_RTC_CNTL_DBG_SAR_SEL, SAR_DEBUG_SEL, 27, 5) + +REG32(RTC_CNTL_RTC_CNTL_PG_CTRL, 0x0124) + FIELD(RTC_CNTL_RTC_CNTL_PG_CTRL, POWER_GLITCH_EN, 31, 1) + FIELD(RTC_CNTL_RTC_CNTL_PG_CTRL, POWER_GLITCH_EFUSE_SEL, 30, 1) + FIELD(RTC_CNTL_RTC_CNTL_PG_CTRL, POWER_GLITCH_FORCE_PU, 29, 1) + FIELD(RTC_CNTL_RTC_CNTL_PG_CTRL, POWER_GLITCH_FORCE_PD, 28, 1) + FIELD(RTC_CNTL_RTC_CNTL_PG_CTRL, POWER_GLITCH_DSENSE, 26, 2) + +REG32(RTC_CNTL_DATE, 0x01fc) From a8a86ed50b117d2ed822c72ba27af1ba5a6aa7d0 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:54:53 +0800 Subject: [PATCH 41/56] hw/nvram: implement ESP32-C3 eFuses --- hw/nvram/esp32c3_efuse.c | 526 +++++++++++++++++++++++++++++ hw/nvram/meson.build | 1 + include/hw/nvram/esp32c3_efuse.h | 552 +++++++++++++++++++++++++++++++ 3 files changed, 1079 insertions(+) create mode 100644 hw/nvram/esp32c3_efuse.c create mode 100644 include/hw/nvram/esp32c3_efuse.h diff --git a/hw/nvram/esp32c3_efuse.c b/hw/nvram/esp32c3_efuse.c new file mode 100644 index 000000000000..86b16b1b2540 --- /dev/null +++ b/hw/nvram/esp32c3_efuse.c @@ -0,0 +1,526 @@ +/* + * ESP32-C3 eFuse emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qapi/error.h" +#include "qapi/qmp/qdict.h" +#include "qemu/error-report.h" +#include "sysemu/sysemu.h" +#include "chardev/char-fe.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/nvram/esp32c3_efuse.h" + + +#define EFUSE_DEBUG 0 + + +#define EFUSE_DEFAULT_FILENAME "qemu_efuses.bin" + +/** + * @brief Specify the delay, in us of a a write or read operation, this will only be used to simulate + * the delay the real efuses actually take on real hardware. + */ +#define EFUSE_OPERATION_DELAY_US 1000 + + +static uint64_t esp32c3_efuse_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3EfuseState *s = ESP32C3_EFUSE(opaque); + uint8_t *content_8 = ((uint8_t*) &s->efuses) + addr; + uint16_t *content_16 = (uint16_t*) content_8; + uint32_t *content_32 = (uint32_t*) content_8; + + assert(addr < sizeof(s->efuses)); + + if (size == 1) { + return *content_8; + } else if (size == 2) { + return *content_16; + } else { + return *content_32; + } +} + +/** + * @brief Return the start offset in the ESP32C3EfuseRegs structure of the given block. + */ +static int esp32c3_offset_of_block(int block_num) +{ + const int offsets[] = { + ESP32C3_EFUSE_BLOCK0_ADDR, + ESP32C3_EFUSE_BLOCK1_ADDR, + ESP32C3_EFUSE_BLOCK2_ADDR, + ESP32C3_EFUSE_BLOCK3_ADDR, + ESP32C3_EFUSE_BLOCK4_ADDR, + ESP32C3_EFUSE_BLOCK5_ADDR, + ESP32C3_EFUSE_BLOCK6_ADDR, + ESP32C3_EFUSE_BLOCK7_ADDR, + ESP32C3_EFUSE_BLOCK8_ADDR, + ESP32C3_EFUSE_BLOCK9_ADDR, + ESP32C3_EFUSE_BLOCK10_ADDR, + }; + + assert(block_num < sizeof(offsets)/sizeof(int)); + return offsets[block_num]; +} + + +/** + * @brief Hide the protected efuses by overwriting them with 0s, this function shall be called after + * calling `esp32c3_efuse_read`. + */ +static void esp32c3_hide_protected_block(ESP32C3EfuseState *s) +{ + uint32_t rd_protection = s->efuses.rd_repeat_data0.rd_dis; + /* Only the BLOCK4 and upwards can be protected */ + int block_num = 4; + + while (rd_protection != 0) { + if (rd_protection & 1) { + /* Get the offset of the block in the ESP32C3EfuseRegs structure */ + const int offset = esp32c3_offset_of_block(block_num); + uint8_t* from = ((uint8_t*) &s->efuses) + offset; + /* The blocks that can be protected are all 32-byte long */ + memset(from, 0, 32); + } + rd_protection >>= 1; + block_num++; + } +} + + +/** + * @brief Load the efuses value from the block device (file) + */ +static void esp32c3_efuse_reload_from_blk(ESP32C3EfuseState *s) +{ + /* In theory, there are 4096 bits of efuses, in practice, the memory space allocated for + * efuses stops at &rd_repeat_err0. */ + const uint32_t size = offsetof(ESP32C3EfuseRegs, rd_repeat_err0) - offsetof(ESP32C3EfuseRegs, rd_wr_dis); + + /* Load the efuses from the block device file (or mirror) */ + if (s->blk) { + + /* Load the file content inside the structure, starting at efuse rd_wr_dis */ + const int ret = blk_pread(s->blk, 0, size, &s->efuses.rd_wr_dis, 0); + if (ret < 0) { + error_report("%s: failed to read the block device (%d)", __func__, ret); + } + + } else { + + assert(s->mirror); + memcpy(&s->efuses.rd_wr_dis, s->mirror, size); + + } +} + +/** + * @brief Get a mask of the protected bits for BLOCK0. + * A bit set to 1 marks a protected bit whereas a 0 marks an unprotected bit. + * + * @param wr_dis Write-disable register + * @param block0_mask Mask containing exactly ESP32C3_EFUSE_BLOCK0_WORDS words that will + * be filled with the masks described above. + */ +static void esp32c3_efuse_get_block0_protected_mask(uint32_t wr_dis, uint32_t *block0_mask) +{ + /* Define the constants that for each bit of wr_dis represent the word index they affect + * and the bits they protect */ + const struct { + uint32_t index; + uint32_t mask; + } protect_map[32] = { + [0] = { 1, 0x0000007f }, /* Bit 0: protects rd_repeat_data0 (index 1), rd_dis bits */ + /* Bit 1 unused */ + [2] = { 1, 0x0018df00 }, + [3] = { 2, 0x00030000 }, + [4] = { 2, 0x001c0000 }, + [5] = { 2, 0x00200000 }, + [6] = { 2, 0x00400000 }, + [7] = { 2, 0x00800000 }, + [8] = { 2, 0x0f000000 }, + [9] = { 2, 0xf0000000 }, + [10] = { 3, 0x0000000f }, + [11] = { 3, 0x000000f0 }, + [12] = { 3, 0x00000f00 }, + [13] = { 3, 0x0000f000 }, + /* Bit 14 unused */ + [15] = { 3, 0x00100000 }, + [16] = { 3, 0x00200000 }, + /* Bit 17 unused */ + [18] = { 4, 0x3fffe0f5 }, /* TODO: Make sure that bit 18 also protects EFUSE_FLASH_TPUW, omitted for now */ + [19] = { 4, 0x80000000 }, + /* bit 20 to 29 included don't affect BLOCK0 fields */ + [30] = { 1, 0x06000000 }, + [31] = { 1, 0x00070000 }, + }; + + memset(block0_mask, 0, ESP32C3_EFUSE_BLOCK0_WORDS * sizeof(uint32_t)); + + /* Go through all the bits of the write-disable mask and set the appropriate mask if the bit + * is set. Ignore bits from 20 to 29 included which are not about BLOCK 0 protection. */ + for (uint_fast32_t i = 0; i <= 31; i++) { + if ((i >= 20 && i <= 29) || (wr_dis & BIT(i)) == 0) { + continue; + } + /* Bit is set and within range */ + const uint32_t index = protect_map[i].index; + const uint32_t mask = protect_map[i].mask; + block0_mask[index] |= mask; + } +} + + +/** + * @brief Write a given efuses block to the block device (file) if not protected. + * Returns true if the block was flashed successfully, false else. + */ +static bool esp32c3_efuse_write_to_blk(ESP32C3EfuseState *s, const int block) +{ + const int size = esp32c3_efuse_block_size(block); + bool protected = false; + /* Mask of protected bit for each word of a BLOCK, only used when writing BLOCK0 */ + uint32_t block_mask[ESP32C3_EFUSE_PGM_DATA_COUNT] = { 0 }; + + /* If the block to protect is not BLOCK0 the check is rather simple */ + if (block != 0) { + assert(block <= 10); + /* BLOCK1 protection is bit 20, BLOCK2 protection is bit 21, etc... */ + const int offset = 19 + block; + /* If the bit is 1, protection is enabled, we cannot write */ + protected = (s->efuses.rd_wr_dis >> offset) & 1; + } else { + /* BLOCK0 protection is done on a bit granularity, so for each word that composes it + * get mask where 1 represents a protected bit, and 0 represents an unprotected bit */ + esp32c3_efuse_get_block0_protected_mask(s->efuses.rd_wr_dis, block_mask); + } + + if (!protected) { + /* Get the offset of the block in the ESP32C3EfuseRegs structure! + * Subtract the offset of the BLOCK0 to get the offset of our block in the + * binary file (blk). + * The offset in struct must be in 32-bit words */ + const uint32_t offset_in_struct = esp32c3_offset_of_block(block) / sizeof(uint32_t); + /* Offset in file must be in bytes */ + const uint32_t offset_in_file = esp32c3_offset_of_block(block) - esp32c3_offset_of_block(0); + + /* Generate the actual data to write to the file. Indeed, the programmed bits (1) shall + * NOT be programmed to 0 as on real hardware an efuse cannot be reverted. + * To do so, OR the content to burn with the existing content so that the 1s are never erased. */ + uint32_t *efuses = (uint32_t*) &s->efuses; + uint32_t real_data[ESP32C3_EFUSE_PGM_DATA_COUNT]; + + for (int i = 0; i < ESP32C3_EFUSE_PGM_DATA_COUNT; i++) { + /* Offset of pgm_data is 0, let's use efuses[i] to retrieve the data. + * efuses[i] represents the new value, efuses[offset_in_struct + i] represents the old value, + * block_mask represents the protection, with 1 marking a bit as protected. + * As such, the final result of an efuse value is: + * Y = old_value | (~block_mask & new_value) */ + real_data[i] = efuses[offset_in_struct + i] | (~block_mask[i] & efuses[i]); + } + + /* Write the new block data to the file (or RAM) */ + if (s->blk) { + + const int ret = blk_pwrite(s->blk, offset_in_file, size, real_data, 0); + if (ret < 0) { + error_report("%s: failed to write efuses to the block device (%d)", __func__, ret); + } + + } else { + + assert(s->mirror); + memcpy(s->mirror + offset_in_file, real_data, size); + + } + } + + /* Writing is a success if the block is not protected */ + return !protected; +} + + +/** + * @brief Callback called when the QEMU timer reaches its limit. + * It will set the raw status of the efuse component. If the requested operation was a read, + * it will perform the read from the binary file (blk) here. + */ +static void esp32c3_efuse_timer_cb(void *opaque) +{ + ESP32C3EfuseState *s = ESP32C3_EFUSE(opaque); + + /* To make sure the command register did not change between the moment the operation was scheduled + * and the moment the callback was triggered, restore its value to its original one. (mirror) + * In any case, it will be set to 0 at the end of this function */ + s->efuses.cmd.val = s->op_cmd_mirror; + + /* No need to check the opcode again */ + if (s->efuses.cmd.read_cmd) { + esp32c3_efuse_reload_from_blk(s); + esp32c3_hide_protected_block(s); + s->efuses.int_raw.read_done = 1; + } else { + assert(s->efuses.cmd.pgm_cmd); + s->efuses.int_raw.pgm_done = 1; + } + + /* In any case, reset the command register to show that the operation is finished */ + s->efuses.cmd.val = 0; + + /* Set the interrupt bits, if any is 1, trigger an interrupt */ + s->efuses.int_st.val = s->efuses.int_ena.val | s->efuses.int_raw.val; + if (s->efuses.int_st.val) { + qemu_irq_raise(s->irq); + } +} + + +/** + * @brief Start ESP32C3EfuseState's timer to simulate the efuse operation delay + */ +static void esp32c3_efuse_op_timer_start(ESP32C3EfuseState *s) +{ + const uint64_t ns_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + const uint64_t interval_ns = EFUSE_OPERATION_DELAY_US * 1000; + timer_mod_anticipate_ns(&s->op_timer, ns_now + interval_ns); +} + + +static void esp32c3_efuse_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3EfuseState *s = ESP32C3_EFUSE(opaque); + /* Address of the register to write if we consider efuses as an array of bytes */ + uint8_t *content_8 = ((uint8_t*) &s->efuses) + addr; + uint16_t *content_16 = (uint16_t*) content_8; + uint32_t *content_32 = (uint32_t*) content_8; + +#if EFUSE_DEBUG + info_report("[EFUSE] Writing to 0x%08lx = 0x%08lx (size: %d)\n", addr, value, size); +#endif + + /* Check if the programming cmd block is being written */ + if (addr == offsetof(ESP32C3EfuseRegs, cmd)) { + + s->efuses.cmd.val = (uint32_t) value; + + /* The command bit and the opcode will be check by the underlying function */ + if (esp32c3_efuse_is_read_cmd(s)) { + + /* Save the register value and schedule a timer to simulate real efuse loading delay, + * the copy will be done in the callback. */ + s->op_cmd_mirror = (uint32_t) value; + esp32c3_efuse_op_timer_start(s); + + } else if (esp32c3_efuse_is_write_cmd(s)) { + + const bool success = esp32c3_efuse_write_to_blk(s, s->efuses.cmd.blk_num); + + if (success) { + /* Same as for the read, schedule the timer and perform the actual transfer once it elapsed */ + s->op_cmd_mirror = (uint32_t) value; + esp32c3_efuse_op_timer_start(s); + } else { + s->efuses.cmd.val = 0; + s->op_cmd_mirror = 0; + } + } else { + s->efuses.cmd.val = 0; + } + + return; + } + + /* The first registers, up to rd_wr_dis excluded, can be written to freely */ + if (addr < offsetof(ESP32C3EfuseRegs, rd_wr_dis)) + { + if (size == 1) { + *content_8 = value & 0xff; + } else if (size == 2) { + *content_16 = value & 0xffff; + } else { + *content_32 = value; + } + + return; + } + + /* Treat the interrupt-related cases separately */ + const uint32_t former_status = s->efuses.int_st.val; + + switch (addr) { + case offsetof(ESP32C3EfuseRegs, int_clr): + /* Only clear the bits that are set to 1 in the value */ + s->efuses.int_raw.val &= ((~value) & 0b11); + break; + case offsetof(ESP32C3EfuseRegs, int_raw): + s->efuses.int_raw.val = 0; + break; + case offsetof(ESP32C3EfuseRegs, int_ena): + s->efuses.int_ena.val = value & 0b11; + break; + + /* For debugging purposes */ + case offsetof(ESP32C3EfuseRegs, dbg_erase_all): + { +#if EFUSE_DEBUG + info_report("[EFUSE] erasing all efuses!\n"); +#endif + uint32_t size = offsetof(ESP32C3EfuseRegs, rd_repeat_err0) - offsetof(ESP32C3EfuseRegs, rd_wr_dis); + memset(&s->efuses.rd_wr_dis, 0, size); + + if (s->blk) { + int ret = blk_pwrite(s->blk, 0, size, &s->efuses.rd_wr_dis, 0); + if (ret != 0) { + error_report("ERROR WRITING FILE: %d\n", ret); + exit(1); + } + } else { + + assert(s->mirror); + memset(s->mirror, 0, ESP32C3_EFUSE_BYTE_COUNT); + } + } + return; + + case offsetof(ESP32C3EfuseRegs, clk): + case offsetof(ESP32C3EfuseRegs, conf): + case offsetof(ESP32C3EfuseRegs, dac_conf): + case offsetof(ESP32C3EfuseRegs, rd_tim_conf): + case offsetof(ESP32C3EfuseRegs, wr_tim_conf1): + case offsetof(ESP32C3EfuseRegs, wr_tim_conf2): + /* Make sure we write these registers with a 32-bit access */ + assert(size >= 4); + *content_32 = value; + /* Fall-through */ + + /* The other registers are read-only */ + default: + return; + } + + /* Check if any interrupt needs to be triggered or, on the contrary, lowered */ + const uint32_t new_status = (s->efuses.int_ena.val | s->efuses.int_raw.val) & 0b11; + s->efuses.int_st.val = new_status; + + if (former_status != new_status) { + qemu_set_irq(s->irq, new_status ? 1 : 0); + } +} + + +static const MemoryRegionOps esp32c3_efuse_ops = { + .read = esp32c3_efuse_read, + .write = esp32c3_efuse_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + + +static void esp32c3_efuse_reset(DeviceState *dev) +{ + ESP32C3EfuseState *s = ESP32C3_EFUSE(dev); + timer_del(&s->op_timer); + qemu_irq_lower(s->irq); + esp32c3_efuse_reload_from_blk(s); + esp32c3_hide_protected_block(s); +} + +static void esp32c3_efuse_realize(DeviceState *dev, Error **errp) +{ + ESP32C3EfuseState *s = ESP32C3_EFUSE(dev); + const char* error_msg = NULL; + + /* If no file was given as efuses, create a temporary one (in RAM). */ + if (s->blk == NULL) { + s->mirror = g_malloc(ESP32C3_EFUSE_BYTE_COUNT); + if (s->mirror == NULL) { + error_msg = "failed to allocate memory for efuses"; + goto error; + } + + memset(s->mirror, 0, ESP32C3_EFUSE_BYTE_COUNT); + + /* Set the chip revision to v0.3 and write it to the file */ + s->efuses.rd_mac_spi_sys_3.wafer_version_minor_low = 3; + + /* No need to rewrite the all the efuses, rd_mac_spi_sys_3 is enough */ + const uint32_t offset = offsetof(ESP32C3EfuseRegs, rd_mac_spi_sys_3) - esp32c3_offset_of_block(0); + *((uint32_t*) (s->mirror + offset)) = s->efuses.rd_mac_spi_sys_3.val; + + } else { + /* A block was given as a parameter, open it in READ/WRITE */ + if (!blk_supports_write_perm(s->blk)) { + error_msg = "block device is not writeable or does not exist"; + goto error; + } + + uint64_t perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE; + int ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, NULL); + if (ret != 0) { + error_msg = "failed to set permission"; + goto error; + } + + esp32c3_efuse_reset((DeviceState*) s); + } + + return; +error: + error_setg(errp, "%s: %s", __func__, error_msg); +} + +static void esp32c3_efuse_init(Object *obj) +{ + ESP32C3EfuseState *s = ESP32C3_EFUSE(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_efuse_ops, s, + TYPE_ESP32C3_EFUSE, ESP32C3_EFUSE_IO_RANGE_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + + timer_init_ns(&s->op_timer, QEMU_CLOCK_VIRTUAL, esp32c3_efuse_timer_cb, s); +} + +static Property esp32c3_efuse_properties[] = { + DEFINE_PROP_DRIVE("drive", ESP32C3EfuseState, blk), + DEFINE_PROP_END_OF_LIST(), +}; + +static void esp32c3_efuse_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_efuse_reset; + dc->realize = esp32c3_efuse_realize; + device_class_set_props(dc, esp32c3_efuse_properties); +} + +static const TypeInfo esp32c3_efuse_info = { + .name = TYPE_ESP32C3_EFUSE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3EfuseState), + .instance_init = esp32c3_efuse_init, + .class_init = esp32c3_efuse_class_init +}; + +static void esp32c3_efuse_register_types(void) +{ + type_register_static(&esp32c3_efuse_info); +} + +type_init(esp32c3_efuse_register_types) diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index 123dbc9555f5..3a3c1e11192a 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -12,6 +12,7 @@ softmmu_ss.add(when: 'CONFIG_MAC_NVRAM', if_true: files('mac_nvram.c')) softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_otp.c')) softmmu_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_nvm.c')) softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files('esp32_efuse.c')) +softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_CRC', if_true: files('xlnx-efuse-crc.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE', if_true: files('xlnx-efuse.c')) softmmu_ss.add(when: 'CONFIG_XLNX_EFUSE_VERSAL', if_true: files( diff --git a/include/hw/nvram/esp32c3_efuse.h b/include/hw/nvram/esp32c3_efuse.h new file mode 100644 index 000000000000..fe43b244fad4 --- /dev/null +++ b/include/hw/nvram/esp32c3_efuse.h @@ -0,0 +1,552 @@ +/* + * ESP32-C3 eFuse emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32c3_reg.h" +#include "sysemu/block-backend.h" + +#define TYPE_ESP32C3_EFUSE "nvram.esp32c3.efuse" +#define ESP32C3_EFUSE(obj) OBJECT_CHECK(ESP32C3EfuseState, (obj), TYPE_ESP32C3_EFUSE) + +#define ESP32C3_EFUSE_IO_RANGE_SIZE (sizeof(ESP32C3EfuseRegs)) + +/** + * Size of the efuses in bytes on the ESP32C3 + */ +#define ESP32C3_EFUSE_BYTE_COUNT (4096/4) + +/** + * Number of data registers used when programming efuses + */ +#define ESP32C3_EFUSE_PGM_DATA_COUNT 8 + +/** + * Number of check registers used when programming efuses + */ +#define ESP32C3_EFUSE_PGM_CHECK_COUNT 3 + +/** + * Start address of the different BLOCKs in the ESP32C3EfuseRegs structure + */ +#define ESP32C3_EFUSE_BLOCK0_ADDR 0x002c +#define ESP32C3_EFUSE_BLOCK1_ADDR 0x0044 +#define ESP32C3_EFUSE_BLOCK2_ADDR 0x005c +#define ESP32C3_EFUSE_BLOCK3_ADDR 0x007c +#define ESP32C3_EFUSE_BLOCK4_ADDR 0x009c +#define ESP32C3_EFUSE_BLOCK5_ADDR 0x00bc +#define ESP32C3_EFUSE_BLOCK6_ADDR 0x00dc +#define ESP32C3_EFUSE_BLOCK7_ADDR 0x00fc +#define ESP32C3_EFUSE_BLOCK8_ADDR 0x011c +#define ESP32C3_EFUSE_BLOCK9_ADDR 0x013c +#define ESP32C3_EFUSE_BLOCK10_ADDR 0x015c + + +/** + * Size of BLOCK0 in 32-bit word unit + */ +#define ESP32C3_EFUSE_BLOCK0_WORDS 6 + +/** + * Magic values for write and read operations + */ +#define EFUSE_WRITE_OPCODE 0x5A5A +#define EFUSE_READ_OPCODE 0x5AA5 + + +/* Structure definition taken from `esp32c3/soc/efuse_struct.h` and re-adapted with few arrays */ +struct ESP32C3EfuseRegs { + uint32_t pgm_data[ESP32C3_EFUSE_PGM_DATA_COUNT]; /*Registers that stores data to be programmed.*/ + uint32_t pgm_check[ESP32C3_EFUSE_PGM_CHECK_COUNT]; /*Registers that stores the RS code to be programmed.*/ + uint32_t rd_wr_dis; /*BLOCK0 data register $n.*/ + union { + struct { + uint32_t rd_dis: 7; /*The value of RD_DIS.*/ + uint32_t rpt4_reserved5: 1; /*Reserved*/ + uint32_t dis_icache: 1; /*The value of DIS_ICACHE.*/ + uint32_t dis_usb_jtag: 1; /*The value of DIS_USB_JTAG.*/ + uint32_t dis_download_icache: 1; /*The value of DIS_DOWNLOAD_ICACHE.*/ + uint32_t dis_usb_device: 1; /*The value of DIS_USB_DEVICE.*/ + uint32_t dis_force_download: 1; /*The value of DIS_FORCE_DOWNLOAD.*/ + uint32_t dis_usb: 1; /*The value of DIS_USB.*/ + uint32_t dis_can: 1; /*The value of DIS_CAN.*/ + uint32_t jtag_sel_enable: 1; /*The value of JTAG_SEL_ENABLE.*/ + uint32_t soft_dis_jtag: 3; /*The value of SOFT_DIS_JTAG.*/ + uint32_t dis_pad_jtag: 1; /*The value of DIS_PAD_JTAG.*/ + uint32_t dis_download_manual_encrypt: 1; /*The value of DIS_DOWNLOAD_MANUAL_ENCRYPT.*/ + uint32_t usb_drefh: 2; /*The value of USB_DREFH.*/ + uint32_t usb_drefl: 2; /*The value of USB_DREFL.*/ + uint32_t usb_exchg_pins: 1; /*The value of USB_EXCHG_PINS.*/ + uint32_t vdd_spi_as_gpio: 1; /*The value of VDD_SPI_AS_GPIO.*/ + uint32_t btlc_gpio_enable: 2; /*The value of BTLC_GPIO_ENABLE.*/ + uint32_t powerglitch_en: 1; /*The value of POWERGLITCH_EN.*/ + uint32_t power_glitch_dsense: 2; /*The value of POWER_GLITCH_DSENSE.*/ + }; + uint32_t val; + } rd_repeat_data0; + union { + struct { + uint32_t rpt4_reserved2: 16; /*Reserved.*/ + uint32_t wdt_delay_sel: 2; /*The value of WDT_DELAY_SEL.*/ + uint32_t spi_boot_crypt_cnt: 3; /*The value of SPI_BOOT_CRYPT_CNT.*/ + uint32_t secure_boot_key_revoke0: 1; /*The value of SECURE_BOOT_KEY_REVOKE0.*/ + uint32_t secure_boot_key_revoke1: 1; /*The value of SECURE_BOOT_KEY_REVOKE1.*/ + uint32_t secure_boot_key_revoke2: 1; /*The value of SECURE_BOOT_KEY_REVOKE2.*/ + uint32_t key_purpose_0: 4; /*The value of KEY_PURPOSE_0.*/ + uint32_t key_purpose_1: 4; /*The value of KEY_PURPOSE_1.*/ + }; + uint32_t val; + } rd_repeat_data1; + union { + struct { + uint32_t key_purpose_2: 4; /*The value of KEY_PURPOSE_2.*/ + uint32_t key_purpose_3: 4; /*The value of KEY_PURPOSE_3.*/ + uint32_t key_purpose_4: 4; /*The value of KEY_PURPOSE_4.*/ + uint32_t key_purpose_5: 4; /*The value of KEY_PURPOSE_5.*/ + uint32_t rpt4_reserved3: 4; /*Reserved.*/ + uint32_t secure_boot_en: 1; /*The value of SECURE_BOOT_EN.*/ + uint32_t secure_boot_aggressive_revoke: 1; /*The value of SECURE_BOOT_AGGRESSIVE_REVOKE.*/ + uint32_t rpt4_reserved0: 6; /*Reserved.*/ + uint32_t flash_tpuw: 4; /*The value of FLASH_TPUW.*/ + }; + uint32_t val; + } rd_repeat_data2; + union { + struct { + uint32_t dis_download_mode: 1; /*The value of DIS_DOWNLOAD_MODE.*/ + uint32_t dis_direct_boot: 1; /*The value of DIS_DIRECT_BOOT.*/ + uint32_t dis_usb_serial_jtag_rom_print:1; /*The value of DIS_USB_SERIAL_JTAG_ROM_PRINT.*/ + uint32_t rpt4_reserved8: 1; /*Reserved.*/ + uint32_t dis_usb_serial_jtag_download_mode: 1; /*The value of dis_usb_serial_jtag_download_mode.*/ + uint32_t enable_security_download: 1; /*The value of ENABLE_SECURITY_DOWNLOAD.*/ + uint32_t uart_print_control: 2; /*The value of UART_PRINT_CONTROL.*/ + uint32_t rpt4_reserved7: 5; /*Reserved.*/ + uint32_t force_send_resume: 1; /*The value of FORCE_SEND_RESUME.*/ + uint32_t secure_version: 16; /*The value of SECURE_VERSION.*/ + uint32_t rpt4_reserved1: 1; /*Reserved.*/ + uint32_t err_rst_enable: 1; /*Use BLOCK0 to check error record registers, 0 - without check.*/ + }; + uint32_t val; + } rd_repeat_data3; + union { + struct { + uint32_t disable_wafer_version_major: 1; + uint32_t disable_blk_version_major: 1; + uint32_t rpt4_reserved4:22; /*Reserved.*/ + uint32_t reserved24: 8; /*Reserved.*/ + }; + uint32_t val; + } rd_repeat_data4; + uint32_t rd_mac_spi_sys_0; /*BLOCK1 data register $n.*/ + union { + struct { + uint32_t mac_1: 16; /*Stores the high 16 bits of MAC address.*/ + uint32_t spi_pad_conf_0:16; /*Stores the zeroth part of SPI_PAD_CONF.*/ + }; + uint32_t val; + } rd_mac_spi_sys_1; + uint32_t rd_mac_spi_sys_2; /*BLOCK1 data register $n.*/ + union { + struct { + uint32_t spi_pad_conf_2: 18; /*Stores the second part of SPI_PAD_CONF.*/ + uint32_t wafer_version_minor_low: 3; + uint32_t pkg_version: 3; + uint32_t blk_version_minor:3; + uint32_t sys_data_part0_0: 5; + }; + uint32_t val; + } rd_mac_spi_sys_3; + union { + struct { + uint32_t reserved1: 7; + uint32_t k_rtc_ldo: 7; + uint32_t k_dig_ldo: 7; + uint32_t v_rtc_dbias20: 8; + uint32_t v_dig_dbias20_low: 3; + }; + uint32_t val; + } rd_mac_spi_sys_4; /*BLOCK1 data register $n.*/ + union { + struct { + uint32_t v_dig_dbias20_hi: 5; + uint32_t dig_dbias_hvt: 5; + uint32_t reserved1: 13; + uint32_t wafer_version_minor_high: 1; + uint32_t wafer_version_major: 2; + uint32_t reserved2: 6; + }; + uint32_t val; + } rd_mac_spi_sys_5; /*BLOCK1 data register $n.*/ + uint32_t rd_sys_part1_data0; /*Register $n of BLOCK2 (system).*/ + uint32_t rd_sys_part1_data1; /*Register $n of BLOCK2 (system).*/ + uint32_t rd_sys_part1_data2; /*Register $n of BLOCK2 (system).*/ + uint32_t rd_sys_part1_data3; /*Register $n of BLOCK2 (system).*/ + union { + struct { + uint32_t blk_version_major: 2; + uint32_t reserved1: 10; + uint32_t ocode: 8; + uint32_t reserved2: 12; + }; + uint32_t val; + } rd_sys_part1_data4; /*Register $n of BLOCK2 (system).*/ + uint32_t rd_sys_part1_data5; /*Register $n of BLOCK2 (system).*/ + uint32_t rd_sys_part1_data6; /*Register $n of BLOCK2 (system).*/ + uint32_t rd_sys_part1_data7; /*Register $n of BLOCK2 (system).*/ + uint32_t rd_usr_data0; /*Register $n of BLOCK3 (user).*/ + uint32_t rd_usr_data1; /*Register $n of BLOCK3 (user).*/ + uint32_t rd_usr_data2; /*Register $n of BLOCK3 (user).*/ + uint32_t rd_usr_data3; /*Register $n of BLOCK3 (user).*/ + uint32_t rd_usr_data4; /*Register $n of BLOCK3 (user).*/ + uint32_t rd_usr_data5; /*Register $n of BLOCK3 (user).*/ + uint32_t rd_usr_data6; /*Register $n of BLOCK3 (user).*/ + uint32_t rd_usr_data7; /*Register $n of BLOCK3 (user).*/ + uint32_t rd_key0_data0; /*Register $n of BLOCK4 (KEY0).*/ + uint32_t rd_key0_data1; /*Register $n of BLOCK4 (KEY0).*/ + uint32_t rd_key0_data2; /*Register $n of BLOCK4 (KEY0).*/ + uint32_t rd_key0_data3; /*Register $n of BLOCK4 (KEY0).*/ + uint32_t rd_key0_data4; /*Register $n of BLOCK4 (KEY0).*/ + uint32_t rd_key0_data5; /*Register $n of BLOCK4 (KEY0).*/ + uint32_t rd_key0_data6; /*Register $n of BLOCK4 (KEY0).*/ + uint32_t rd_key0_data7; /*Register $n of BLOCK4 (KEY0).*/ + uint32_t rd_key1_data0; /*Register $n of BLOCK5 (KEY1).*/ + uint32_t rd_key1_data1; /*Register $n of BLOCK5 (KEY1).*/ + uint32_t rd_key1_data2; /*Register $n of BLOCK5 (KEY1).*/ + uint32_t rd_key1_data3; /*Register $n of BLOCK5 (KEY1).*/ + uint32_t rd_key1_data4; /*Register $n of BLOCK5 (KEY1).*/ + uint32_t rd_key1_data5; /*Register $n of BLOCK5 (KEY1).*/ + uint32_t rd_key1_data6; /*Register $n of BLOCK5 (KEY1).*/ + uint32_t rd_key1_data7; /*Register $n of BLOCK5 (KEY1).*/ + uint32_t rd_key2_data0; /*Register $n of BLOCK6 (KEY2).*/ + uint32_t rd_key2_data1; /*Register $n of BLOCK6 (KEY2).*/ + uint32_t rd_key2_data2; /*Register $n of BLOCK6 (KEY2).*/ + uint32_t rd_key2_data3; /*Register $n of BLOCK6 (KEY2).*/ + uint32_t rd_key2_data4; /*Register $n of BLOCK6 (KEY2).*/ + uint32_t rd_key2_data5; /*Register $n of BLOCK6 (KEY2).*/ + uint32_t rd_key2_data6; /*Register $n of BLOCK6 (KEY2).*/ + uint32_t rd_key2_data7; /*Register $n of BLOCK6 (KEY2).*/ + uint32_t rd_key3_data0; /*Register $n of BLOCK7 (KEY3).*/ + uint32_t rd_key3_data1; /*Register $n of BLOCK7 (KEY3).*/ + uint32_t rd_key3_data2; /*Register $n of BLOCK7 (KEY3).*/ + uint32_t rd_key3_data3; /*Register $n of BLOCK7 (KEY3).*/ + uint32_t rd_key3_data4; /*Register $n of BLOCK7 (KEY3).*/ + uint32_t rd_key3_data5; /*Register $n of BLOCK7 (KEY3).*/ + uint32_t rd_key3_data6; /*Register $n of BLOCK7 (KEY3).*/ + uint32_t rd_key3_data7; /*Register $n of BLOCK7 (KEY3).*/ + uint32_t rd_key4_data0; /*Register $n of BLOCK8 (KEY4).*/ + uint32_t rd_key4_data1; /*Register $n of BLOCK8 (KEY4).*/ + uint32_t rd_key4_data2; /*Register $n of BLOCK8 (KEY4).*/ + uint32_t rd_key4_data3; /*Register $n of BLOCK8 (KEY4).*/ + uint32_t rd_key4_data4; /*Register $n of BLOCK8 (KEY4).*/ + uint32_t rd_key4_data5; /*Register $n of BLOCK8 (KEY4).*/ + uint32_t rd_key4_data6; /*Register $n of BLOCK8 (KEY4).*/ + uint32_t rd_key4_data7; /*Register $n of BLOCK8 (KEY4).*/ + uint32_t rd_key5_data0; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_key5_data1; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_key5_data2; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_key5_data3; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_key5_data4; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_key5_data5; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_key5_data6; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_key5_data7; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_sys_part2_data0; /*Register $n of BLOCK10 (system).*/ + uint32_t rd_sys_part2_data1; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_sys_part2_data2; /*Register $n of BLOCK10 (system).*/ + uint32_t rd_sys_part2_data3; /*Register $n of BLOCK10 (system).*/ + uint32_t rd_sys_part2_data4; /*Register $n of BLOCK10 (system).*/ + uint32_t rd_sys_part2_data5; /*Register $n of BLOCK10 (system).*/ + uint32_t rd_sys_part2_data6; /*Register $n of BLOCK10 (system).*/ + uint32_t rd_sys_part2_data7; /*Register $n of BLOCK10 (system).*/ + union { + struct { + uint32_t rd_dis_err: 7; /*If any bit in RD_DIS is 1 then it indicates a programming error.*/ + uint32_t rpt4_reserved5_err: 1; /*Reserved.*/ + uint32_t dis_icache_err: 1; /*If DIS_ICACHE is 1 then it indicates a programming error.*/ + uint32_t dis_usb_jtag_err: 1; /*If DIS_USB_JTAG is 1 then it indicates a programming error.*/ + uint32_t dis_download_icache: 1; /*If DIS_DOWNLOAD_ICACHE is 1 then it indicates a programming error.*/ + uint32_t dis_usb_device_err: 1; /*If DIS_USB_DEVICE is 1 then it indicates a programming error.*/ + uint32_t dis_force_download_err: 1; /*If DIS_FORCE_DOWNLOAD is 1 then it indicates a programming error.*/ + uint32_t dis_usb_err: 1; /*If DIS_USB is 1 then it indicates a programming error.*/ + uint32_t dis_can_err: 1; /*If DIS_CAN is 1 then it indicates a programming error.*/ + uint32_t jtag_sel_enable_err: 1; /*If JTAG_SEL_ENABLE is 1 then it indicates a programming error.*/ + uint32_t soft_dis_jtag_err: 3; /*If SOFT_DIS_JTAG is 1 then it indicates a programming error.*/ + uint32_t dis_pad_jtag_err: 1; /*If DIS_PAD_JTAG is 1 then it indicates a programming error.*/ + uint32_t dis_download_manual_encrypt_err: 1; /*If DIS_DOWNLOAD_MANUAL_ENCRYPT is 1 then it indicates a programming error.*/ + uint32_t usb_drefh_err: 2; /*If any bit in USB_DREFH is 1 then it indicates a programming error.*/ + uint32_t usb_drefl_err: 2; /*If any bit in USB_DREFL is 1 then it indicates a programming error.*/ + uint32_t usb_exchg_pins_err: 1; /*If USB_EXCHG_PINS is 1 then it indicates a programming error.*/ + uint32_t vdd_spi_as_gpio_err: 1; /*If VDD_SPI_AS_GPIO is 1 then it indicates a programming error.*/ + uint32_t btlc_gpio_enable_err: 2; /*If any bit in BTLC_GPIO_ENABLE is 1 then it indicates a programming error.*/ + uint32_t powerglitch_en_err: 1; /*If POWERGLITCH_EN is 1 then it indicates a programming error.*/ + uint32_t power_glitch_dsense_err: 2; /*If any bit in POWER_GLITCH_DSENSE is 1 then it indicates a programming error.*/ + }; + uint32_t val; + } rd_repeat_err0; + union { + struct { + uint32_t rpt4_reserved2_err: 16; /*Reserved.*/ + uint32_t wdt_delay_sel_err: 2; /*If any bit in WDT_DELAY_SEL is 1 then it indicates a programming error.*/ + uint32_t spi_boot_crypt_cnt_err: 3; /*If any bit in SPI_BOOT_CRYPT_CNT is 1 then it indicates a programming error.*/ + uint32_t secure_boot_key_revoke0_err: 1; /*If SECURE_BOOT_KEY_REVOKE0 is 1 then it indicates a programming error.*/ + uint32_t secure_boot_key_revoke1_err: 1; /*If SECURE_BOOT_KEY_REVOKE1 is 1 then it indicates a programming error.*/ + uint32_t secure_boot_key_revoke2_err: 1; /*If SECURE_BOOT_KEY_REVOKE2 is 1 then it indicates a programming error.*/ + uint32_t key_purpose_0_err: 4; /*If any bit in KEY_PURPOSE_0 is 1 then it indicates a programming error.*/ + uint32_t key_purpose_1_err: 4; /*If any bit in KEY_PURPOSE_1 is 1 then it indicates a programming error.*/ + }; + uint32_t val; + } rd_repeat_err1; + union { + struct { + uint32_t key_purpose_2_err: 4; /*If any bit in KEY_PURPOSE_2 is 1 then it indicates a programming error.*/ + uint32_t key_purpose_3_err: 4; /*If any bit in KEY_PURPOSE_3 is 1 then it indicates a programming error.*/ + uint32_t key_purpose_4_err: 4; /*If any bit in KEY_PURPOSE_4 is 1 then it indicates a programming error.*/ + uint32_t key_purpose_5_err: 4; /*If any bit in KEY_PURPOSE_5 is 1 then it indicates a programming error.*/ + uint32_t rpt4_reserved3_err: 4; /*Reserved.*/ + uint32_t secure_boot_en_err: 1; /*If SECURE_BOOT_EN is 1 then it indicates a programming error.*/ + uint32_t secure_boot_aggressive_revoke_err: 1; /*If SECURE_BOOT_AGGRESSIVE_REVOKE is 1 then it indicates a programming error.*/ + uint32_t rpt4_reserved0_err: 6; /*Reserved.*/ + uint32_t flash_tpuw_err: 4; /*If any bit in FLASH_TPUM is 1 then it indicates a programming error.*/ + }; + uint32_t val; + } rd_repeat_err2; + union { + struct { + uint32_t dis_download_mode_err: 1; /*If the value is not zero then it indicates a programming error on DIS_DOWNLOAD_MODE.*/ + uint32_t dis_direct_boot_err: 1; /*If the value is not zero then it indicates a programming error on DIS_DIRECT_BOOT.*/ + uint32_t dis_usb_serial_jtag_rom_print_err:1; /*If the value is not zero then it indicates a programming error on DIS_USB_SERIAL_JTAG_ROM_PRINT.*/ + uint32_t rpt4_reserved8_err: 1; /*Reserved.*/ + uint32_t dis_usb_serial_jtag_download_mode_err: 1; /*If the value is not zero then it indicates a programming error on DIS_USB_SERIAL_JTAG_DOWNLOAD_MODE.*/ + uint32_t enable_security_download_err: 1; /*If the value is not zero then it indicates a programming error on ENABLE_SECURITY_DOWNLOAD.*/ + uint32_t uart_print_control_err: 2; /*If the value is not zero then it indicates a programming error on UART_PRINT_CONTROL.*/ + uint32_t rpt4_reserved7_err: 5; /*Reserved*/ + uint32_t force_send_resume_err: 1; /*If the value is not zero then it indicates a programming error on FORCE_SEND_RESUME.*/ + uint32_t secure_version_err: 16; /*If the value is not zero then it indicates a programming error on SECURE_VERSION.*/ + uint32_t rpt4_reserved1_err: 1; /*Reserved.*/ + uint32_t err_rst_enable_err: 1; /*Use BLOCK0 to check error record registers, 0 - without check.*/ + }; + uint32_t val; + } rd_repeat_err3; + union { + struct { + uint32_t rpt4_reserved4_err:24; /*Reserved.*/ + uint32_t reserved24: 8; /*Reserved.*/ + }; + uint32_t val; + } rd_repeat_err4; + uint32_t reserved_190; + uint32_t reserved_194; + uint32_t reserved_198; + uint32_t reserved_19c; + uint32_t reserved_1a0; + uint32_t reserved_1a4; + uint32_t reserved_1a8; + uint32_t reserved_1ac; + uint32_t reserved_1b0; + uint32_t reserved_1b4; + uint32_t reserved_1b8; + uint32_t reserved_1bc; + union { + struct { + uint32_t mac_spi_8m_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t reserved3: 1; /*Reserved.*/ + uint32_t sys_part1_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t mac_spi_8m_fail: 1; /*0: Means no failure and that the data of MAC_SPI_8M is reliable 1: Means that programming MAC_SPI_8M failed and the number of error bytes is over 6.*/ + uint32_t usr_data_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t sys_part1_fail: 1; /*0: Means no failure and that the data of system part1 is reliable 1: Means that programming the data of system part1 failed and the number of error bytes is over 6.*/ + uint32_t key0_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t usr_data_fail: 1; /*0: Means no failure and that the data of user data is reliable 1: Means that programming user data failed and the number of error bytes is over 6.*/ + uint32_t key1_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t key0_fail: 1; /*0: Means no failure and that the data of key0 is reliable 1: Means that programming key0 failed and the number of error bytes is over 6.*/ + uint32_t key2_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t key1_fail: 1; /*0: Means no failure and that the data of key1 is reliable 1: Means that programming key1 failed and the number of error bytes is over 6.*/ + uint32_t key3_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t key2_fail: 1; /*0: Means no failure and that the data of key2 is reliable 1: Means that programming key2 failed and the number of error bytes is over 6.*/ + uint32_t key4_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t key3_fail: 1; /*0: Means no failure and that the data of key3 is reliable 1: Means that programming key3 failed and the number of error bytes is over 6.*/ + }; + uint32_t val; + } rd_rs_err0; + union { + struct { + uint32_t key5_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t key4_fail: 1; /*0: Means no failure and that the data of KEY4 is reliable 1: Means that programming KEY4 failed and the number of error bytes is over 6.*/ + uint32_t sys_part2_err_num: 3; /*The value of this signal means the number of error bytes.*/ + uint32_t key5_fail: 1; /*0: Means no failure and that the data of KEY5 is reliable 1: Means that programming KEY5 failed and the number of error bytes is over 6.*/ + uint32_t reserved8: 24; /*Reserved.*/ + }; + uint32_t val; + } rd_rs_err1; + union { + struct { + uint32_t mem_force_pd: 1; /*Set this bit to force eFuse SRAM into power-saving mode.*/ + uint32_t mem_clk_force_on: 1; /*Set this bit and force to activate clock signal of eFuse SRAM.*/ + uint32_t mem_force_pu: 1; /*Set this bit to force eFuse SRAM into working mode.*/ + uint32_t reserved3: 13; /*Reserved.*/ + uint32_t clk_en: 1; /*Set this bit and force to enable clock signal of eFuse memory.*/ + uint32_t reserved17: 15; /*Reserved.*/ + }; + uint32_t val; + } clk; + union { + struct { + uint32_t op_code: 16; /*0x5A5A: Operate programming command 0x5AA5: Operate read command.*/ + uint32_t reserved16:16; /*Reserved.*/ + }; + uint32_t val; + } conf; + union { + struct { + uint32_t state: 4; /*Indicates the state of the eFuse state machine.*/ + uint32_t otp_load_sw: 1; /*The value of OTP_LOAD_SW.*/ + uint32_t otp_vddq_c_sync2: 1; /*The value of OTP_VDDQ_C_SYNC2.*/ + uint32_t otp_strobe_sw: 1; /*The value of OTP_STROBE_SW.*/ + uint32_t otp_csb_sw: 1; /*The value of OTP_CSB_SW.*/ + uint32_t otp_pgenb_sw: 1; /*The value of OTP_PGENB_SW.*/ + uint32_t otp_vddq_is_sw: 1; /*The value of OTP_VDDQ_IS_SW.*/ + uint32_t repeat_err_cnt: 8; /*Indicates the number of error bits during programming BLOCK0.*/ + uint32_t reserved18: 14; /*Reserved.*/ + }; + uint32_t val; + } status; + union { + struct { + uint32_t read_cmd: 1; /*Set this bit to send read command.*/ + uint32_t pgm_cmd: 1; /*Set this bit to send programming command.*/ + uint32_t blk_num: 4; /*The serial number of the block to be programmed. Value 0-10 corresponds to block number 0-10 respectively.*/ + uint32_t reserved6: 26; /*Reserved.*/ + }; + uint32_t val; + } cmd; + union { + struct { + uint32_t read_done: 1; /*The raw bit signal for read_done interrupt.*/ + uint32_t pgm_done: 1; /*The raw bit signal for pgm_done interrupt.*/ + uint32_t reserved2: 30; /*Reserved.*/ + }; + uint32_t val; + } int_raw; + union { + struct { + uint32_t read_done: 1; /*The status signal for read_done interrupt.*/ + uint32_t pgm_done: 1; /*The status signal for pgm_done interrupt.*/ + uint32_t reserved2: 30; /*Reserved.*/ + }; + uint32_t val; + } int_st; + union { + struct { + uint32_t read_done: 1; /*The enable signal for read_done interrupt.*/ + uint32_t pgm_done: 1; /*The enable signal for pgm_done interrupt.*/ + uint32_t reserved2: 30; /*Reserved.*/ + }; + uint32_t val; + } int_ena; + union { + struct { + uint32_t read_done: 1; /*The clear signal for read_done interrupt.*/ + uint32_t pgm_done: 1; /*The clear signal for pgm_done interrupt.*/ + uint32_t reserved2: 30; /*Reserved.*/ + }; + uint32_t val; + } int_clr; + union { + struct { + uint32_t dac_clk_div: 8; /*Controls the division factor of the rising clock of the programming voltage.*/ + uint32_t dac_clk_pad_sel: 1; /*Don't care.*/ + uint32_t dac_num: 8; /*Controls the rising period of the programming voltage.*/ + uint32_t oe_clr: 1; /*Reduces the power supply of the programming voltage.*/ + uint32_t reserved18: 14; /*Reserved.*/ + }; + uint32_t val; + } dac_conf; + union { + struct { + uint32_t reserved0: 24; /*Configures the setup time of read operation.*/ + uint32_t read_init_num: 8; /*Configures the initial read time of eFuse.*/ + }; + uint32_t val; + } rd_tim_conf; + union { + struct { + uint32_t reserved0: 8; /*Configures the setup time of programming operation.*/ + uint32_t pwr_on_num:16; /*Configures the power up time for VDDQ.*/ + uint32_t reserved24: 8; /*Reserved.*/ + }; + uint32_t val; + } wr_tim_conf1; + union { + struct { + uint32_t pwr_off_num:16; /*Configures the power outage time for VDDQ.*/ + uint32_t reserved16: 16; /*Reserved.*/ + }; + uint32_t val; + } wr_tim_conf2; + uint32_t reserved_1f8; + union { + struct { + uint32_t date: 28; /*Stores eFuse version.*/ + uint32_t reserved28: 4; /*Reserved.*/ + }; + uint32_t val; + } date; + uint32_t dbg_erase_all; +} __attribute__((packed)); + +typedef struct ESP32C3EfuseRegs ESP32C3EfuseRegs; + +typedef struct ESP32C3EfuseState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + /* In case no block was given by the user, use the mirror as a file in RAM */ + BlockBackend *blk; + void* mirror; + + qemu_irq irq; + /* Use a mirror to make sure the operation value did not change between the moment + * it is scheduled and the moment it actually happens. */ + uint32_t op_cmd_mirror; + QEMUTimer op_timer; + + ESP32C3EfuseRegs efuses; +} ESP32C3EfuseState; + + +/** + * Define a few helpers for the efuse blocks + */ + +/** + * Returns the size of the given block, in bytes. + * BLOCK0 and BLOCK1 have 6 registers while other blocks have 8 registers + */ +static inline int esp32c3_efuse_block_size(const uint32_t block) +{ + return (block == 0 || block == 1) ? ESP32C3_EFUSE_BLOCK0_WORDS * sizeof(uint32_t) + : 8 * sizeof(uint32_t); +} + +/** + * Returns true if the current command is a valid read command, false else + */ +static inline bool esp32c3_efuse_is_read_cmd(ESP32C3EfuseState *s) +{ + return s->efuses.conf.op_code == EFUSE_READ_OPCODE && s->efuses.cmd.read_cmd; +} + +/** + * Returns true if the current command is a valid write/program command, false else + */ +static inline bool esp32c3_efuse_is_write_cmd(ESP32C3EfuseState *s) +{ + return s->efuses.conf.op_code == EFUSE_WRITE_OPCODE && s->efuses.cmd.pgm_cmd; +} From 3eb4caf87b9d0e0a1f597b10fdd1d347e890ab0c Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:56:39 +0800 Subject: [PATCH 42/56] hw/misc: implement ESP32-C3 AES (no DMA supported) --- hw/misc/esp32c3_aes.c | 257 ++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 3 +- include/hw/misc/esp32c3_aes.h | 123 ++++++++++++++++ 3 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 hw/misc/esp32c3_aes.c create mode 100644 include/hw/misc/esp32c3_aes.h diff --git a/hw/misc/esp32c3_aes.c b/hw/misc/esp32c3_aes.c new file mode 100644 index 000000000000..26cd50cce3ed --- /dev/null +++ b/hw/misc/esp32c3_aes.c @@ -0,0 +1,257 @@ +/* + * ESP32-C3 AES emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32c3_aes.h" +#include "crypto/aes.h" +#include "qemu/error-report.h" + +#define AES_WARNING 0 +#define AES_DEBUG 0 + + +static void esp32c3_aes_dma_exit(ESP32C3AesState *s) +{ + /* DMA is not supported yet */ + (void) s; +} + + +static void esp32c3_aes_start(ESP32C3AesState *s) +{ + AES_KEY aes_key; + + /* DMA mode is not supported yet! */ + if (FIELD_EX32(s->dma_enable_reg , AES_DMA_ENA_REG, AES_DMA_ENA) != 0) { + error_report("[AES] DMA-AES is not supported yet\n"); + return; + } + + /* Check whether we have to encrypt or decrypt */ + const uint32_t mode = FIELD_EX32(s->mode_reg , AES_MODE_REG, AES_MODE); + const bool encrypt = (mode == ESP32C3_AES_MODE_128_ENC) || (mode == ESP32C3_AES_MODE_256_ENC); + const bool decrypt = (mode == ESP32C3_AES_MODE_128_DEC) || (mode == ESP32C3_AES_MODE_256_DEC); + + /* Get the length, in bits of the key */ + const int length = (mode == ESP32C3_AES_MODE_128_ENC || mode == ESP32C3_AES_MODE_128_DEC) ? 128 : 256; + + /* Cast the keys and data to byte array. + * This can only work as-is if the host computer is has a little-endian CPU. */ + const uint8_t* key = (uint8_t*) &s->key; + const uint8_t* tin = (uint8_t*) &s->text_in; + uint8_t* tout = (uint8_t*) &s->text_out; + + if (encrypt) { + + AES_set_encrypt_key(key, length, &aes_key); + AES_encrypt(tin, tout, &aes_key); + + } else if (decrypt) { + + AES_set_decrypt_key(key, length, &aes_key); + AES_decrypt(tin, tout, &aes_key); + + } + + s->state_reg = ESP32C3_AES_IDLE; +} + +static uint64_t esp32c3_aes_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3AesState *s = ESP32C3_AES(opaque); + uint64_t r = 0; + + switch (addr) { + case A_AES_KEY_0_REG ... A_AES_KEY_7_REG: + r = s->key[(addr - A_AES_KEY_0_REG) / sizeof(uint32_t)]; + break; + + case A_AES_TEXT_IN_0_REG ... A_AES_TEXT_IN_3_REG: + r = s->text_in[(addr - A_AES_TEXT_IN_0_REG) / sizeof(uint32_t)]; + break; + + case A_AES_TEXT_OUT_0_REG ... A_AES_TEXT_OUT_3_REG: + r = s->text_out[(addr - A_AES_TEXT_OUT_0_REG) / sizeof(uint32_t)]; + break; + + case A_AES_IV_MEM_0_REG ... A_AES_IV_MEM_15_REG: + r = s->iv_mem[(addr - A_AES_IV_MEM_0_REG) / sizeof(uint32_t)]; + break; + + case A_AES_STATE_REG: + r = s->state_reg; + break; + + case A_AES_MODE_REG: + r = s->mode_reg; + break; + + case A_AES_DMA_ENA_REG: + r = s->dma_enable_reg; + break; + + case A_AES_BLK_MODE_REG: + r = s->block_mode_reg; + break; + + case A_AES_BLK_NUM_REG: + r = s->block_num_reg; + break; + + case A_AES_INC_SEL_REG: + r = s->inc_sel_reg; + break; + + case A_AES_INT_ENA_REG: + r = s->int_ena_reg; + break; + + default: +#if AES_WARNING + /* Other registers are not supported yet */ + warn_report("[AES] Unsupported read to %08lx\n", addr); +#endif + break; + } + +#if AES_DEBUG + info_report("[AES] Reading from %08lx (%08lx)\n", addr, r); +#endif + + + return r; +} + + +static void esp32c3_aes_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3AesState *s = ESP32C3_AES(opaque); + + switch (addr) { + case A_AES_KEY_0_REG ... A_AES_KEY_7_REG: + s->key[(addr - A_AES_KEY_0_REG) / sizeof(uint32_t)] = value; + break; + + case A_AES_TEXT_IN_0_REG ... A_AES_TEXT_IN_3_REG: + s->text_in[(addr - A_AES_TEXT_IN_0_REG) / sizeof(uint32_t)] = value; + break; + + case A_AES_IV_MEM_0_REG ... A_AES_IV_MEM_15_REG: + s->iv_mem[(addr - A_AES_IV_MEM_0_REG) / sizeof(uint32_t)] = value; + break; + + case A_AES_MODE_REG: + s->mode_reg = value; + break; + + case A_AES_TRIGGER_REG: + if (FIELD_EX32(value, AES_TRIGGER_REG, AES_TRIGGER)) { + esp32c3_aes_start(s); + } + break; + + case A_AES_DMA_ENA_REG: + s->dma_enable_reg = value; + break; + + case A_AES_BLK_MODE_REG: + s->block_mode_reg = value; + break; + + case A_AES_BLK_NUM_REG: + s->block_num_reg = value; + break; + + case A_AES_INC_SEL_REG: + s->inc_sel_reg = value; + break; + + case A_AES_INT_CLR_REG: + if (FIELD_EX32(value, AES_INT_CLR_REG, AES_INT_CLR)) { + s->int_st = 0; + } + break; + + case A_AES_INT_ENA_REG: + s->int_ena_reg = FIELD_EX32(value, AES_INT_ENA_REG, AES_INT_ENA) ? 1 : 0; + break; + + case A_AES_DMA_EXIT_REG: + esp32c3_aes_dma_exit(s); + break; + + default: +#if AES_WARNING + /* Other registers are not supported yet */ + warn_report("[AES] Unsupported write to %08lx (%08lx)\n", addr, value); +#endif + break; + } + +#if AES_DEBUG + info_report("[AES] Writing to %08lx (%08lx)\n", addr, value); +#endif + +} + +static const MemoryRegionOps esp32c3_aes_ops = { + .read = esp32c3_aes_read, + .write = esp32c3_aes_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32c3_aes_reset(DeviceState *dev) +{ + ESP32C3AesState *s = ESP32C3_AES(dev); + memset(s->key, 0, ESP32C3_AES_KEY_REG_CNT * sizeof(uint32_t)); + memset(s->text_in, 0, ESP32C3_AES_TEXT_REG_CNT * sizeof(uint32_t)); + memset(s->text_out, 0, ESP32C3_AES_TEXT_REG_CNT * sizeof(uint32_t)); + + s->state_reg = ESP32C3_AES_IDLE; + s->mode_reg = 0; + s->dma_enable_reg = 0; + s->block_mode_reg = 0; + s->block_num_reg = 0; + s->inc_sel_reg = 0; + s->int_ena_reg = 0; +} + +static void esp32c3_aes_init(Object *obj) +{ + ESP32C3AesState *s = ESP32C3_AES(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_aes_ops, s, + TYPE_ESP32C3_AES, ESP32C3_AES_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void esp32_aes_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_aes_reset; +} + +static const TypeInfo esp32c3_aes_info = { + .name = TYPE_ESP32C3_AES, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3AesState), + .instance_init = esp32c3_aes_init, + .class_init = esp32_aes_class_init +}; + +static void esp32c3_aes_register_types(void) +{ + type_register_static(&esp32c3_aes_info); +} + +type_init(esp32c3_aes_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index baf8c7608885..78f2c968e394 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -140,7 +140,8 @@ softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files( 'esp32c3_cache.c', 'esp32c3_sha.c', 'esp32c3_jtag.c', - 'esp32c3_rtc_cntl.c' + 'esp32c3_rtc_cntl.c', + 'esp32c3_aes.c' )) if gcrypt.found() diff --git a/include/hw/misc/esp32c3_aes.h b/include/hw/misc/esp32c3_aes.h new file mode 100644 index 000000000000..2a168e05007e --- /dev/null +++ b/include/hw/misc/esp32c3_aes.h @@ -0,0 +1,123 @@ +/* + * ESP32-C3 AES emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" + +#define TYPE_ESP32C3_AES "misc.esp32c3.aes" +#define ESP32C3_AES(obj) OBJECT_CHECK(ESP32C3AesState, (obj), TYPE_ESP32C3_AES) + +#define ESP32C3_AES_REGS_SIZE (A_AES_DMA_EXIT_REG + 4) + +#define ESP32C3_AES_TEXT_REG_CNT 4 +#define ESP32C3_AES_KEY_REG_CNT 8 +#define ESP32C3_AES_IV_REG_CNT 16 + +#define ESP32C3_AES_IDLE 0 +#define ESP32C3_AES_WORK 1 +#define ESP32C3_AES_DONE 2 + +/** + * Encryption and decryption modes + */ +#define ESP32C3_AES_MODE_128_ENC 0 +#define ESP32C3_AES_MODE_256_ENC 2 +#define ESP32C3_AES_MODE_128_DEC 4 +#define ESP32C3_AES_MODE_256_DEC 6 + + +typedef struct ESP32C3AesState { + SysBusDevice parent_object; + MemoryRegion iomem; + + uint32_t key[ESP32C3_AES_KEY_REG_CNT]; + uint32_t text_in[ESP32C3_AES_TEXT_REG_CNT]; + uint32_t text_out[ESP32C3_AES_TEXT_REG_CNT]; + uint32_t iv_mem[ESP32C3_AES_IV_REG_CNT]; + + uint32_t mode_reg; + uint32_t state_reg; + uint32_t dma_enable_reg; + uint32_t block_mode_reg; + uint32_t block_num_reg; + uint32_t inc_sel_reg; + + uint32_t int_st; + uint32_t int_ena_reg; +} ESP32C3AesState; + + +REG32(AES_KEY_0_REG, 0x00) +REG32(AES_KEY_1_REG, 0x04) +REG32(AES_KEY_2_REG, 0x08) +REG32(AES_KEY_3_REG, 0x0C) +REG32(AES_KEY_4_REG, 0x10) +REG32(AES_KEY_5_REG, 0x14) +REG32(AES_KEY_6_REG, 0x18) +REG32(AES_KEY_7_REG, 0x1C) + +REG32(AES_TEXT_IN_0_REG, 0x20) +REG32(AES_TEXT_IN_1_REG, 0x24) +REG32(AES_TEXT_IN_2_REG, 0x28) +REG32(AES_TEXT_IN_3_REG, 0x2C) + +REG32(AES_TEXT_OUT_0_REG, 0x30) +REG32(AES_TEXT_OUT_1_REG, 0x34) +REG32(AES_TEXT_OUT_2_REG, 0x38) +REG32(AES_TEXT_OUT_3_REG, 0x3C) + + +REG32(AES_IV_MEM_0_REG, 0x50) +REG32(AES_IV_MEM_1_REG, 0x51) +REG32(AES_IV_MEM_2_REG, 0x52) +REG32(AES_IV_MEM_3_REG, 0x53) +REG32(AES_IV_MEM_4_REG, 0x54) +REG32(AES_IV_MEM_5_REG, 0x55) +REG32(AES_IV_MEM_6_REG, 0x56) +REG32(AES_IV_MEM_7_REG, 0x57) +REG32(AES_IV_MEM_8_REG, 0x58) +REG32(AES_IV_MEM_9_REG, 0x59) +REG32(AES_IV_MEM_10_REG, 0x5a) +REG32(AES_IV_MEM_11_REG, 0x5b) +REG32(AES_IV_MEM_12_REG, 0x5c) +REG32(AES_IV_MEM_13_REG, 0x5d) +REG32(AES_IV_MEM_14_REG, 0x5e) +REG32(AES_IV_MEM_15_REG, 0x5f) + + +REG32(AES_MODE_REG, 0x40) + FIELD(AES_MODE_REG, AES_MODE, 0, 3) + +REG32(AES_TRIGGER_REG, 0x48) + FIELD(AES_TRIGGER_REG, AES_TRIGGER, 0, 1) + +REG32(AES_STATE_REG, 0x4C) + FIELD(AES_STATE_REG, AES_STATE, 0, 2) + +REG32(AES_DMA_ENA_REG, 0x90) + FIELD(AES_DMA_ENA_REG, AES_DMA_ENA, 0, 1) + +REG32(AES_BLK_MODE_REG, 0x94) + FIELD(AES_BLK_MODE_REG, AES_BLOCK_MODE, 0, 3) + +REG32(AES_BLK_NUM_REG, 0x98) + +REG32(AES_INC_SEL_REG, 0x9C) + FIELD(AES_INC_SEL_REG, AES_INC_SEL, 0, 1) + +REG32(AES_INT_CLR_REG, 0xAC) + FIELD(AES_INT_CLR_REG, AES_INT_CLR, 0, 1) + +REG32(AES_INT_ENA_REG, 0xB0) + FIELD(AES_INT_ENA_REG, AES_INT_ENA, 0, 1) + +REG32(AES_DMA_EXIT_REG, 0xB8) From 273c5c21928ae63128408e428faf757851a24ecb Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 12 May 2023 10:58:13 +0800 Subject: [PATCH 43/56] hw/riscv: implement ESP32-C3 machine This also includes the C3 BIOS (ROM bootloader) --- hw/riscv/esp32c3.c | 491 ++++++++++++++++++++++++++++++++++ hw/riscv/meson.build | 2 +- include/hw/misc/esp32c3_reg.h | 49 ++++ pc-bios/esp32c3-rom.bin | Bin 0 -> 393216 bytes pc-bios/meson.build | 1 + 5 files changed, 542 insertions(+), 1 deletion(-) create mode 100644 hw/riscv/esp32c3.c create mode 100644 include/hw/misc/esp32c3_reg.h create mode 100755 pc-bios/esp32c3-rom.bin diff --git a/hw/riscv/esp32c3.c b/hw/riscv/esp32c3.c new file mode 100644 index 000000000000..42fae7b0a9a4 --- /dev/null +++ b/hw/riscv/esp32c3.c @@ -0,0 +1,491 @@ +/* + * ESP32-C3 SoC and machine + * + * Copyright (c) 2019-2022 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/qdev-properties.h" +#include "qemu/units.h" +#include "qemu/datadir.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "hw/riscv/riscv_hart.h" +#include "target/riscv/esp_cpu.h" +#include "hw/riscv/boot.h" +#include "hw/riscv/numa.h" +#include "sysemu/device_tree.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" +#include "sysemu/runstate.h" +#include "sysemu/reset.h" +#include "hw/misc/esp32c3_reg.h" +#include "hw/misc/esp32c3_rtc_cntl.h" +#include "hw/misc/esp32c3_cache.h" +#include "hw/char/esp32c3_uart.h" +#include "hw/gpio/esp32c3_gpio.h" +#include "hw/nvram/esp32c3_efuse.h" +#include "hw/riscv/esp32c3_clk.h" +#include "hw/riscv/esp32c3_intmatrix.h" +#include "hw/misc/esp32c3_sha.h" +#include "hw/timer/esp32c3_timg.h" +#include "hw/timer/esp32c3_systimer.h" +#include "hw/ssi/esp32c3_spi.h" +#include "hw/misc/esp32c3_rtc_cntl.h" +#include "hw/misc/esp32c3_aes.h" +#include "hw/misc/esp32c3_jtag.h" + +#define ESP32C3_IO_WARNING 0 + +#define ESP32C3_RESET_ADDRESS 0x40000000 + + +/* Define a new "class" which derivates from "MachineState" */ +struct Esp32C3MachineState { + MachineState parent; + + /* Attributes specific to our class */ + EspRISCVCPU soc; + BusState periph_bus; + MemoryRegion iomem; + + qemu_irq cpu_reset; + + ESP32C3IntMatrixState intmatrix; + ESP32C3UARTState uart[ESP32C3_UART_COUNT]; + ESP32C3GPIOState gpio; + ESP32C3CacheState cache; + ESP32C3EfuseState efuse; + ESP32C3ClockState clock; + ESP32C3AesState aes; + ESP32C3ShaState sha; + ESP32C3TimgState timg[2]; + ESP32C3SysTimerState systimer; + ESP32C3SpiState spi1; + ESP32C3RtcCntlState rtccntl; + ESP32C3UsbJtagState jtag; +}; + +/* Temporary macro for generating a random value from register SYSCON_RND_DATA_REG */ +#define A_SYSCON_RND_DATA_REG 0x0B0 + +/* Temporary macro to mark the CPU as in non-debugging mode */ +#define A_ASSIST_DEBUG_CORE_0_DEBUG_MODE_REG 0x098 + +/* Create a macro which defines the name of our new machine class */ +#define TYPE_ESP32C3_MACHINE MACHINE_TYPE_NAME("esp32c3") + +/* This will create a macro ESP32_MACHINE, which can be used to check and cast a generic MachineClass + * to the specific class we defined above: Esp32C3MachineState. */ +OBJECT_DECLARE_SIMPLE_TYPE(Esp32C3MachineState, ESP32C3_MACHINE) + +/* Memory entries for ESP32-C3 */ +enum MemoryRegions { + ESP32C3_MEMREGION_IROM, + ESP32C3_MEMREGION_DROM, + ESP32C3_MEMREGION_DRAM, + ESP32C3_MEMREGION_IRAM, + ESP32C3_MEMREGION_RTCFAST, + ESP32C3_MEMREGION_DCACHE, + ESP32C3_MEMREGION_ICACHE, +}; + +#define ESP32C3_INTERNAL_SRAM0_SIZE (16*1024) + +static const struct MemmapEntry { + hwaddr base; + hwaddr size; +} esp32c3_memmap[] = { + [ESP32C3_MEMREGION_IROM] = { 0x40000000, 0x60000 }, + [ESP32C3_MEMREGION_DROM] = { 0x3ff00000, 0x20000 }, + [ESP32C3_MEMREGION_DRAM] = { 0x3fc80000, 0x60000 }, + /* Merge SRAM0 and SRAM1 into a single entry */ + [ESP32C3_MEMREGION_IRAM] = { 0x4037c000, 0x60000 + ESP32C3_INTERNAL_SRAM0_SIZE }, + [ESP32C3_MEMREGION_RTCFAST] = { 0x50000000, 0x2000 }, + [ESP32C3_MEMREGION_DCACHE] = { 0x3c000000, 0x800000 }, + [ESP32C3_MEMREGION_ICACHE] = { 0x42000000, 0x800000 }, +}; + + +static bool addr_in_range(hwaddr addr, hwaddr start, hwaddr end) +{ + return addr >= start && addr < end; +} + +static uint64_t esp32c3_io_read(void *opaque, hwaddr addr, unsigned int size) +{ + if (addr_in_range(addr + ESP32C3_IO_START_ADDR, DR_REG_RTC_I2C_BASE, DR_REG_RTC_I2C_BASE + 0x100)) { + return (uint32_t) 0xffffff; + } else if (addr + ESP32C3_IO_START_ADDR == DR_REG_SYSCON_BASE + A_SYSCON_RND_DATA_REG) { + /* Return a random 32-bit value */ + static bool init = false; + if (!init) { + srand(time(NULL)); + init = true; + } + return rand(); + } else if (addr + ESP32C3_IO_START_ADDR == DR_REG_ASSIST_DEBUG_BASE + A_ASSIST_DEBUG_CORE_0_DEBUG_MODE_REG) { + return 0; + } else { +#if ESP32C3_IO_WARNING + warn_report("[ESP32-C3] Unsupported read to $%08lx\n", ESP32C3_IO_START_ADDR + addr); +#endif + } + return 0; +} + +static void esp32c3_io_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) +{ +#if ESP32C3_IO_WARNING + warn_report("[ESP32-C3] Unsupported write $%08lx = %08lx\n", ESP32C3_IO_START_ADDR + addr, value); +#endif +} + + +/* Define operations for I/OS */ +static const MemoryRegionOps esp32c3_io_ops = { + .read = esp32c3_io_read, + .write = esp32c3_io_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + + +static void esp32c3_cpu_reset(void* opaque, int n, int level) +{ + Esp32C3MachineState *s = ESP32C3_MACHINE(qdev_get_machine()); + + if (level) { + + /* Reset the devices */ + device_cold_reset(DEVICE(&s->intmatrix)); + device_cold_reset(DEVICE(&s->gpio)); + device_cold_reset(DEVICE(&s->cache)); + device_cold_reset(DEVICE(&s->efuse)); + device_cold_reset(DEVICE(&s->clock)); + device_cold_reset(DEVICE(&s->aes)); + device_cold_reset(DEVICE(&s->sha)); + device_cold_reset(DEVICE(&s->systimer)); + device_cold_reset(DEVICE(&s->spi1)); + device_cold_reset(DEVICE(&s->rtccntl)); + device_cold_reset(DEVICE(&s->jtag)); + + for (int i = 0; i < 2; i++) { + device_cold_reset(DEVICE(&s->timg[i])); + } + + for (int i = 0; i < ESP32C3_UART_COUNT; i++) { + device_cold_reset(DEVICE(&s->uart[i])); + } + + ShutdownCause cause = SHUTDOWN_CAUSE_GUEST_RESET; + qemu_system_reset_request(cause); + } +} + + +static void esp32c3_machine_init(MachineState *machine) +{ + /* First thing to do is to check if a drive format and a file ahve been passed through the command line. + * In fact, we will emulate the SPI flash if `if=mtd` was given. To know this, we will need to use the + * Global API's function `driver_get`. */ + BlockBackend* blk = NULL; + DriveInfo *dinfo = drive_get(IF_MTD, 0, 0); + if (dinfo) { + /* MTD was given! We need to initialize and emulate SPI flash */ + qemu_log("Adding SPI flash device\n"); + blk = blk_by_legacy_dinfo(dinfo); + } else { + qemu_log("Not initializing SPI Flash\n"); + } + + /* Re-use the macro that checks and casts any generic/parent class to the real child instance */ + Esp32C3MachineState *ms = ESP32C3_MACHINE(machine); + + /* Initialize SoC */ + object_initialize_child(OBJECT(ms), "soc", &ms->soc, TYPE_ESP_RISCV_CPU); + qdev_prop_set_uint64(DEVICE(&ms->soc), "resetvec", ESP32C3_RESET_ADDRESS); + + /* Initialize the peripheral bus */ + qbus_init(&ms->periph_bus, sizeof(ms->periph_bus), + TYPE_SYSTEM_BUS, DEVICE(ms), "esp32c3-periph-bus"); + + /* Initialize the memory mapping */ + const struct MemmapEntry *memmap = esp32c3_memmap; + MemoryRegion *sys_mem = get_system_memory(); + + /* Initialize the IROM */ + MemoryRegion *irom = g_new(MemoryRegion, 1); + memory_region_init_rom(irom, NULL, "esp32c3.irom", memmap[ESP32C3_MEMREGION_IROM].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[ESP32C3_MEMREGION_IROM].base, irom); + + /* Initialize the DROM as an alias to IROM. */ + MemoryRegion *drom = g_new(MemoryRegion, 1); + const hwaddr offset_in_orig = 0x40000; + memory_region_init_alias(drom, NULL, "esp32c3.drom", irom, offset_in_orig, memmap[ESP32C3_MEMREGION_DROM].size); + memory_region_add_subregion(sys_mem, memmap[ESP32C3_MEMREGION_DROM].base, drom); + + /* Initialize the IRAM */ + MemoryRegion *iram = g_new(MemoryRegion, 1); + memory_region_init_ram(iram, NULL, "esp32c3.iram", memmap[ESP32C3_MEMREGION_IRAM].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[ESP32C3_MEMREGION_IRAM].base, iram); + + /* Initialize DRAM as an alias to IRAM (not including Internal SRAM 0) */ + MemoryRegion *dram = g_new(MemoryRegion, 1); + /* DRAM mirrors IRAM for SRAM 1, skip the SRAM 0 area */ + memory_region_init_alias(dram, NULL, "esp32c3.dram", iram, + ESP32C3_INTERNAL_SRAM0_SIZE, memmap[ESP32C3_MEMREGION_DRAM].size); + memory_region_add_subregion(sys_mem, memmap[ESP32C3_MEMREGION_DRAM].base, dram); + + /* Initialize RTC Fast Memory as regular RAM */ + MemoryRegion *rtcram = g_new(MemoryRegion, 1); + memory_region_init_ram(rtcram, NULL, "esp32c3.rtcram", memmap[ESP32C3_MEMREGION_RTCFAST].size, &error_fatal); + memory_region_add_subregion(sys_mem, memmap[ESP32C3_MEMREGION_RTCFAST].base, rtcram); + + qdev_realize(DEVICE(&ms->soc), NULL, &error_fatal); + + memory_region_init_io(&ms->iomem, OBJECT(&ms->soc), &esp32c3_io_ops, + NULL, "esp32c3.iomem", 0xd1000); + memory_region_add_subregion(sys_mem, ESP32C3_IO_START_ADDR, &ms->iomem); + + + /* Initialize the I/O of the CPU */ + qdev_init_gpio_in_named(DEVICE(&ms->soc), esp32c3_cpu_reset, ESP32C3_RTC_CPU_RESET_GPIO, 1); + + /* Initialize the I/O peripherals */ + for (int i = 0; i < ESP32C3_UART_COUNT; ++i) { + char name[16]; + snprintf(name, sizeof(name), "uart%d", i); + object_initialize_child(OBJECT(machine), name, &ms->uart[i], TYPE_ESP32C3_UART); + + snprintf(name, sizeof(name), "serial%d", i); + object_property_add_alias(OBJECT(machine), name, OBJECT(&ms->uart[i]), "chardev"); + qdev_prop_set_chr(DEVICE(&ms->uart[i]), "chardev", serial_hd(i)); + } + + object_initialize_child(OBJECT(machine), "intmatrix", &ms->intmatrix, TYPE_ESP32C3_INTMATRIX); + object_initialize_child(OBJECT(machine), "gpio", &ms->gpio, TYPE_ESP32C3_GPIO); + object_initialize_child(OBJECT(machine), "extmem", &ms->cache, TYPE_ESP32C3_CACHE); + object_initialize_child(OBJECT(machine), "efuse", &ms->efuse, TYPE_ESP32C3_EFUSE); + object_initialize_child(OBJECT(machine), "clock", &ms->clock, TYPE_ESP32C3_CLOCK); + object_initialize_child(OBJECT(machine), "sha", &ms->sha, TYPE_ESP32C3_SHA); + object_initialize_child(OBJECT(machine), "aes", &ms->aes, TYPE_ESP32C3_AES); + object_initialize_child(OBJECT(machine), "timg0", &ms->timg[0], TYPE_ESP32C3_TIMG); + object_initialize_child(OBJECT(machine), "timg1", &ms->timg[1], TYPE_ESP32C3_TIMG); + object_initialize_child(OBJECT(machine), "systimer", &ms->systimer, TYPE_ESP32C3_SYSTIMER); + object_initialize_child(OBJECT(machine), "spi1", &ms->spi1, TYPE_ESP32C3_SPI); + object_initialize_child(OBJECT(machine), "rtccntl", &ms->rtccntl, TYPE_ESP32C3_RTC_CNTL); + object_initialize_child(OBJECT(machine), "jtag", &ms->jtag, TYPE_ESP32C3_JTAG); + + /* Realize all the I/O peripherals we depend on */ + + /* Interrupt matrix realization */ + { + /* Store the current Machine CPU in the interrupt matrix */ + object_property_set_link(OBJECT(&ms->intmatrix), "cpu", OBJECT(&ms->soc), &error_abort); + qdev_realize(DEVICE(&ms->intmatrix), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->intmatrix), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_INTERRUPT_BASE, mr, 0); + + /* Connect all the interrupt matrix 31 output lines to the CPU 31 input IRQ lines. + * The lines are indexed starting at 1. + */ + for (int i = 0; i <= ESP32C3_CPU_INT_COUNT; i++) { + qemu_irq cpu_input = qdev_get_gpio_in_named(DEVICE(&ms->soc), ESP_CPU_IRQ_LINES_NAME, i); + qdev_connect_gpio_out_named(DEVICE(&ms->intmatrix), ESP32C3_INT_MATRIX_OUTPUT_NAME, i, cpu_input); + } + } + + DeviceState* intmatrix_dev = DEVICE(&ms->intmatrix); + + /* USB Serial JTAG realization */ + { + qdev_realize(DEVICE(&ms->jtag), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->jtag), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_USB_SERIAL_JTAG_BASE, mr, 0); + } + + /* RTC CNTL realization */ + { + qdev_realize(DEVICE(&ms->rtccntl), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->rtccntl), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_RTCCNTL_BASE, mr, 0); + qdev_connect_gpio_out_named(DEVICE(&ms->rtccntl), ESP32C3_RTC_CPU_RESET_GPIO, 0, + qdev_get_gpio_in_named(DEVICE(&ms->soc), ESP32C3_RTC_CPU_RESET_GPIO, 0)); + } + + /* SPI1 controller (SPI Flash) */ + { + qdev_realize(DEVICE(&ms->spi1), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->spi1), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_SPI1_BASE, mr, 0); + + + DeviceState *flash_dev = qdev_new("gd25q32"); + DeviceState *spi_master = DEVICE(&ms->spi1); + BusState* spi_bus = qdev_get_child_bus(spi_master, "spi"); + qdev_realize(flash_dev, spi_bus, &error_fatal); + qdev_connect_gpio_out_named(spi_master, SSI_GPIO_CS, 0, + qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0)); + qdev_prop_set_drive(flash_dev, "drive", blk); + } + + + for (int i = 0; i < ESP32C3_UART_COUNT; ++i) { + const hwaddr uart_base[] = { DR_REG_UART_BASE, DR_REG_UART1_BASE }; + qdev_realize(DEVICE(&ms->uart[i]), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->uart[i]), 0); + memory_region_add_subregion_overlap(sys_mem, uart_base[i], mr, 0); + sysbus_connect_irq(SYS_BUS_DEVICE(&ms->uart[i]), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_UART0_INTR_SOURCE + i)); + } + + /* GPIO realization */ + { + qdev_realize(DEVICE(&ms->gpio), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->gpio), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_GPIO_BASE, mr, 0); + } + + /* (Extmem) Cache realization */ + { + if (blk) { + ms->cache.flash_blk = blk; + } + qdev_realize(DEVICE(&ms->cache), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->cache), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_EXTMEM_BASE, mr, 0); + + memory_region_add_subregion_overlap(sys_mem, ms->cache.dcache_base, &ms->cache.dcache, 0); + memory_region_add_subregion_overlap(sys_mem, ms->cache.icache_base, &ms->cache.icache, 0); + } + + /* eFuses realization */ + { + qdev_realize(DEVICE(&ms->efuse), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->efuse), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_EFUSE_BASE, mr, 0); + sysbus_connect_irq(SYS_BUS_DEVICE(&ms->efuse), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_EFUSE_INTR_SOURCE)); + } + + /* System clock realization */ + { + qdev_realize(DEVICE(&ms->clock), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->clock), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_SYSTEM_BASE, mr, 0); + /* Connect the IRQ lines to the interrupt matrix */ + for (int i = 0; i < ESP32C3_SYSTEM_CPU_INTR_COUNT; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&ms->clock), i, + qdev_get_gpio_in(intmatrix_dev, ETS_FROM_CPU_INTR0_SOURCE + i)); + } + } + + /* SHA realization */ + { + qdev_realize(DEVICE(&ms->sha), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->sha), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_SHA_BASE, mr, 0); + } + + /* AES realization */ + { + qdev_realize(DEVICE(&ms->aes), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->aes), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_AES_BASE, mr, 0); + } + + /* Timer Groups realization */ + { + qdev_realize(DEVICE(&ms->timg[0]), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->timg[0]), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_TIMERGROUP0_BASE, mr, 0); + /* Connect the T0 interrupt line to the interrupt matrix */ + qdev_connect_gpio_out_named(DEVICE(&ms->timg[0]), ESP32C3_T0_IRQ_INTERRUPT, 0, + qdev_get_gpio_in(intmatrix_dev, ETS_TG0_T0_LEVEL_INTR_SOURCE)); + /* Connect the Watchdog interrupt line to the interrupt matrix */ + qdev_connect_gpio_out_named(DEVICE(&ms->timg[0]), ESP32C3_WDT_IRQ_INTERRUPT, 0, + qdev_get_gpio_in(intmatrix_dev, ETS_TG0_WDT_LEVEL_INTR_SOURCE)); + /* Connect the Watchdog reset request */ + qdev_connect_gpio_out_named(DEVICE(&ms->timg[0]), ESP32C3_WDT_IRQ_RESET, 0, + qdev_get_gpio_in_named(DEVICE(&ms->soc), ESP32C3_RTC_CPU_RESET_GPIO, 0)); + + } + { + qdev_realize(DEVICE(&ms->timg[1]), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->timg[1]), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_TIMERGROUP1_BASE, mr, 0); + /* Connect the T0 interrupt line to the interrupt matrix */ + qdev_connect_gpio_out_named(DEVICE(&ms->timg[1]), ESP32C3_T0_IRQ_INTERRUPT, 0, + qdev_get_gpio_in(intmatrix_dev, ETS_TG1_T0_LEVEL_INTR_SOURCE)); + qdev_connect_gpio_out_named(DEVICE(&ms->timg[1]), ESP32C3_WDT_IRQ_INTERRUPT, 0, + qdev_get_gpio_in(intmatrix_dev, ETS_TG1_WDT_LEVEL_INTR_SOURCE)); + qdev_connect_gpio_out_named(DEVICE(&ms->timg[1]), ESP32C3_WDT_IRQ_RESET, 0, + qdev_get_gpio_in_named(DEVICE(&ms->soc), ESP32C3_RTC_CPU_RESET_GPIO, 0)); + } + + /* System timer */ + { + qdev_realize(DEVICE(&ms->systimer), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->systimer), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_SYSTIMER_BASE, mr, 0); + for (int i = 0; i < ESP32C3_SYSTIMER_IRQ_COUNT; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&ms->systimer), i, + qdev_get_gpio_in(intmatrix_dev, ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE + i)); + } + } + + /* Open and load the "bios", which is the ROM binary, also named "first stage bootloader" */ + char *rom_binary = qemu_find_file(QEMU_FILE_TYPE_BIOS, "esp32c3-rom.bin"); + if (rom_binary == NULL) { + error_report("Error: -bios argument not set, and ROM code binary not found (1)"); + exit(1); + } + + /* Load ROM file at the reset address */ + int size = load_image_targphys_as(rom_binary, ESP32C3_RESET_ADDRESS, 0x60000, CPU(&ms->soc)->as); + if (size < 0) { + error_report("Error: could not load ROM binary '%s'", rom_binary); + exit(1); + } + + g_free(rom_binary); +} + + +/* Initialize machine type */ +static void esp32c3_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + mc->desc = "Espressif ESP32-C3 machine"; + mc->default_cpu_type = TYPE_ESP_RISCV_CPU; + mc->init = esp32c3_machine_init; + mc->max_cpus = 1; + mc->default_cpus = 1; + // 0x4f600 + mc->default_ram_size = 400 * 1024; +} + +/* Create a new type of machine ("child class") */ +static const TypeInfo esp32c3_info = { + .name = TYPE_ESP32C3_MACHINE, + /* Specify the parent class, i.e. the class we derivate from */ + .parent = TYPE_MACHINE, + /* Real size in bytes of our machine instance */ + .instance_size = sizeof(Esp32C3MachineState), + /* Override the init function to one we defined above */ + .class_init = esp32c3_machine_class_init, +}; + +static void esp32c3_machine_type_init(void) +{ + type_register_static(&esp32c3_info); +} + +type_init(esp32c3_machine_type_init); diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 7b59b8b25ff7..be0858cf1391 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -10,6 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c')) riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c')) -riscv_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_clk.c', 'esp32c3_intmatrix.c')) +riscv_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3.c', 'esp32c3_clk.c', 'esp32c3_intmatrix.c')) hw_arch += {'riscv': riscv_ss} diff --git a/include/hw/misc/esp32c3_reg.h b/include/hw/misc/esp32c3_reg.h new file mode 100644 index 000000000000..14d2eacfa506 --- /dev/null +++ b/include/hw/misc/esp32c3_reg.h @@ -0,0 +1,49 @@ +#pragma once + +#define DR_REG_SYSTEM_BASE 0x600c0000 +#define DR_REG_SENSITIVE_BASE 0x600c1000 +#define DR_REG_INTERRUPT_BASE 0x600c2000 +#define DR_REG_EXTMEM_BASE 0x600c4000 +#define DR_REG_MMU_TABLE 0x600c5000 +#define DR_REG_AES_BASE 0x6003a000 +#define DR_REG_SHA_BASE 0x6003b000 +#define DR_REG_RSA_BASE 0x6003c000 +#define DR_REG_HMAC_BASE 0x6003e000 +#define DR_REG_DIGITAL_SIGNATURE_BASE 0x6003d000 +#define DR_REG_GDMA_BASE 0x6003f000 +#define DR_REG_ASSIST_DEBUG_BASE 0x600ce000 +#define DR_REG_DEDICATED_GPIO_BASE 0x600cf000 +#define DR_REG_WORLD_CNTL_BASE 0x600d0000 +#define DR_REG_DPORT_END 0x600d3FFC +#define DR_REG_UART_BASE 0x60000000 +#define DR_REG_SPI1_BASE 0x60002000 +#define DR_REG_SPI0_BASE 0x60003000 +#define DR_REG_GPIO_BASE 0x60004000 +#define DR_REG_FE2_BASE 0x60005000 +#define DR_REG_FE_BASE 0x60006000 +#define DR_REG_RTCCNTL_BASE 0x60008000 +#define DR_REG_IO_MUX_BASE 0x60009000 +#define DR_REG_RTC_I2C_BASE 0x6000e000 +#define DR_REG_UART1_BASE 0x60010000 +#define DR_REG_I2C_EXT_BASE 0x60013000 +#define DR_REG_UHCI0_BASE 0x60014000 +#define DR_REG_RMT_BASE 0x60016000 +#define DR_REG_LEDC_BASE 0x60019000 +#define DR_REG_EFUSE_BASE 0x60008800 +#define DR_REG_NRX_BASE 0x6001CC00 +#define DR_REG_BB_BASE 0x6001D000 +#define DR_REG_TIMERGROUP0_BASE 0x6001F000 +#define DR_REG_TIMERGROUP1_BASE 0x60020000 +#define DR_REG_SYSTIMER_BASE 0x60023000 +#define DR_REG_SPI2_BASE 0x60024000 +#define DR_REG_SYSCON_BASE 0x60026000 +#define DR_REG_APB_CTRL_BASE 0x60026000 /* Old name for SYSCON, to be removed */ +#define DR_REG_TWAI_BASE 0x6002B000 +#define DR_REG_I2S0_BASE 0x6002D000 +#define DR_REG_APB_SARADC_BASE 0x60040000 +#define DR_REG_USB_SERIAL_JTAG_BASE 0x60043000 +#define DR_REG_AES_XTS_BASE 0x600CC000 + + +#define ESP32C3_IO_START_ADDR (DR_REG_UART_BASE) +#define ESP32C3_UART_COUNT 2 diff --git a/pc-bios/esp32c3-rom.bin b/pc-bios/esp32c3-rom.bin new file mode 100755 index 0000000000000000000000000000000000000000..853f400d3f0333b0f5ac936eaa5671dd2d1e9945 GIT binary patch literal 393216 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

LH7xgD^xpFxxjaGA)O&rrK=0N-Zvb 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

e!xabeoauFJ{&bTSUQ>U+ynkbrtP2%f z-Ie4yQ(|Wi(p6*$mI|9ddc-r1d7YR6Wj*k^AHXj}#pvqsuh7FvUH>4iq4@czm~b98 zYDdF)HnB8KcT^scH&b$sY1P%N9P!D$UuAUK#;+cQQ^cx$*|!HNk5v_MjX2qQcYD!T z0spJ>7ZJrRpMPi9?oA79#h82+_p`O|el-+@Qpk!(8QjWi63> za7-ndy;Aa>#G1Rx(Yg`XJMuWz&37`VxW24{q*9FS(^h#ti>3LTmEC+ae~w$NW?++a zn(ls({O9DKmZ1Q9tNL}$b+%ivs&nj*D06uCaFaiIb|wlx)G@A&^i=a>!*iL$wpX-C z0+W9wA z_C{{|Z&W_n@}wo4e}r*^djMNR^@Z#wTMCWtcgBar*r-i7O>`B`Xg0pi zd*ck>97!Wd`sU-@8tH5w%~+~Mtwup-`%yxwd6fD4qaBIH z+48I_qHRdQj3)-ol4o2IP1NQ9N2I9fmWCq#C`#?Vpyx>YmNSb5C6ZT{jY~DDhnX>N+3=A? z5pC*5_c@O4f~ThI#sN*l&aw3}L=iL*G=q}_k20$|->k)V+HU6BPJ$d8Rwd4^-xV`c zutvLhx4K^mkJQ;~p&26QJF-){8`ce*N8*y8Wu0Sh6(sGt^KH8HEi6XW`4Rrsr!rSc zzQE@nJ+C&uiDOb420pr6G5 zE6>cD=lsxiH>q23c0-4hj^{MEfRf@Q+eoSA~!nWpmc{gR7uVw}+~Xt#jZ(9t@~ z+^-b6*w)eE{cN=VZe{T>r6WqYCss-M#Np>4xzqaW^L6@E`1;0xKYz>Vd&1Z0y|2$d z)>F!~Z^Ykl!!`9*d@F8S!CIrc*tbSJ4PVn;m?xC7@uphLPUo=$&+ompOF#rK$XX__ z`jlEo9%7Z8#-`Snex@*&i`yP&v!e97KU2Km_LRP~jmk+r32BB;YX)4#M&Cs2@^g^~ zqC;Y~#i(PiFM7^$$})X%+2R;mRP=bP(^i${=9(5ql)iMBg378aA9Kl5+WJejs8;W@ zx2a4qW1CXUJfIwZM!!2&ndO$+|3(ze8b(LI`%lmvTmL!o-*@)b3+}f@Jj!0h|4z2D zoO*ZF-O8vsvj(7RT6>w1^pR=3(q1P)fjv^)JYU}RK>2BV6ojW?TQLMO)}Qx3uE!c8 z=wQwMMTn~j-V^biXzs0u^~R~*8gb)xWx3=ti!-ZbJOocN>ip?LchzUAOVhY-!oyY2 zfOcf=gdJ|-VXvz3yNPSXnUf{1m9-?Af!=M$+8e~(f~T72wGLjbRi*vjJw=sByszH! z=*28S&vh{tNW`6dr$&E&7c3lzo@~J`{ki}efK46^y+1$rpivYw zIdAfv#8d|CpC*t!GS7%Q;8{dkDYL;#(j$Jq@!$^X8P&8bDir5sss;U7Ox%^b%ce4a zxmC!&@Urk0+Jv>CkiQD4eTZp6EDA(IlVVx?+LtNMdcI8Y{q--WtO;%j`81}P&NN|& z8Ud|kM*YR?a|aw9MTyVIB{&Ag;w{yqY)oxSL`Xf2|AxFl4gv88{#!{Ev*eO6m(r-} zxq*@zep-^uYxw#6bQGmT7YI2OI2YeFFY*|$W*P;;Z~C;7g=7zRlhJ<9^+N&!$+f-+ z+Oh=_XY)o0ov2i<`Cq}qiNW5kFz~!de7S_8CQ9EAerc_LjA0x&$&IjOVn9dL=**kBosQ3Ue4gb~Lv~CzB$}%24xcxxji^7% zg0@%sMz&>Jnlyh-GgQzxR zXWSs2F3$+XQhTw2qGHc(B%5l|M6}LSGs>CpjvpPul%^TlH?fAKtIVV{?dLNYEnk zD`8)!g!Z%&I_gSi&nEC@oZU|{@X0ybxh{*zsdKJoTS1KQOcDIaccR*RXD%3C0yCpol$T~3(Z)LS(JW$^hf|MK?=6**heufa6bMEudin^i1`)Lxq zJACZ9`btjO5+arJ zkTxL=J8yIf`ty5&51P-;hbiAy39kJfkl=bE{jYu;HV;Y}1}1>ViFW*s{yQhc*!(5W z5OQxJ1uz-x2N>~6yEpY(xm)OW2QUGI>BEPs80Tg?=iKwQ_CNah!Fvmxpn$?N3;69JiFyI?PuXiW}p7uB*eLHZdwUzGvb(g;DhK~ zYh4~YDec2{cZlqNhPg!kXQ<@DM$@ZKb)CY^Fb2S0q`LLZ zbc;SJCh_mF;GXl>`l+S5h(np({V$QWz7uqd>$*mMfHWl?+V57&aVQs)*n6*Z9>Fy4O8$9pssWM51v!6EN9cr={~(7 zueTghMw|&;J>3e52u?9GxyU!ZfmfciU=`^99x8cUN<~#TuV5)6d43f*g8goku0+|& zw>1p=E!IHi`Wx4cc&5EUkuj_sUn8l6v(n-><#T z&T1ECn4ZH3jJ-(XzeQS2O01?e+4XUou$HX#_c6-zF^o1AR#<9gwRX{utm~_0=IM68 zV@iILzG$?P*3uw!N#$Vu@N9k4rqfjR(hHwD97SS|dZc!)z&N|Zu^&!mG-i0ZOcQ@o z%-Ev0UKVp|6>PKyt#d@%+_oq-x^>LC8;B;n%@OUQ)o;llgJ(~6y z=e8+K-@Uo#tx<)n7^v~8{1PqQlG{Wrq4v=_cSCPAw<1<2 zw&)n95Un?vCo)^-cz41Y!R^5oefOSe+Fwpjj~7VTBT&D00{fnOe|BYE{3NX9b4LYT>|9V2NGQ=Bx3LLNuuuK<|Zm3ABM!)Mv zCd8g9%$@#Gn)56yur9k5qc%NWfEA?B7yZa6CwMc~l3~oA4ylx~wQipXSNeQ5Lv6zz zL38U*df%hdSh+0cIzU}o!8c_4=Umr4Lj20kc&m2hvXRMdPIV1A$1?_d5?c(Z0LSU7 zy2^EPYJgdmAxbjYf(reG^HZA$7i`F*lrp1|a09yv`r*==!V~#Y2X!ySCI?>m*uO?T zuM(buj&ctlbnVA*%(@O<*o>gY;J2&}9GWj*=zEE1v(EL~%dn3-+qfXC$$t?RhKHRY zC609uEiu@vUCRZnyzui9%Rl#&xOA)43{OZXd+Y%!?<8WtqBq4n?RczVT{k0+?oqk1 z8|24@gJ(?9u=Bxr#r^81ao0?DmizcX>(klIfYEgJMBFIe`KtOB_DbbEq~*`4e3f<| z_i*C-I+6g*-(Ss69(|#SO5GCo-^!z%>4of3RrzyFudbmo)cL37I>r#iprm@J4(!3| z6y^o!UZt~vjc4L~<+nHGw|81F>`-~minUp1;s(CH>pfe8@|EwG;J#!*pRZe!2g=bp9398e(js~AgUVf zIXbI!cI>8e7je+#9g6loirYv-D57<=(XUZQ*Dqnz~3HXEmu+hn-_r}_gV8I zDc1LAfWBV9;tkmQex1j-p?9C5f-f=e;yfiZd3KRSXlGNAWVzlM2YH_OtzC_^m_pEJ zIZ9(@IqJ3tF|MRuhSGF(ZqR1olbJ+H(N*i_0y0*|*suyJob5d$bZ0E_o_h;8?-W6i zIPVsV#AAm?{5Q{9a1MMOJa>U1`dsFuYjK9;Qj$l?e(-};i#JivDvnZ*DvlnKS1Z<{ zwQei>Ve8#ASz#mPr5yon@uNuL$^G!40gj0_kH@ZOS^*Ctj8?7g?8?5p;Vkh`Dgk@= zW~4OJeVFNyO%_mrcW{CLuc&sSZD@CgPow^j29@z8_<$g6JK|R000xl#J(LNc`+N8x z=vZ{Fe=E658Yc-Cco_*7lwpjsf24KVCGqHgsm!LEcb7R>Mu-QWys^Bi%q=c%)3O5pn{wSXwIr-C@2yA__*P``E~mi9CwRXgDnZMz(l&_Bk}V+^XO%ymS40|%<`OeFC$8BpxL2PsIPaRDwd#1YOREqO#XfM zl2o7@b0%RVz#90~{h?{w`HjW`s~Z@Ku#?3UV1{0eLj2YF)GUtGoA^%ch5-M`n?^xaF;#FAR{Q1V|V z(-a=;OWqhf7}#ka)?ez_7~$d{XTux|OwP<<{p9uK*XR{xD9299G~9?*x>OlP@o(E0 zis9a9!zgr7tFF2yr5DT3o%8w(sz_5zu3>JZGBrkfv$|jT4lH17li7va#I_8^r7kdD zcArXz9>_IQug&{ZE;u$LF5kfhEz-QPGOQj`zRd$0;4ET`sSkq&rMeMy?sfy4@n=W(oWOO-J-NDr^!1l?ePD! zdU)g1FQPdd%dtOw-JIvay&iR)pq&ZnMR2XVq3He&nEcIB2P~TLjYUvSv@@>m8w$gD{N~12Rl3q5P2zI}ijZ6bmuqZYxaE7ap*Fg^Z)8n5 z&FjUQryv=GZNj_@)cLT8~KIt$Ivm-vd& zhkh?{PYB*1HAPGs`HZTreG2=3euRvZBKsv;q{{sOlNexh+N(8E{8>nAJi4?vU!UKQ zch*fK@8s(=k}qQx5Hk7wo82BO^?&BFBiX&0{D>yqpGFs?&L;m>-GOYL0+^okrlQgJ_OOf-9mr-XTZHB>kPK6QO=VzEVsUH&b3y0T8R zu`%_u-l(OdeE=D^Ci-^1(PA7|wG+PPG|U3b1$nO{V_j+Cpp9jfKJ=8TxAcWvXjI>|=HLf>gFJt~JbTF?~FL=QlcIn3;N7 zYV*BDX)UNHOenQ^Md(boB68~DV^aZ}r8fU-l#^;jG@IQgV(X!EqR4Zi=EWCi3?|uV zl;ynh&i0{YPHrCaIV9i>(pWqBXp8|#!wZGR+R)nc##7bj4u4v)un!qaFs8)Gpw#|2g?O9h3slvjx9-T{Vn3zgzMe87Te zaYdfml{uLepIgTpdgdx0?J)EtD5rdrzx1hZ8Z$#O<$jC*;D^&p%6$(_TYj94DHAph z^m#URGOWi-p=l!P4WERRZ!Vq=vv ze3gMd;=Exjdo1wzKoym;%eG>mCB7G)b|0`UO#icOdiCRnJB$^foa6PV;2HkMl@n$u zoumK2OwH3ph&}7r1rZ&$V}Xoz0k3h_#;(y%U8IjXfK z?o*p9GuA|Tp4ky*_Pr#g43ownRhs?E{e@DFMN*Ducl4HXF&Fj+F4wB&F=r3a^)aS< zzXuix+H^)*WrL7EMw;D#`JA*)Z519!54;*?F17*E=abzA!8$>kyuJvw2-c5-v*9`8 z{6fi>B?z8xtJ4{2v^^!Z{EsC{cmOnZSX$s=eUKVdwZv<={YQpYK6|Z9Xo<*Qs%a`X z=6{T^Sj(b-io%MYwvE6gGe{qCHwF?^E zYa~sNY41*HgY6MUZR# zUWrqp3l>>=2B%!C)M5!rJQ$j=3XNY)`7hz5m=kjA%7B-iY72`dT-~y?vPy0jq&1!8 zyQWagw0{*Nyow(fnTTxHV-Zt+CFVv zcR%^1alyLwwat~~QhVXMWLI_iKvZ>)?~>43HuCI{9T1qqQ7D9E968WqztUT0#(%TXEwyeEj)uBbOgG}?+Yu|qG~ke8DrewWAO{ONa?rZ)6=T{OY|y-88f_u)VYP!<0-W+``ZMXkr+_)i8Jb40 zJEnRUMyO0^uu+K%VikD@fGa{Gx83FWWEp0LjW)aGRVnfsW?^~*cIA$gOVbu^ccndV z`m|u)t;){j7!O)wYs*O!I{lm+J4x1mrszpm4u4(o=Pzhv-ne^Y(l9cP0}@`Pks(-a zj`(W?u&Q6a5Fl{vSzpl@9YEB%kh$CDsuO-5VQD$qNLa4{Snq`k@aHZx$F{DR(C12@ z$hJOr{?^6_&=DCrQ%t7Thf%c5alC{%&U_|Iv<*{<-_2w-D~q#ayu0(8p(FWdO={#& ztlNO`BCNZ=SGSWH7Q;M=JoRGNC}$c^kvz#1EV(Y?DFz3^VjJMF$e## z8N5rea}gx?W7UX0#Gm!Xo=w;!G%ca~#T{SgZgtxt6R=0ohz7b#?crGOlWfWf_SP4J7BY-qX23QAcvohvhX!S+nj?RdKc8y0$gmSa~1U3%Uv z_#|$O;2faHp!uOZTVh!ilp@MsV~?!C_lraAl#6&Cxe?AQ_d@a^^H!d)fwvM=l<1*# zwdXnLpQZQ^-6Y=E!+e+o&7RJ_EUZhXtfMq?R;85IogKIWI+FG}hP>CD6~zCXXTqLe^q`wPt%d93$X*+}|0q@9$K0!@C8c9PDhzkeL-(F1y2APiPmp-3Pd1(Io!Un?(D zNW*GSGbE#<)ApM`aF@M|k1$)!I7RjP12>tHl1K02d*Od575XVdcakXsT0!8PlK*)# zTH&Ss;_+I*y#L=3X`;~RoAMUCceh07?;WRn$cuIdk2VnL0>LL$x(U45Rh@7C$U=TX zy&`Yca&J0PDty3^;}g}AE{}=&u_13%n^X@2oa0Szx5&C)18)P{EWlgM5w~J}keB*P zJq^H|^o@4C+QZ~r30$s+z2+#KOjw@^p-n#I zoy7JL9%F3n_6d0~-Dw$CnjHupX3K>nCxAcCLu9N48z zo`n|R7mE?PnG8-%C^4{&v?Il|ydkGPT5Tl#4?dQ4*?k3eYV;#5rS$X>T6NS&C-(>< zLva2bj|9!|GEKrdg65&A5G8A_QfW4;6L#{pO!7@mBT41S6k8omhMv=B@UdsAt#wI= zeziA^i!P|r_V$e6VwCS_s4P$+qpqbGHDAdyA^WwZazrLlDZcDrV$!T74*2gm0*ad; zw9uG}b$SG6t<`?uikmOHy-Z~Ub#WW)I&)#1?Wnx=XPDKEkKokhe{C0ZCJO3wku7mJ z-$%ZLG*4S`HY}&r;b}9id9sZR`E>R^2 zz`WmvH1)D5FB4Yr(hYWNEze|8zG0Wkt+nCI8+5O%fxixcv0Z)7d;zKRnXI-fSc5vb zis4##qBNJ|ZrJDaucqgDbf^5h{C)HB^5bSYM-s<_R>`?jdoxnao>lTiWBM0XteVDi zpPnF}PNC9TAvrFvn;&9b!0T4QCDBi#pmh_Ka3CRM;kJe9MK@!~OHznUj<1Uv@2s9j z{-7N1&BUZHvFl8)(5x?#*H2hfXr_xVW?VkiMtKcUzE9JAymThRCWnz$Nz44%1=zX0 zO4FW8e-@r|@>uvW)`vxYxqTtl4PZE(_JUQN{RIRi@*V`L`u5LvAJN7Dz=5DO~D>#xH^Fq ztrNJxHQr#uo>2e@yV?T#2@hV!^JS9FE4GKG1!9L1(yN_n7>!8N?f`@e(v4zcks(x?PuYeLEOTRoU$eaai$IlA%%|o~PbfT|Oj5m^-{T>8)bN=$^UDB*7YIixrm!ZQM4XQpJ`d_P!>%hHX!-Nd}TwZ>iK{eUbn9FG@and!k z*D!R#CCW+GOZCkJ*U#?XaW}sZ9wfM_HuJJot5g0$?UGxO8krL#{$~4tX17QCliGk5 ze3yY1XmMWi=40{#gsEuDOUx6s@cQ~^7ylSbt+1(%NOCQr4Ty`kz^IGJ8Ok#@ek}Bz z?><9#@~oSrQjoba`nP%J%p$|%ml){BZ9lpB%x8ECzr?8d?(LBBe-;qke3ZPx<;GH+ zsh@;wx?+=mT&}$}H5R zIIO?NpS?%GbLXt=Cl22uXzN)sdn(;%D#aPN#b~Ke9(jNPPEhD(qSi}>a3kAy z@2fmnD(H?`W+vY!X+HPxw_NQ4YdNN@9mz;Jzc++eK*Q_L136O#|5_(vn)H#4`m_bW zjWkvlvMnbzMM9ojFMZQ#2oFN(e;N1&wr6S$GhCA#s9o1PO*eP8E!9lA2dMcBVn;xO z4R;m9oBtS;wzBpC=2#?2UdoRQrBY-&52CA$CepRg%~V6G*K4(99!SfnvdoOH2$<>2 zo6JD!)#-Y?lS#h!x_V9ayzGEutdLp=X~r0z~`PcPNA3ucztA5XuJ$DCOLt@E-M91EcNgYF~sY^PN_ zIvpBT7K{dDcb7=>6&A6_X!O?qlg5@&gxF|w3n5V=ZH|v4Y|viWfF6+6iWK)TsNgb{ zh;@znQ>nFi9($5Oi<3Xb`lpU@zym8I$2A~*53)qL6`KQ34~w%XDh{~*WbMhTmV}&2 zix|||CmsF{zb#&x)Y4pvrwSWN#7uXpR7;$WBa7Kc_d=gU?J&mA7E3T7uJqWvcrfGi z*s@r{j@rNnm}d)=p@@^b&fBk`qr)#=sYw+%8xvRoZZ1=3+?A(KS;um!<>mUI7Z9bA z#!=Qu#m?$DkT&XCho2v#N%gAe@OuROst&)P^_o;oiUtuf9Pl4y{NFiAnpE_wV(M1n z0|ZBItWZSDrzkq>A^+cXMosFNEPc=(CLHk_;6IyeKz5f{q-(L;0{Rvy))Ia()lL{1 zkrpUVP{|Vi7gLoc;f9zxK45c(H7oR^#V)vYhA+>x9hy)Vjh5XcgpP z)n0tX>k+S+Ue5srr+xLMAofmRDaYl{S|Ylzi(hs>Gs}%g0$RJzlCSf;B5b_NKEd>2 znsbxSlJEsSiDJSHug3IXyNi2(<%+cTPGF{Qv%<%gLEQ#VR6v-uTc(TK>fx0MULcpb zZ?oCr{a00$$u8eR%HT}~^#iO_%Khm)jRW*G7Y9T@^J;N(H4FXhYG&k7nhkhUUYu4{ zSg(tysL;Rt0KDN8R_LHn|08o~kBQ6Hx{d$VI>8%sB<#5NTZ?_*NA)4*aNd`ar^ZbYO2BnaqqwO}F*pNJW91om z#QV@8F}scViy1oIqkY)_b&!xRFn*66{QJB07i+H^#-bZeBR(UIP{K*X>l4IAH?z=w z4jf_$m!G1w9qJ&OkqxEEb$MvdYF^z&eeoAju?rO7#;}6I_khp#u;_ty8`& zEavKUMzJ7Ivf5u@R2K6~-1C4pI0UGMFDpcBjpga^~A7en)5i95k3 zG5qVUX@y2nyrCGn^AS}rGBV!iW7OJI6FX8yd~A%YbW2h(DZZM2gNzGuBX-%eTtjF_ zO2>zU17BOCK1a0ro5f*fc}~BTC83&6>@rM6usb!xTYNxDdAa{`X)pE zJ5#?Vzsh^zzf(kjW{$J*z;;4?d1+p_P|u1#wlm4|;B|1GXTL67H2|h@;Ht|7V*Axl6=1x}`($b8k6isSqF5ZX0*O(tOL7OlU*jfBvozE2|QkHMbKuT|6iJ=u>RR!!$BQ_NXUyA3Lv(Ui8f9N+87wmzo*nQG#( zkbOAfKrZCi_b(%2YLFHl)lgHAGl8x}V{?eNTH!?MCul*@{l4&w0;qkpgmR5>!tb2> zSzx2M$t-IgzZ>n*$zL)$H+lwtP?3ly031xz9`qnai1!G}G4NtMT@#W^8vlmn53oO- zMNVZduS{b7DLzy1F+*B6q5y>Ex?X8xxJ|EZB1nPeVlF&NjHrA;{5Sc{dvv$+yozmo zsrR;I!36sd_ITxT_-1)(&=yzLC1}j;9ndJVd$6(H!)u`w30qMLpcT8*GSUGfO>;N@ zd+c_kVP|-(8@dL8HLwOA-OU6p*MI{-{F=b!6a|ee(EUvEny@{xD&?O}DoMYgWC>2h z-M|-|&2y(VD&VaN&#MySACu~<6PA2fW%8$dZtOR~)! z&1S$eJU69DzC0)$xhIomVtI1y3_^%ZSc*- zarL~Q6!UpM*SZ&#;_Li9$_c7|mpvMia`8_+er`|;*1DJ_$~~D3WM)eW>Rz4@B#%{T zJFFVkUjvWin(NF9N`vJ^r6J)3W%!TBr-c-1hh;7it!eD|3TvG=^TvRWfwU!sGqI~4 zdwHT<26XtBQ7oX2_@(a|680!sW;W!tAX-!ZnNuY9>nw-FVCh-nwUotsxGiK8Sq7^} z^RiW);uY%T*Q$7H`NUNqoat)0^5XP3g~$$5N$E& zN9bGjH)Xk@4}9X`t8y-zsvDXK!xT#7?J6g!)=&8Xa-AgcGWwkzSXF%gF~MMaM*%4O zDq+p1^^-EoY~+h6{Tz8{B8lV>c_gAWW5$n&!#JJHui*P#{1h5zvFCnpZSMDs^)HQc z|2b%21akK{Ra2O*e9|=&zbjxG)Am&N&DXA-!c47q@*EqI{;ADio4|A=R=k9|DzvX0 z=?}K~NBJP?RrY1z+s^eB;=QWj)aTTr1o4nbEoqMR=bMkZHWe7PeaHI6dwqe2-!+LF z-u3-Dw{L!Mx{KSvczI2&??_Bc!g&9S$}_;ne8-8n7AkYvzf9j!iAR1?VssJw40f*n zm!g_I;u^MtasK!R__+KHJg(DT^L19pCTC{)5=YXXGsN%QtmegCf{V*!Q#*ju72*wn z#X3=)f_E;&9w;+Yd`k!7TV^9B38g4&y&3;nWpOO~%r<=~;5loS>6t>& z=Br)|KQTjLuO-sPw^Y9zIt2E-e*o;gX)`P=RTR!Rl~-7g-n<9LWN3GPF-Gt`k^~=! z|20|gs?Im}wtB0+T_!=yPrWZ4hz*&!ZKitG^~KAvDhY0S!Rx*{pqt9~C#?Cpq9sCx zl|c_)GQ|A(3xh9Yt^Y0=AC@L6)FHI0tU~OP(#*XM?XcLNt;35uojphUr&b>lw7q{| z#INmMPSs>4*xZoYl^+7E(Q#r#Q)$+i%Sr(>tB2ZMGEyksHWL0XH7sTsaDz3M7!(cc z@DIv2s%`)aE(tJld_cu_4+N!z17?&Hgk=SrI^suMcb$1#vA`ITx1i$JM(NKs>iw$D zv4tWBdRH(wCYYQ*AabAGo5_iBwI?WD89x{s?BdG_>^b|GO|xw-{xx>$VT^y?n*7vA z{~A|X0-Lqb`N2pgID?&;lk`lw_?^J|uW)V3U>ggs*iyfe;iV2%0*u1P>vbWl)?l*( zLORMzvqtrXMH##sjA4bxzr}oR2?Ok|Krbtvz|-c|KyP@;9X4bwxm;0*n&&Q zkwxQ@z#425SwP`*N}HA`DmAKLv(uYp{iDtShphUrG^_Pq?%SW1xJw&NXQ&MMf@DFB$R>ObOX<*GYpp)R~ z%28$`sS#02&md+^8ETEYZ8}2M@<-a8JvW%j4#FEs?B1|$TM~HJeh@pkDIG<9?1oh?=^ya@udN9=wE+Bv;4>r_aH(tHozv(it~{@Re~C!n zhEls}ZE}_&t;D$3@mFRt!$#3b2X((&n&y9XmpLYVwr$r|c##SSGoux5+6{>J5Mq<1 z+c;w=WXe`uo0FugBpDHQGemSP1g~VL0N=Lvyv^v9IL{2&5ip4V=;l)fC@Rnb)kB|& z^FlfT$@9OzNO}VK5vgX*EZGGOluUA1qGR^I?Wv2tX^AD>rww@p56S$QJ+OT9Njw-q z?}DpIllWlOL0PjHwnucocE>@SgChG#MqKbP-H}WWoHRXggG}u2-llfcpU+JBoRB&BC%b!oB!IB$qb@LtYr2X69tJp2A zgw8MQnkPA+Q`5I0FTgnJNPytvd;1NxJVuen9hbFfbP|tGx!bO6jtd1Z6H+bkuH4{W znpnj~i=z484KDZKXoH&>0nNx zoeSrC*R=Su$ACR0@8an`^hS+FdmV_X^uu?j;z9CQm)h{ zN|_+dTH*9VJ1X5zM)dBe!GHG-;3t$bIIHrLJIW`KT77W(xXiT|4^Dq=$HBt~r(>NS zhR*E#GBs{F9_)H{oX%-~7t&^d(8Slty)AMEmbdIS8i@>%awk&dW z@39sji6u&2m-1kEq3 zDS&0Gnj_ZiXodtpUVo4|OB!VC5$p}Vo;<+6_PXK6$wKFoQaee8p4cjWQ>-#<1nyu&Hfx5Z1-?P zO&qR^cyzR)UEQ$0=1ycxua>Xz`BCuGr3QGBItl`Nbshdh-9O+^Fg^)IehCs+QDhiD&g^I z!D)r*kI4aj0fq$uCf8RrjNz{VtT@U`EoQFp@Ua#jqOm%kGjQz*f)ES27|H+8D0G7N*<+Q%K?SSot?^tt~1WUnIN4vrL z6>AXRV)RAJ8JkxQcd}fA8vM<@hy(FoYw4_4V%^jxl!p&bVca89`rQiV6ZagS#AQ7+ zX8!p7|GYQVclU;{M95*9eRZw%0sc97L9uIUK&#R|j`6))u}bkG+&Z%l3H zc)A|I`XzrO^7^HSwtmyKYt?@KZHTZm!v9N~8WIWqvO93it`@?7L~Rv++R$7moH`?G zwtafyi$?6?Hpp;brSw?MTUM3i6(ajnvH)^uyFJ&=c1A(Xh}}L>peYq3Bu{lH0e5+Z4Rj zGY?c^bKIG@H3eKIY1^J@@-ngQ&2g};$6A$qxYix3J8?Sqy!=$ZbdX0)a*&Sri@i`Z z4(NvWv>S{!7hrOZeg$+qFkan-Y}x*uH|i?EeT-lKeYikYcml8G>wI$~v^Uj8wiXnE zU0V71wDPGe#MD^YTKjC)hq42!# z$Ow6a2Ko!!eO74wPswfhz2IBpM*eFUo1f%|<^Rv}g6AhF5?hwO1MLD^U3iZY)P)WA z*DhM5C=Hf6dY``(){sH@7XwWCz3pD|7dw$_>%bRTcfPPQL%#6K2bHQXYWLQwIEKDz zUiv#LmpP^`f2nN+#ySNw-9_vtUa!nqFvqEm_ZGd*Gw>ufLcABAwiBma(eG;aCTLb9 zD&G;jwcP%0Std`~Pm;vfyWzT3@P_wCS+kow7?BKKbn*{{YamaYpkc$!ibV4EM$o5! zuon_d2ix`>C!DRxwwwXRyhM3A zm4SFW_7wfU*=m^?XeQp~KrZliFMdwB{8VG`zPt(e_0H4Sla#jf68%p*t&1OH)($K3 zmcP`UK-#C2mr=nhVdvOm@|W_{`s0*V-a`LxHd!JyW@lzY*Fc@sNIOSg2C4kz(mEi?Q*{UL7PY5M9B6?sG$TO)rZKdrB&wDPm`|0Z-?Mh$$Wqy9Cy z-$4}YD99)-Yi$i(9q|>~@JI#l#HA7X;2Yk$1)!8VX_X-w79fdccJdsu-gfUlHtpo* z$)`sy2$y`nbZs8lOqRJpkb#&lkrl369TWtOqGkGr&UnG|?4&bZ`k*u3`rzk>Swo_w zIfNgA6z3H+q7h$UtRY8O($LaRy1;y}h_K-YpM9{Xcl!sQO^&6f$ww#0_HLhi^n*p$ zpu;98%saru6b+;&UKA0|FD+ zaP7QDXCXKQ3m^Ct_i7X{Nhy0 zxlccBrszduo1|4zB6vIbcur({plh3=f@f4e#i@>X82D9m7%zS_)Q|s`k(kFRXyBTT z#OyY<$o=85X~fr3G-_4VUCy-VOC+OpdS^WG7mAl~Pmh9X(4ur&l^+>HBezF-N8e0X zvGCl&s729eS%gT_x+aqg*R^O7{~C$ds!dk)rRlA5S5qbl@Idp99Gc} zIv?~sQdp#L+P{9^r^i*g|08nJ{cbg{{o@QqkE@)%5iRAp1<@K1Kd>p!RZg?%#%hR zd#4|@g!a&br->>HIa~$`oFupK_m{3!ao^dZK7mF9_no@7@wb)ywFr^?)&8Z{N(V$I#)`AT&I8+sj#b)&{Ix&EUEW8Y6< z!M8nl^x&Me*=DI%z}Se#aPYJn?a?($xZe-dQnSo!qdK+VU8CkdhTqThhmT+?+#{Gv z&f)d_rFNVZ|B`%v^4PwyZY7gq;NLN3T?Vz;KXt3lg#H-`qGig<(Bs7tUuaAbo!$0s z6iCUp#c4M`!mzF#I*WAek*`VXkp4cet2Wq6jFo-A)EfB=x_C`IlU|z|D$eAXUBXk# z5%Xf*)U8C9955~e7G%wB6UNj_q$ob6>H)uX@qP~k4isG zEA^?4cxb2;QQUCgi6`&K&dHwUP7he{jVmJHfr9iOZtt>#>uZ+0Ros;$1%56h{fk?_ zoFk;6T9EC}NLpOpOOY|cqOKc@?Go>JNLe8bX|aPj$M*bMPHTz%E(oc+>q*cI_5eBQ z2|R@19LC^gY2K!)6F5Z-P05c4tg4Stkj4!tBXE`c@*|=p&e`BI*?qqTz8dkF=nN;n zu_I?r+u*x|tZU`&(Mmd3rqQX*r&2CcUs@7CcoTXr#($P-j&~%kdi&R7y?QJ?@7BwG z4nDo$W6Su@V$BhnNl9;K22RCi*&@)+KVXLN>xXZ;a{S0g-8B6AzjwEjUZP#&$P~Bo z!z*#J%JcDftrK1@&f5~u7(1a;X! zC60-8f73M$F`MCk)1cYTG}yE@@2An9dRb$(A#YQ}#3)hqJWCQ}tu6CuPKEZ>w%(K0 z4_aE$x@~e_IOus`{;3`D>uUhZq}i`lM{(sZ$1{KXE@|%HoP34qyOPm=(-~jhGU0Ea zM~B!4{a@_830zgx+CRSbnIQ%BFsNyrw9LFl>UPSvbb}0HP9cbTbHEKMH$-A^=thEY zIHJOdwt!leWjS>; z>;Z+F@@Q<_lqXi|nbK=6FWR;^qnE8;;Z_?zsD_mkZny6$+>)=v$`>mQu2}bPrCr}` z^S0QL!@+vz&vvoW=z2HpACyD;Jj!7ME6iJ!x805$${JvExE0H}iE`le+ck2rLt~Dv z52U?7Y8{5*9K`^e6jdL%*=C;D5XkEfYDB3?btyPVL-rgDuuupH^d@kUmV zFHXW*wybxvBlfQtz8|ROp;+t!to5geQZ6{4c~O1|RX5Lu9mXm~ao(MEkPvT8 zKGj4*O*R*652B5%>+zMYx+K;h?a9)@!(0f`|AzFqVEI=0W>800J8p+!lFjh_*5WLz zcb1KfuvF1XKQm_Gm6N!s78fX|D~=X?q}*AT+wsxl-wGo!gpn(yT?rc@E!ddUGwDmHCWBMFmH3QxdL~2 z7CQXBy>V9J<@7vg;4Ysc&BH8Gjs=E%W}9KhkD((Rq{%vHX)g>y}w19?d{{J}}F z9+~NRazj1K&Fod&l()4=iVkDDkaH+zC%nDQ#>UG73$NQ3=Fv)n+jEzq_1q@Axx&Vt z%#)%+*d}||xZTUl`nXlVl0c^!^vVjz&m19sqi4jkcrWlQuV#VQt`(Xlir*Lzx`)ZQ zBV9Ul&50H^>=F9eIxqRfCcbX4ko5y&=I_PlK5MggrZ~USQyOS!CzbiJd;=dL_8Ixv*Vt;C z`1cbGJi+*@Q=EC8iK!>hH>;gN`YCytA)_}A(xXp@R?k^~^=xQCY5VUrFA-fdwE6-$ zx{`fdNU{j`*`a^S)&@a*t-&N4Kf?}D^LQgCpPuEawKRdspQV{+<-IDk`;1iQat?L2 zy6ardnXPJ_%L93&bJuwm>Rg5tRA*q-RcEAXsq;mp&SI`fX(8ekYw}bM0$xGikkEi{ z$Soy|$`hKInecfZupIp>lk3WX+x4zm61L@r^%@1cg$7QlG;&Atf3b=;XX18FNx^R| z@H>-9gx?~%O@RMuJutdAOG!uAHB{JF=iuwmB9Z~PRa&GR_vTikMfT|n>=k(x+r^mE zKES85L1V_2HglLi?j3M|SIHH%=;=lmg#$mJds*Koi0vCS`jG02WjGmfKcllYh|zVTC=Z_ zqZ@j{?ay1q7pk~{=tWMaIID_@X;qwAf5|zpm^W4h%2UhH279w89dA0J4Kkjz&$Ed) zja*5w*+y-M6!plVHm)`CJQaD*8lzy`od3PZUqyqD_@9-(RxXhPGT~=t5F~B!al;Gf&WE+HG_> zzLIq=)`G7MRC+a^RV#?gYMJbt$oS|QCU>04PUgw}aZIWNE~_du=0Xz}m?_s+;Hx%h z%td-msxWe2>c6?dQhs9n5P$I6Pu8h^wh-zqy_F$-tY zh#tT1&x5o|f1W!N{rL@*CTEJzRhn*b6&YM5;Lh3?*BW@xq*Q_WP5>WK>Pvl_pYK2m ztk(o#$DFvJoP`#Pai~WM`P$oM#8ulId?SZqokVS`T53zaLVIp0>?%ZMV#&3$p@9y< zk38YxEqnn}W|TY{(hGFHq`1`(b7i9?5{veOHALdUa8%0VnZZ_mQ1q*vEwY< zxl_i8&q7}`928{3X+a(U{n1(?yl)$7owOaN-4kV9^!qIaH>S$b_@W{|?i461kx8H? zd0LfL_PviYzXpn;uZfOhr}8A6TEqMKalEfDFk7YNy_*#}c@cC{r_c!~OQDlG(8(px ziEOJ2msP^RNf7wILMV0N=8ai0m?dv^Kg)&Fvz%f?i4#P7ii9R zI_3H0oHP~pDP{35mT|ltwCM%9wjn1YYM76=(cWAGPI@cnUMx1BHgd_ufr;t&$&KY4 zIO?L$xf{h|Z4DD&0W7R%d``I_JIcY&yV~Ek$wtu90GyeSmz&2+aZIlA$IcD#%nDyF zPwthqbxA*4uO(Y;Vo@tecjeHZmvqHD{z%e6Ufq&(ovpHIrlz%|^CzjHck@+$@F?P| zvduqGK5@IG^K(g!GPl&QUArYUZ0B8)4jR}WNxDT1t*PpdBwZmSo$U}Loiq`YblP95 z)>@Tx{#sQ=tCH?tNoRkpThjS!|D1G&PNd4UxQ2$ap@j}bu2o)B) zeCEkyC38 zwgrk@Z#yVRQ7*}()b5WYle=!^sGBO8NOqA_D#Ti6MgB~$ zy>T`)zLdUMuB?F`4IC7L6GLX3k-tm+m?3}0YhCgu4$``{{DJ0CgVjZlKl^?se@L@a z<jG?YQZt5fLq2I#hmTMd1N3n z$etRu2C_$9Nv#MTTXP<=M-L0cAX7V*-jQoBFW7-HLLlWTIDWwi+;3t|ZCqq79?YZ@ zp`4eg$B~nE>DskL=IBaJ-EArzujiT;^RtYcm)^_3n|uPr*N%4+Bbm3j(xj1R;?#4y zVWOnJ=FGj&t7vGkJZL@i_@Xn2r;qoG}>j`GoU0#&_rt+ja-kH`LM%njSB}0Z* z{G`Ox6e{j5F_=vZ`t1%uCLTNy`gTX~s#>(*UV@i;dUValC^H2T%&hTF}BjohR>YgXIMQjWe^LJ9JODhB;`3FzCzbW|RX zQ%CsOhnTyZ%#ip}`YIWxd{mT*%+yAr`qsq5L&^ZkMee?qj3xtX_7anZC2azBLDXo3&zjg`p`#JPO@c`OXu9T!?bV6URZ% ztBF&~uYtd^3U-cz7(FTZ+sasIHuAI@nu%k{6%M8TGnrcd69T`I>c6oieP-xk2b~rw z57>tKO9mg@(^R`?_gSj{Bj?0S!(jS4>%LoUrD75_FL&clj}=R445wQTG{aU<5GuB< z>TfoNUASC~vnzsWKTq<)k6GwGDL%~Fs-(`2Jjde2$~kJ=O8 zD*fb$(ogpMxqc!WDg@c;Kz=lqsu$2(Jg|SF@nKG1mEMWR83LPg=WJH;Z*%;zyFbR1 z{%3m0bFF)c-qeO)f?jf-FfZond(w9mT;TQVg|2pf;CkvOLP_?c4zm^*x_>sKodSD zbvqc9BI_N3QVwK8Xm&|9S886OZ#H`&^$8eohKoxM;%puCc*;vcK3Lu9&LcAv<* z&CSyZV$@%17QKCeKaV~XSI!=_sw_4F^mu&-*Kxg$Qmarxh>Xrbmdlp+&-T3q3nVD1`Oc%+&Wm= zcM60JIc+D~a#;3QkB~-u-9V1_I1DUeKbQe~h0c8Uk=bZkJY`{TK&!x&WQ~ zI&2gVb9~_iCJHtaXEz)C8F)-t8TbU#Ko%C&F*)iW>_s)~Xg)va4C8BRk**wPGCUyj zHIHzUnrKJ%$&J``b!JfsW}-BcN+qMUNiM#QzCOpH_m^OS;;ZUdW~gW^fu(}!3i9Qm zDt0)Z_y!+W#WKT2mv&n2rl^pe^t}Puaqp2k`aNoUlo6uRUi(kxx-W_?OuE zFwnZos*hQm5tQw#lpT~^u$@ZG41Ug$8TK=5xGL?gdXGZGvA^GZB7{>rh?!z8WoBtjz zj5l2uq~gC|cDl)bXDDBm%ZX$e{Va*||F*$SptCBIw z`COP7-l(Y`Y1Ubtv^!8Y-8&=XG3Ol>5|^4*6m%C)&MqR;A=cE6gbQ zN|;z)r>PHl6u|2u=haA|`dgk>4D)qWU(xFtJS6Jp4 zluG$6^I~5^N4UJGZ5Zds49*PGht=%P45ko|u%_)|Z6qhISlvsUar`gl;v10PKFoao zRZjZ4Gvi~SHxyIs<4qzkJF0731DG)|@TgcU2?4a7h#Jx;(U$mAp1@g_I3#tTu;< z1vwgVZYl03y$Wr}25smPbH|dhFFEI};Ek7ruFK^?msr>3O;bf%j+Z>`Ee(~%r@p0W z&gZ><)duPI!lp`g1__n{x1B-Czh!3t9>|&kJUkEkaW!GWF1|1e`uHuI-z->;$>t{& zdvS-Malqo7$s1=0=C7c~c=>8&lUd7a6E(coR*kvBiwk`%xll~?<@U}Fl_XgBR<8^c z)6INZ91GIR&53MYp*Ry3rFQ=Jew^R+F!IfBbkc4FCDg~ili2h&?s2ViO2xiR-tJ%} zg#pDMTSXtF(QRka#rv3Kyf#ey>t#=K@+}zkq5*({O&9*U29$LjUtk{)LBY-%2 zr*e#oolX8t%O#^pFdNS-5`!8I(&?eNL+d!!aa3{UivA3%R2F?{?5C%-a`pDUnTPE! z8syq?cIUqOA=VO{PKP}W9l5dA569$GX1|#~)s`0~dNq1t=Yy%yGdHZdLt_IM!i7=4 zj&sb&IqGoez|Y2Tp=~jjqYvqtXEs9q1#K{;hlwLM=**_`fpW19R>Q53e_lA9O3~A> z1BI`6iayD7{Xc5rut?c@AO zyGf6B7~5es#|+)MSJviytbkf%hCG+AIaohCRyb!8-)veecHY4Fi?eBOjgJ=-_2(Jp z`g}LCDfzgq{syenos7=v;%m*-g%_RTk_tBGSGu*5AJ7h(JI%Gx-FjF_1^z5AfEH}) zl|}iQE9yDP>+&M0B9u$B_sf^+>#3}cCph`yHJldfWmp)6a*8TAIkB8oul8ydyO?xx z-8Jl`_h+llPReilS>}(T53FS;^<3M7>iH`LWdkvq5+ir8IIMrGj`MelubyYsF^SF9 zv-dlxHnj7l#<{n&`po&}gQbw)zg0k9j>c}H|Fc@s-je^hTGAb?(#a5xRx{JhR8z}T zNjLJ?!6)Qf{X`+*9VN zk(_zO5k_s_H$(dR28S_8PbHOiV{b2=RP_zF*FFd`Zpw1A(I0Ey{{uS2u2p9Lzp!xo zrcgd~GACI(G4VicpIm4uwY_O4nRul(ATZIaZFZU`dVmVi-xtO+xp@{e$&;{?!d_Da z{$hAYd!uMzv25C?5mV~8UslTV5TkJxZsXx!jAb8V3<>@pfz;lI!G#WK&9H7_C%v}w zs*%OK>6%7Nr85>guMCWrystZH28v(gge|s_GauJ+vhyk@XTc^b1sR9De&c1{bR6Yk zG_A90Fx#jND(r=^s*yXgLYivi*1xtl)@;4%jJM0bu49;k&>zs=SIjT5X=H6PY^;r1 z={qgAx%lJP#b4iLJyr(BrTfZ_?=p(L&senbwPL>XJjUGe;yP~EO5SlEWp2?RdnX@6uabq72)~}jOK=klaF=2#Yx(Sh^7tTl`c-Qf;b7K?u5}1 z!{~D1a*PsGUOBqTV)j3-a+eGT`pK7ue!8aoz8UY2+ne7l5?r#b><%tD#QL$qBl!!^ zUT|wgo}xoM_EKvd!t9~y5D!9!xC$MD@AM!ic^um#=WY@LKg21ld98Jb6*!0Vs6)x` z9y$|Cf|keh;aQ=d2lJj5jj1wkJu(#F)L0|A`DU@!$7c5MM=7 zREKW3sY(jTS`*0oe}Eg5H(;fQ0~Q7v0n4}{6nljKxuj6qH-p94AOG=ITV{r~-K~%I zwJT%w=yRmy8}y*kn&GnF2hhVw$CqIl<$~iJR5Kb$a-mHhlAjC1{VMnp3abY;ATdHK zWCzw@^uoFsYX3iLjZthdu)dHj#>?cg#=tg1BStU1%O+zG3t`{IIBnHgnk855Gevjp zGk5JXckMHRLuaa!~f8Rc%jx_j22m2xu zw^l>f|6(!Oov{yMkyxn5dK7(#$B!g?xe&3imVII82VBNDLm8!Df0$%za4O>y!ET560KlZ<#beC zC4?A(H21<+)UkSul+;pa7ux0=I@v`X2f4}_SEJ)X3Th<%nZWcY@v9ot=?mE8`V8-s z4~zJbgSX14C_@>GGg{}aj(=#?BJHz&`1`!r~;@5ff!I}zn8`%@g;Z(PcS zWrnFI{L&e_5A4MmN)0Xf9=J1KI@{rWW4GW4A>YL>%dk?3%cGU7SQ(N*tL89Eq^$F$ogP$Ixuy=| zddqO}yKy-5eFvho4iNHxd&p7(Fbd}bIoMy`&y4t^;#x- zY!m3zC0@5y_$(VYVj5r{JvR5;=B1MH%y52bbRd;49ttyV!OaIZG?H=CoE;e`N3LM|loYJbs#hxJxHw~6j()jXxz zF{!QJJtcYSHQ|^InGEaM2hhLvIwa%t;o^xf?E|5_VM1Ux>t|G_t-Y3Q%_hG&XQ>u# z`7R#|`+0xN0mR1QW{)?*#ADG~SQ=2TrB2=$9mqq=Q|c8zNU0a>&p4k*nxBdrV0W_2 z&!zcSS^F??3AI8n#v?ZNX5r9mvUmP$#|gKXcY+lqPcmLs@X$6xDz4x#9yvaMJzkm_ z3@vaZ&i}=|d+J%D>M5=Yo);TC^uk#@TeElX4M5H9pKs1JdjgxDLsV?;4>LX*_NGnD zzMwG^K0^j6_%z!l0iXR9d@5G&a~Li7p93yu1QSjpJm1UYXYFEcJPvhPgMpjFl80XN z9B?>E!C__??hzpzR)lHIIk`9w=?Loa`KzPz9tf5Duf>}8ZdTqfFc9a!t>VwU#R764 zp!$p(q~b3p7x)_#$agx4wO+8H#6OIB9A~h;V5}skUHGS(_s1?9%^bVOCu(f7=jGwo z^XSX-vdq9AW+H*VClzZbH?k{ctuwIR8M)2}9fKQ~BhxtI0_KV|ZjRlYdexgw7opQ) zn=&_Nu3%+$4}(eA*MHjnbBI1v{Hy{Lh55IrDy&_t6nOtCrpz2*EztYL7#Zr) z?NQ$-R(x+!f36!sUX&XAVYRVh*JOn~ru4ldvcW2FKZzMei#eyk`OsB;Xf_U%CSe(X}vUG`SX6YXVwLyOg!xtiT##4*DI z7phIhiz=R0+4aE#)++V#I`GrK!$E<4kO$Mz3|qC)_=7sfc3n;Fec-%`$F$Nd`v?cV zXT)VjAHso0Em`BXW>2CSRBsV$!*)oqMturOs){4BN7=#Mbm-^~=VK z)f(ePibS!ZKyYU8;~RnXn@#>6%W?Vz3;b}GEqwPbTZ~L4Wrm@Z&~se# zKi;C|oX*{DkmTN&_wmE%6INOQyHcj&UB;sI#)Zq@&Vnte@G6H>*YZf7X~IcH?6M8S zOmSw|Nu0;mqzI)fM0P&a8g=4!5SVQXM>>7~rn zJRT~ChI8V~2E!m_rp9b2tAAgaslf@Q8j=*BXG+HHPD!`+8gbg(<(O{;4su6U=XzYr z8;Mz|VC%?94&OcC^n31iQd~ts7}s9QwUd5#+1n#5@I>1%n!nPAO>&t1BANJGZkr~b z%rGg+!0{(`YUob5=j>Qpe0`@TD4W+Cwfj8exu41gRxH%R!lOIye7`ss z>v6CurqQ9FCOe+(s!^PL#zgXARkb~PQ--O z*xS!py{4?W`rd2JTu8Oa(X0>oxq%SHO~9xZh>3J{kavideZG=Z9y0G8F#m8MwhL zq&mJ9J8IHTpDeBBDsINqFRc1PksyDzY{e@5UsyJsC2pRS#?eXQphO>)CL<1*7hdkC;!R#ezK!}_ZB zeK8-qfG|6$UjjNYHWKqojy5_IyS-mS~L zJW{0+>jBLC?pgE^aSF2sxXKD>{T`cy!@Dt4>+LbJI!E_YTimP6h3iM|-QHE$_qV-8FFjr-tGD@*&iBoqj7xKOZfZX({)m#%~YLZ{Aq$U7q<}* z-mC2;S3#G#4WP^FR~s%9#cXmsiI6(>Xjt{~x|?IHJ+i;d*$dkxt&qtJJzP36r)j%N zqt)S!H*u$?i$)Lpjz)neZB;88CAmygTC?3vrCi9B-D*v~*lqSNR49q?^-xwCcINrB zX5*wh8cn&iCZb?fbDCpUbtlr4h=L_(JET34E|qU=%Jec49e1jh4*EjZIUtC|g&o9a zjv25khoR3wZgZ*@wN}w!)|AltF7LgnPNhH4hGgv1zt>@+V6Sj#O)|8m5|^eD__<4K z^8CHlw0$FKO*y1BS&bIS+Th$pCQ2lPxq4Hch)YG4nW^`~jG`owx*P(WPR$}{NcXc6jD4nW99sTg1=udk}Gyk0a z^z`8rWAC4?7-mtW+ z!0eP_XMs$IRD_gN?H}H-cNj0&r3v8b$7*zv{+Ne&qNc^tG7y#)zNQ?b$#EXy*L9G) z8ya}u8n)^Pjr*Yi7^iz+Jrl<6*qMt_x`dpm1j*3gB&|%zJ)fj7>hMjyrhT2+c*XkIg>qe-u{a~-Af#^~*&?!tzskl4_~v1sdtjlxWK-fEI@Pc-Dt}y*dPq! zupf);KCoKsxs=~)sX1pC?1J=Uf9aOhCm5|VP9s)EbCPXW6OAj>7BoYHKWlGa{^Sx^ zceLkPBre$`ND^S~^q%W>s&QV{d*BV3;hDh&e_+R{_?)a|h0sOOALY%sx#-M2bgs1W zorfOAcV@TxPP6Yq?(HnMJ~Ktp`GKEzC7oV#64n@e+wq5Cjrjmy0(;h;OIf4ylrJ5! zmg)1=u*Wj^*v+6S`l@13`3L`ruY!JrucG?pW$h;V3V+){ybE?)@4)tw(O2SftuDWI+fp) zDftgz;rq=-!y&T?qpT6d00z3d?Vk6Pa71q;83Mgdhmf01ez4-> zna224?lFD{X>e1GZk^X$SdaDVbe;#*kw$LSOUrH)7}JsS7mi*zT!_@*%L?}OE3{@B z4E5I+XE4@lNdVRdy}tx~75hES%^jKanm-dgys#5{9d;kfgSO&tvQ>)y75jlYVueIA zGia+{HQnUOu@gbFt1z=n&M|09AfXr&$LKZUe!VUrXR|du%6A|1mj&2|F<}og7;+5N z2_+b5iRTWog1o3a>tg-l`WuTgauy#RhB4Vf0%~>2bOp$Mka~6x( z1ucf_*_1&Pm)=(YRo_f+pGKT*!s5k@1>kmS%Y1X!+(>G1- zbe`6vjl{|N?%Vxn{h2N}>ycpA)JZ(E_IdkRMTHQe!8V5&+W$e`3tc(f9&^g?Vw%&^Jnqad@OQBu_+3cb+;mq7G_u%QB(A8y*vDg| zRi9N}@6_wpdDk~r7nNgVPP$aDBGCuuk>G2x!t|^<4|W25lLMow%h+uNxstbR)sJ~$ zK7m*wSzODW^J}j!&{to;=sryJsa4X+Mx0n}lyhou^O})ml{Gl4v#OeTYn6aGlk&Hb z18+RYGV74%#d55i6O(E@v&wKzyV0s&XRm6m{(;U}mF5k=yMiOF-$)IEpnFO4%AMvM zLo;e*$XcgoS#O50taq(U`|d%OwN=k)w}#+EEGw6_@gUZRglM|2ozJuz4?4TQ8I3z~ z8@cZ5>$vV4tGMo)%en6Vn8mtp^@jus({$fzbf!683M?=d=(}$%Z?66kbvakp087TN zZ|iW%G7}e7Xrzz^XJ%NFzbKK$#@ia0c7&1fwsO|1xH~g)ryRVko@Iq1%vg_a>dvZI zwSNP?h-R}$6Wv@)c&1&dL#^V9a^S4*+9rQ3#)s7%9fw|kX{O8mH^WC4>>!{O1UY1|%a&SvncfWe3$J}4X!_OS<@(k&>*`MI# zN~WI6tm>JUw!M4eR*CPP_@fff=+qMD!pQXJOKkUy!&W#-%BlKg#KGq7<`Tl#r~&S?7_j9F5{UaG-sQxXy879xwVd&{X0lG z^H!$MLN0yz@>-2`KF<623_3roI0ZBDuCts|rD;NF`4}}+tTK|Wn_&)X#GceHdnsQv zS5QCfxKd8hb^QpvJ}a!=iJCCl<==Lh=wn1LHfpSTEvTB$sa5XMY`awS!K!nk5j!yo zs-J5lTO3)v-1q0Hvx{{4MX%hQpF1|;L;>5X>qCnvPiv@@yXrdST!pqVYNTvm%*>jv zHhTB%v3aTfDYIuMmKAox`Nn?UcDw1?8edeO0eNT3WD| zxD*eb)HJ^BvW0aH+oDC1t+BCP;EF&wxdHoW8ra7#%iqsnVsUaCv16rST;TCL->gjb z6z{FnwF_Ahaz~m1yt%JZGcM%#oo`kro5c2&ns(tU!tY2UC7Yhsf1$7Tu52*-8#t*L z`!Ks;bQ2AKm4V~+je?X`?_F>KoSeNxtlM3;n1SLsN7m@q0P1|NW#pEymbTWSlza=8Ag6^!1Nnd<0(ggtwPbxan{?m zv1`$KeaArDAcwN)Ys@@Jn z{Y71MAR7*n+<2)Wl+MQvG?Gpnr5nN?oy%&ar(%blRmTC=_iu36vcT=l(KUk5)?elHu*zBMEZ z)LBrCzMli>6KY^Y=>(%)zS6b9Ok6RW&Wh3$+E-yyVMQ}>4wXthE~Wc5O%OdQS!+t= z>Yx*&$yE?{6{Q56$)<)~%Tuc}T!{TC*dQBo(JPGXZ0Y7g^ew9cv|wbM(wipDzMh>`R{eX_n1VWicMP>s zt+a<4ouC6_)(GrQS&5mSb|y`Ci$T%Js(m{;FEn@AM?IM|k;gaY)}lANQ=rdRcRbNt ztur+fuDk5R7l)2^-0E|=f7Iv9B`nil?QyVkU>yZ0eC@FBR0^NFcGy?2(izmH z%)qEVEN_{(0@gLG5WDl82fdT(7zg?xO24#r+SjV(jMZ%RiFF9PY~>S9tA&v`#A}I0{3$Q?&$4_6V2Vv$DBup5ipcR`5%Y> zM62g-;V00!-k*d2e5>c5;J*wox!#li8la8q`6m2~eKyR;_1v!R=rDpVuIDb7;3sfB zPluo2pFRUGv4DT|etN6-8*v8iA;1$0)$i*9d_D+x#`R2og4loZJQ(kuX!V}_1hZZ7 z1^5Zv&m-U`a6gZOpTPZm?U$p&s7}l0sr5O8x_%1i>H2>19|QDuJu7~s>En8)enDwQ z-Oq%19koIq^bP70)OOS_s4tMeKV0eud>-6-7MUT#0N75T}fb|OEy)JEiYw-@=Toe0QJ?Lt6)Y7+wT_eR@L zo09*8GfDwXEMxaD143>%e{r67e&gKl+~M5pEO6SK3!O2}MRTW(9roD$-uD=_8V<4U zWoG8ZOs(R7<^04cJ2yI4J2Rd0o$=16ofd8_qkoo`e~imuxBpv&jFp`4cjwJs_u z5c=(MG96=`Sh`NreDgjwj>Y01e!u)hiK1mi>=1j2n~ork^W?nQ6L2|>UQ!mBHyNw+ z(+VC1Acn;Z1T`-bonX00^LJq<-UVH^T8E` z4^igX?_C*osQKtHj&)$VcdiWk6n;y)x_{Xoo%U>u^>tvQqPc zc_sCfMmSW0^ZE7^8+~^;g{)53BJ5 zJFD({X4TDXuey7@RrgSyn*Lm;ilQI03i{u)L=gx_u0Q zI}wl#*a$cT2>M7X^!`9AjM}ah5&@e5FC%Ot;56VPJpTabQKA(N0KNny?bZri99p42 zU>smNU^XBJa02ks4z2JOAb6)%_!w{ua1rn((skIS6$S!c1)Tp-EBu78AK*`b|0TfW z6o3lK<7fOFcmNxa1qeCNGrSsI0r~BMi{_rrB;{;xC&UjN-L}fYy?ySz6N{? zI1L!J8s7-m0k{f?d_^lP0F(iK0EE7(6~+MCtbrepVATrwfNg*;0hNFg0IwXakP7$+ za03u(Lp(soC0gNoz-7S9T*Luv2KX%13LgMGmuZEOfaQR10Y3q50+N^GTLE42w89I3 z&iSYp;549zT`LR)lmU`n!h1jwU>iUv&d%3fD*tBz|eJQw|CGd;NJHStuW#(w87h2;S3;Yy;j%<7`hSZwxG-n$YYaM zSg{#>2kn_HcQJ4m19vfS7Xx=Oa2Er2F>n_HcQJ4m19vfS7Xx=Oa2Er2F>n_HcQJ4m z19vfS7Xx=Oa2Er2F>n_HcQJ4m19vg--+%#H97q3jrZ(-&ex179-|fMNAL$)%>Cz>3 z@4fdjPTPj*HEr8sZ41R>3v!r1@C(3XW5RN{`v87RRTu(y6krKpdI1x3FEe2XAQZ3w z5CM2$B@@buZ@JIlxiu`n^9y*t{6i+p04&+Xgk2vop#%K7-Kx9bVc$wRG1OAk_)M?`Em_$ola`N2d2P_Z8db0Q@ABycg zGdb=#a>baWX(_33Np64Kf>iR(o0~9AoEsabL`{g9l>m ziF1>a+#45B34^cb_LH+Rq7g7C+tF%!|uq!^jQD3;SX-Ugz zkQ~wR9zRNl4AmUnkIEWydZqMrB}U61B~D931os^@q|f6+`V68NBhgHj!Ipk~`t@ae zzkYpZ^o?cW?D(WX{RU1;n!PZ2?wlc(hf;tg1w2_yT*@?2oD(1-E%~4Ar+C?n)L6uv zk&rzTK^XN&RE z=A_J0>K-&=1PdC)SWwW2prCyuukwfTMZxry z$jluTY4M|XYEg`;p*$1&xK|^be?%kH4$}yUQ#8WL9F6eWJy^rv7HiO} zIpIsdvvJen=EWr{gbV+iIF$`C^1Hed`BP(3o>lr5`QzurCDTJff(V%ef|!<;6pH}m zd2XWXNqr9r5$7f*g2gMzl{m2pEm4%`xI{5|VUikw@|YPHlM2Bk&PEagWaQtfn9vpO zOFSq1y$xfymPdF2ZY^B11-rHmF~Jw^2OnU(0QW!>6FR{SxXOgiaB+m4a4*~*4NS1W zU3`QI4^a3gOy~wT;4BmR!2QQxIH4ch;NHj=dxko4oZtiZWw?)`yroViV6!Tl%z$Uq z6YZ&d6#2nQi7hD4pB`Ysw$0FuA@3{SXTlEnalZ+hejMdsuaSm%vjtZ$CP279_V2v* z3llztzb&-n5x+8l_8@Waf7If?hkbny=Ss`5pqoq(XwMSz48XU#{laB;T8>?8@#~oZ zcsqyq*k#HlwB(~@J6h$lzKjXSQHPF*gUwVe{*{Qo5oxukj|uoz>&7u$HrwK_{Ei79 zx#|;p=9XXgh&wIEG`(*5KZgGt%ED#n?2OD@`IDsmpZh6omLMikgSl7<3mTx1I`JQ{ z3WfcVU*&_u7Zm2;;twiYp#Iy^2O!&9I<_8ro$k|ef`Rrt!M#VrSaUm0Xal!RdroKz zcZLpQH@MI1LFaHkL;vuGJLD+Fjc{?qwa^~!h{w<$;g0-_2|jQ`KSzIuyUkZ4z+tu9 zF*XJIeyU)C0q%%?oM43eX)_Z{a1$z--~spJYfQKYuI5uFc*0%%Jrml(9fkB>aJvMc zesFV49CSU#2KM0u(s3rkh04d;d2j-$Q@h~m;hGwmLI?BWlHKGAe8f(RiJhn5Byyr< zTx7WAuOSm7ErG!kEWv@1fm84}hD4_#KRuZ{&WPaQ6z9&@E$>JDiTC4&2abstKki@U z@w<0a!Qo?|dki11)JV}CpfF6aL{1tP;;#A>OT@&GF=~W~!~g9kDD{g^j8_=$b%~EjotykS z43R7%2?g0PF(@k35|sp1InJfa_O^_l43zh_j0u7R&Gxo95fg($#t$E28J>oLN+OhS zXo_kNhzLgX|FDcqo0D{BDDpxBkBf|GQ7muEGkko6MS0Wm8f98W2Trt%3K`le+m! z;PA+4RLGrOgYcQMFi~OR|E`Xc#tc{U_;2XMRFBj+bpVx+FsFrwlHW~Z~JLa}a*&S=-L-zkj%wTYE|qY=o)a0adc?q#?pxXZuQ2-u3u`oQ&s zAbB3)G$GP5=YF3cAGo@c2#5RqF_Z(h=a(o4?wgg! z7w)m0c!vDj2Nwf6RZt?IKl@wz{*_?~fENJU04o3o01E*2B}O`-AN@W8M>$ef0)Va4sb=Kv9yK8@s^N?h_MkA+D{#uhmIfJ5=6L3o*$nyEjBqG`iH^` zV^UJ$$V`%=aPy>?nKhZIE5@X-kby#b#Bj`-gGoQ<%JuJ@PW z`r!Rwz%zjL01BhD^i1*S9i^do8GqvaM;&#-w}6{~E}eA36M$#_1-y!QOS+&ez#+hS zfT^oa==m>THsWMF#GYcYdp3^SkE439zxvMSelrI5A3SIPi;YiCU1*7$F@!qPqqqMd zg6-Jcp9MW-2_79d1g1`fY$4BeLR@Ofw78jRDb#V*`VGBJeRK(qnz;goW|r!l#7>j*pxcIx2Ad2sOGAcI#1z<4*6+ zkiN-fMr3g*Nqj$%e>5g3zVD-C?d;RHZ{J51Y_X8>;~tF|i@u)X3ED}r@O{W0+K&aL z#V5onq2P-tsf4fvmYxr#Jkoo{+_|kD39sX0=EcQY#tpxPRoF)pV-n`hvZSOz39`(O zO$FZsCx)Fed9FoFN>d*#GZtD#Mh1o6%7XSa)DgS4_(D5vnfAN{l17C2pUV$jW;)JY`1f zP$euSDgMqdGBMJaz+D<;5bvt1>ysIJR^iCiHwLMQ>~hfJN@u+QEGsz zoYv2jzU4V60v&K{RHQ38)r;O!GNoRw@>}AMk0Nzci9*$8VWYw$hmW`wKO{7YEWFA) z>gUv@rwtzwJ`Psj@gb2)->0T;9j4%9nmZ>Y8q?+DJfuYMy`j*5`u5}d4;VOT@Z+uh zF*C&2xS7g zq7$HRCsHpb3qDfamL{d8!Vs77GvmdWR5GKh=6p{UIBOQVRSIM&NNC>NXX8)<(sg13 zED_3ctmWCbg|1Ig2CHewNpmq>5E40ln%XE&g-n_@E-GT&STxZ1kl|4gAqvx&791WH zGCtBZru|)=@U8RXQ)go!oSFw@Kz?(Q65=eFJ;A)m+&NG@;!|2si+B?h4%3>kw4gF&2Yn}LBBu;CmqYub50C2(pZQLcORpt6MTgpE4?(>N(WQfV%f^~QW7c@@3T zUEe>T36iep>5%Dhvxuz_LxZlQI+nSpSwc*b%I8Rh!bGM@OH`CXhYA->Nt>fEB(T*0 z%kW#wkh1Bw027@G*HoX7%1wX2qq!lT>{e=wCtPTy_6wXbH#rr;l?n|^rO9S`qA3_f zL5N9QI6r1#K!EZsF!v-cbbSiNe>!|Ddm6Hg@(G4N*yUIBsEA-Te$?3LX>i9vw;CTA zp}4{1y5fxuAFGDLrSKDbu$~5R4safD8E_52_F}#O&<@ZMU;!}pK)WD|*e6?fdtBM{ zx+GKPBLyShc=o;Jd$)Y?+1X21`gUliN$D5SZF|IupvL6N8IMaHv;HnmUbp+JSNA)A zJzYKH!QuTaI?ksywmkK%U~A;x-hOI(Ppe1a#hTCS|8X#{V*J459_{`57^>zq%q*Pn zLFiu{&u{2dJlOVKV{_e_s*lPKjHsEIGke1V!4%U`)3f{FPY?fmGXKK6*GJ^WukzgV zm!0*KkB@XbU-Y-YYGj|*R!xa>bZ?EKF91ltSeMjd>nTW{?X z)7u1g*@~-le>!^fRIe@f?4F$$zNYxalEjLsSI3x#_6vCWz9g^LogZI1_1(?S?=2nj z?xfcj*q0P+$~^Mkk8ia3;?cchuFO4~(e4eluTQl_H|`-JG-=lKomnfT-`0ICKe@ll zSBt8r{`#Kgr4GM#`?BAFAfJf&GbSYeu>F&_Hx}kv6YIy;^sZ=o@caJzA6)B`shgP^ z7W-hNKKPprHyo>MJBp{(z1Y~b{E4csdi*l5z_86Pdgi=&zM=gmj5;~zu-Em+E*x5Q zA$RG{cQyr2j2mHC@bK(C9nYE;4_?a+2bT3|r&(q0 zG3(uV{eyQ$joh;Tqlx)nyq@@D-HjIx)t}7j>uD+I&{4Z#e!$G_kxzttvODM>Ctn+9 zzx3P8ADT|29@YirjrWUrJ;|cm!u(}bTctel?v+lR@U4Wd2SM_BW8w};;8-^Z}if6S%w=4U>w zIQ6$p)jJj}z4D4J#cM|4xGsU~2K0LHJ-@-m&z+$cPkkGC^v9huHeO$yw9J&9S=f1l zRMLCj+g}Ym>$ohK4tI+9%Qr(}$NW5P-W=x(xht6U6-S5lTfTg7f9aKhXZCg+;qldf zOzu@PHDPRH`ilvkZ)bhbF{hw7pnAhEPwd(LMbIOk3?Aos^4^(qFTI#Ls%gry?V7h% z6}7Xy`)iNycOUD&cmLxfdw$V*;yrbX5)KJU*Btjb_|ALX*6w_{PgeQg z$Na5g;xpmZPyVgzQUH9q||6{So$sWVoemhTRe)ide{_l^@>8u|YcHfSl zO+CCXAMRFJx%9D^PoDZq>?>^se3f&wujktQCwA{1J2>f^_M^(nj*YnQj1;n|DI)M6 zTYRV8yY2X2_Z1aSNLw}`;?TfOe_QmI6N&5Fz9P17H+hzi&~@RuDc`0)|M%CEj?SE# zdZwiN%IJ5#e>Fevje^HtnqK(Co`;t$J5_6s`0ee*HMOxh6aV^`k1vJ(uxsG-O^(d; z*>d)yk8R=mT-@}7-@~Or8)hMKb-XIvE~WePK7`9+{sb*4lMu8(73;w<%7=( zpG-T_Gh@gvudn&7A@su?zg=0s(0R3C=-J^vI%`%R{pkFo$I^eApOn*o&z!J6ou1M? zxpl(9$KNq5ez?oM!@D1Rk_9AN_V)UGO@4<38Dst4Sl{MezyGhjFM+3Od;8yKFdtKf z2(<|%WJr?nkfBTwQIUCe%+kb7lxUDLmXZdVOBtff$!(yJM1&+NiljODKkJ<1cIv&q z+x@@yegE(0|9O9F`|dUDXFdDbYwxp`v)6Y$=UU?|p`o3G6Ynk9VwyNPZ#UkeaGcHD zP*CC!?VlnN*1e~7UFYM}Kw9;Rkm3PB58{_5pDNQME}Tv-Yno%E9DUrn>^xPoty-1W zEaT-7H@+&`PR*>(JBN3Ao%%E}C(pWf;HX8x(W)nq9I#qwlhc;`yCfnzUp? z0hRdoysvk>U3>a~G1c$zVIRemd7EFR4N4XD+FPk`B2HAmYbmZGaNc--zax8t7$vrvh!1p;< zP{699NjNP#ReW~B3MoDZl{aM;uiv=^o&WeSl=ig+SM2lFdpS@pae9b{-EXAi+MI`k z{DJ%Jv3cDghrJ#JG|sMj+|*Z1et)#FaLDb}Z+rABZlz3?36zu`-;%66u(@%^7Y>wk$Wr!aq9IL{0D{_?e5E(Na~( z?y|}^ykA&k3%WS05!n$cE~XmPF1b+e2r&+KVRvGe;u)6c;>dj;F>5+s_fmk$G2WPwyE>Wwg}-#sdcL3L+hajKMdgn+uPY_3)hsTeez=4_{~4+r z>y_O3USGB4Iv`#b#IbigAar4#=ZoX%UODQCoqQ)syEe{z@t`-cqa{<(vV^N5`qFP4 z%B6$*q^eT91g=Pp;ROLp!^+-v8&+s!s)aZTjRf zF?`E==W=I)a0iXu(^HTC^E+P7JvZ@S9Tx$A%YH+*2jOA9$C~>|x@N6pi;3;LErG?{ zd7n=eFQjE%HfplOD zFOr^JSLkpc{pvmbyo%DCQsP|BL^jvU9h7?67d)4CM2DydTKcUzE9G9Jr|eUbV%QbM z9@a@H$6K=I2|O4{+I}f)R&fb?UVqh*1+AsekKN+fpz#UgPd>$!A(qAWag*h1)}Lu2!G2BmM4o`95{KWZmjekjZK)C_44<_vw0ttGDtN&DU|RxN@F$wHl8v zeN|Feb&%3mLOR%TDRQydgO?ZAw;UFc?{ zt=aTQpuzmHZ%9wsr%xl5$xAA)On;DE;P(7@Tib7`%}48M+qG7V^(=qmd#%~mu{{4V zd$ECq=H;c26nWb%CAcrXHz#SjZ6X_9A93qh+2ea^Bso}ZW2L|8?n3uFGva;9b6Y~> zH2eHkq_3wmkj!|lm5CB%ROH!KR_a{6F_)*}^8PhNisXPo=aZ8UYt`;G74ORFP?EaP z?Nm_fl`TK!Ieh4Nz&h^KAmV9uu0sZzd_&uPIl_e;F}67Ks&wH^rF|C^FKyP6D4}F0 zx9sPweDLhbNLRFUPbW`n%l!nSzScJ%3m^Lh$3L3YC|bGINxtm;ll285>&>o+4Xoiz z3=QC)ysg9Twm%HLL`9jy4whkYj9_px0`y#sw<)?4tTv5JbFwO4Pe zrWV@eA1{(+(`>q$%KorX!Li%E%C}?o{7pWErRMH+LCF%sH@oSKRhf7xRx66<)3Qz53SO&aMY7lONx_f7<`*<&}c6%CqP4j_pm{nvj}y z_~0B|VZM&;LiJfwhpeVtjw1fi_e@cz((YuNXx6t)ze;}VZDrM zwqm8TQ&iZ7EdfDZp8AVb7s<#eDY6qd`DaK83tc#!d-8H|`L&FFSx0v6*%sg3(e$wP zM#G(fC(lPdPmI5XpHc|t$mn0kcjQ$xSJunTl6xkDC3b%FpBDedO=R19U#-)f<^~tK ztTazPFjmWLSt48fyTk0u)wc7l-CCtwe%CehNh)#uKpNX`BZny)pC9C*P3)Z+_&HJB z4F!HF(*piXPtYJ=QIrv})pmKy`%=94}@Y4&xR*LW>itd#Q0 zg!&cKH=xfq`i!FU!_+n11~hk$=FQPuI+`a(bGb0Z2ad?$+c*GT*2vcE7_ms{lT~j(xeI$?W4QdN;364z%NC4ng zV6y>=fCT^@z!HERz!MMwhzA@8Tn9V_AU@et5D=UO978U4ZZ;k=g~UtbgDLx8g{k(L zil^FXDkgyfR!p_qRE(~Z6|Cn&_Y&zvve25GToAaKf#;_{`9_WwEy*G(jl z2xI~qft|oX;3ROt#tj<}Y!ujdnHwL0vGEfan*f2a2@-zXrV)PJga|)w!h|0;5yD?@ zqJ+QRrW5{p6C?cfCQkTg+YG`#+aw78Y?CDXlT8YB1N3Kq>aqX%QUBFb{ZAj*Uo46I zZ$JDGmt6jTUmXT?Sg*>)h8h}O%+wN6G$x=hH7-oWKMfB&zZf1UzZxD`NM--2B>z7Q z%mtwTW0BzhaG>9RMDgR|22vj%Km4yEBrGC2T}*t2grwBWS-7;!Y*{(^Idc`}DJm(? zSNYBv(ALq_(>I_pr~_t8mzi5wT3Ii*u>}spN(aYPtJgR=uXS;CW6%wJ{rm$0X+gmu zp<%#|Sr@f_!^TaUqho&C61z1ne%tnh9f?UhckSMjyfV zE%#d=v^{L^c+}bTxVxwKN#E1{X9I)JU%VU|e)W1}^v&4Y@ptb(eEjtJ%h!o-lmFYp z)c-&Kj{ldo0Pdl5Pa#(h!)3*71zR~ilv4D*EmqU;Q0kFk6Vs>MQ~0(xS5raloDRHc#lj6o+2eHUL%yvJHl=&$R?I6x>nd$Fq_wv z>vwW1r#>Z#$DO;CbAE6PfV@=u>Br?fy@M?+bD)|~kZb@en=7U>(nVm?>k$k932qJ?CtEI=L5ewj@D z3>XF&L*5?X2H*yiLRm1xn*e@AWNH*30gwSW1E>Z}>2+n03|#3%08dzhS4^h10D1xY zS@4=AeVLj5%8WTnew0P^M4`-+76>%oC?;z|DU3Da#hUSqP-V^f{cvzS;tEeGL0^S| za06fOaQH%w$6}ZpJr6s^+I^g!`t>fVgG|i@R0BfRMY__t;;5w~fyp7QXAKl@3>YY` zJ~Utl!D>lhEcphNGsT8PLP?3$HnThK%YXJ=qxCv zvvD8+yiq6tHjXy%ZIICnAuliF#(@5euv{x$C8+!9`hU*T+W@`lK%C#HGiiC@I9fNW zC#U7L4vGpM6w}Wy!D7Qo9@Ed=2 zz-P5nQw6AD_8?;qGWH;24>DGE_J;N=?J%n)hCrx=yuE{=CD;XgUrQ4Q6O;sgS_E(- z=??<#4xb6&ha$HNz-IKNv*CU?4oosQ?Bl+U7D=y5qj~$f(}42&hYrjL9`wM_5a@hh zjS=Ex|A|sY`H#xzY*`gUtL1-I0Zztp{D+Dr!BPIemJ345_JCSTgC#uR6=S6`;`|{S z|NOY!AIDb!wLBas=>J;Q>JM4gwxIVZ%$A^E4@<#!TUiR>1UH`n2Mj>0A-Momt@AWP=78!37`tl0B8Yp0aSo7U@5>7U<0rRtO7U#+yGtx zKL8C73Wx-307L^~0owqHfZc!;KpG$ma0rkKH~}~ZC<2rNW-F^I;&5$#G)v6e$JfNv z44!!t6Ki{5DAPS_{J}rOFclB9Fd#z3-^)kEGdv^$xPBotWot8)`Sb%SK&kbNTA;2B zYYvpXX+A0u;hrkN-s@@p9#at{Jyjwiy--m&j0=oD?)&$!fBgju-Cqogg;@j?Mhzw> zx4>)y77KqUhIs`PM(AlqIVv56eC#AjF~aDi05e6}v;reU69^Kp$QzZx>wZjDR|v}? zF$Dff?x2AXw&`!k4I2qzE`LK###9K_q5t~4!nRpS^)PBzUol zs-g)Va1w?99>>T_Ip>m7j4B0B?N|HF{aM#WqkFsVJH$kEGxb8>51l^@6gV0tsv(E< z1LmTy8xWv}`~U|br8-Kl!9m}{i6%dxnPBkI!PFng-Noi?X*yjmWvRxeXBWfF99UjPCQJ74p2058n#DK;U>6@IhlFnON0V>R3Ft7ggp9PZRE=Y{nj@8tTeq`70Qu* zN9J+CublMX<))wOE4{feVbCM=RftSJ3IF?mtngPMwrYq`+U+YjQ4)?Lc{X7|`fqn5 zd)Uc>q<$zvW=fG6{d~oQT^n(_AcRZk+hXHS*v@j#W$<3Qi;<9q3wk z!8SKYqjU2y^`mlrmU9WPlna8MP-fj}ENLNJh%b_GDfeTH`g*0k^31(fCmSmBaV!6hdIFW?>2qF7tF=dcE z&a@4srEwwp{X%IOT!_60d<3ENY^FSVW@K?9{TV=dmTm}%73icA^Qc1kR1WfuGA!+n|hO?VY%UF7pfm3i%TkXB>4Ms-|>qXEj0 zZ3|e+HNgH>C`UFdWU)<)<=N9_>POeE!(yi{i#>YGa->He^mH+G8i1Z*C`08`mS@Qj zH{#{q#CYb7;JHQqppeWG+(_GHGe$*r8skL1VW!O{Ec#7ZuH6hi7ay5*m$IanvB;aV z*lfW}qkC`3Or!f~#d065S@a-&3_ZZ-oXAXbLYl-(qvw!|nMU^uI5mHKPQk4(J)rAS zrZ7JHs2@-RM_i~3VF3l>5CDBBy^unkIe#OgO*T^){R6Tsnj-i|KjX=wAG}y$iKECD z78gbvhkh6Od0mK+AFF66=fteAT!;;TQ9^|nBaty8bYC`@64pe#3%whCq(a>_a+g7Y z;XnXJ3Sk7`phyCT2M4~5ECN(hLV&(n0|EMQT?F9Y7$d-?S|R`!#~uOtY-a@Mv%L_Y ziD(GWXGcPRy#e~_XkqAfMPMiqMQ#ef{Rez6NdYcX8uY_iz~4C}iD9`?FoeKjlT))` z2*JU{lr#(-G8k4m8^g+FVWg9TAw(W|2>UM#sA1@h^M9$+jZlQy@Vtg*tY6cQLdzima&e1S#(VcDsi61$TAybzA0GxG~=8BK6~h&sYZL1q=Vxv6+}K46|f1{09I! zpnoR|P*IEuVMjt^F#P~n#~1l+TJG@q zeD_MtK|X?}mp}3PJ`bVbu$>L*Z%7M`H8Fw)6oS@E0(-1xWr|KzRfUOBmZmIcob~%& zNNSn@+{gbANXSZhLz2m8ePs2wM);qBfQ^6nJb{texzGbgBqOHS^uV!Zr6*=acaaMaq?RUF@rM0}zXvVkfErZGCL;TUAId>Hu7pMi^bt$>y zN3B})&X!g7KbZ7G!H@S@W-nV@e%4d|xEuW^()$mLE#2IG)F$Kf>g!@WH*7B-KE|qd zr|Gl8JF{fW!m?frjyWa788_ZfrVI^lu)aU-++3+zCsx_aTBT(Tct(F;fMVm7RZCqe zCX?(((s?ub47(zoX13|G%AV)>BCpeNWrp$dtmLfTBQ;M`0z@vPJ&k(qaHd>(Z6+AZ z>}udTq|7S=O?yIeqhjWY`EQD!plLKGuOCS=d|II8Ua>NM536jdszQo%=Mob&X~)I4 zF4*6^d?HlsZb4oD{193lZ;w$btL&L4VSB3#Up*<}UcKEhduZdXVY^f(U5{=(Bi>O- z#j#>m**7gCGFq`_HYsuQ&aU?u4r{RX967GB>G00)yS;Jyu;Ln>@JE$T zdxa@qQsvkdRLH2u_XV5uCC5Ao(%--;D;%(rav?O|?d(h`p_8NOWqHo8=aaNK3cltK zWOng_3mq1{KI*+rN4rl8cE4GgBvNo)*gyEJ&hGbRR-Uhpa}2+Dr^hO*bEB?=NQq3a zy6tn#NBW~|T52cPy7`|Uwt5T{?>KcGI<)Wh9&PZn^R%g%6L6%3l1~qb9cLanA88H@auXot4?@XFkLG zlE>p0qOWw+^Y?CMmE~IQnk#nBkpGMa9en)vu9g z-`sPg=dDd@*{hwIcI>-o!&eBlHFbhp6{!YM0#xUW8vC*R#0`q}zOqsIx`moXN{>o{w!{mv>Y ze>W$EmwbwxG|Q3iQ4O1BLx|I%9lB?RDW~H)`okgX$B_=FBh5g@<`>}$=W(-F~O>r(Bin}{rKL+PcH3i-e5jx zsB5a3e(1*Gr|%5?Y%8BV*~cnd#%_LYCyy4MaN&wcgsH0hyZ9r!=X9MAX%uYDcp6af zidA;kybr!BdbwyXDHu=H{FnnR+uJ&@sN2yd@(r4Y1UO%_%HEkg$o(yb-RIux^Jco1 z*5>((k4p<&cQ08ZxRA6mWZGL++3;sQ{d41sXx+TKPp?WUtmioM*>=(8_SA?i!D$UQ zK7L}A#Ye0!riahG6ttJ9$1QtKZyBk#f#r&=B*}35i8;jO!uE`j$Gyv==E|f zkLz>w1xc*3LXrf#?XLLlC06fNB-Gq4QCZbzY*QOx9I*`7>pHXK8LMn?W#OD2rK@`c zzCLr{K5}`kzr@w?MiIY+d7&HfGmnLav&uSck=F>=EU@d-mx(PC^@aWE)>1jXxlc+C zB~&h-H%GgORW|8q()^Z^!&iC>tbBJ&o4>Brr(UV|Y<%b7+B)-~L&)#!_jb^fb#V8- zGdo3M?D4a*W81zFiwxpVnnsl_E$iMr$1FXMRrd3!ga7aC`WJNuTWj|X@0B!OL{&Z$ zbEtXa30S9>mpH&GyKR-`=zb~EnHezz|i~V=miW$0% z`K1R|9k@ar+Uz!IZet+O^0e?)q?YTAYhPE^SqZGitQRWypV4xfz;4BF@8>P-}p#b-lrEQLDl^AgNCo&i+p0x=)RH@Q zUDN^{7u;18&EbzW9~w-~-ZJA`pV8Ch8MRsMCX0`b=Pnph-Wo$%KSn*_`D~#4qnVM? Old Date: Fri, 2 Jun 2023 11:27:02 +0800 Subject: [PATCH 44/56] hw/char: fix autobaud support for ESP32-C3 target --- hw/char/esp32c3_uart.c | 33 ++++++++++++++++++++++++++------- include/hw/char/esp32c3_uart.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/hw/char/esp32c3_uart.c b/hw/char/esp32c3_uart.c index ed503d94c387..029aeda1f1e0 100644 --- a/hw/char/esp32c3_uart.c +++ b/hw/char/esp32c3_uart.c @@ -19,6 +19,8 @@ #include "hw/char/esp32c3_uart.h" #include "hw/misc/esp32c3_rtc_cntl.h" +#define ESP32_UART_AUTOBAUD A_UART_AUTOBAUD + static uint64_t esp32c3_uart_read(void *opaque, hwaddr addr, unsigned int size) { ESP32C3UARTClass *class = ESP32C3_UART_GET_CLASS(opaque); @@ -32,15 +34,24 @@ static void esp32c3_uart_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) { ESP32C3UARTClass *class = ESP32C3_UART_GET_CLASS(opaque); + uint32_t autobaud = 0; - /* Same as above */ - class->parent_uart_write(opaque, addr, value, size); -} + /* UART_RXD_CNT_REG register is not at the same address on the ESP32 and ESP32-C3, so make the + * the translation here. */ + switch (addr) { -static void esp32c3_uart_init(Object *obj) -{ - /* No need to call parent's class function, this is done automatically by the QOM, even before - * calling the current function. */ + case A_ESP32C3_UART_CONF0: + /* On the C3, AUTOBAUD is part of CONF0 register, but on the ESP32, it has its own + * register, poke that register instead */ + autobaud = FIELD_EX32(value, ESP32C3_UART_CONF0, AUTOBAUD_EN) ? 1 : 0; + class->parent_uart_write(opaque, ESP32_UART_AUTOBAUD, autobaud, sizeof(uint32_t)); + /* CONF0 is still a valid register on the ESP32, so fall-through the default case*/ + + default: + class->parent_uart_write(opaque, addr, value, size); + break; + + } } static void esp32c3_uart_reset(DeviceState *dev) @@ -60,6 +71,14 @@ static void esp32c3_uart_realize(DeviceState *dev, Error **errp) esp32c3_class->parent_realize(dev, errp); } + +static void esp32c3_uart_init(Object *obj) +{ + /* No need to call parent's class function, this is done automatically by the QOM, even before + * calling the current function. */ +} + + static void esp32c3_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); diff --git a/include/hw/char/esp32c3_uart.h b/include/hw/char/esp32c3_uart.h index 6c98662f5c9d..38f56bd40b4a 100644 --- a/include/hw/char/esp32c3_uart.h +++ b/include/hw/char/esp32c3_uart.h @@ -34,3 +34,36 @@ typedef struct ESP32C3UARTClass { uint64_t (*parent_uart_read)(void *opaque, hwaddr addr, unsigned int size); } ESP32C3UARTClass; + +/** + * Define the ESP32-C3 specific registers, or the ones that saw their address or fields + * changed from the ESP32 UART + */ +REG32(ESP32C3_UART_CONF0, 0x20) + FIELD(ESP32C3_UART_CONF0, MEM_CLK_EN, 28, 1) + FIELD(ESP32C3_UART_CONF0, AUTOBAUD_EN, 27, 1) + FIELD(ESP32C3_UART_CONF0, ERR_WR_MASK, 26, 1) + FIELD(ESP32C3_UART_CONF0, CLK_EN, 25, 1) + FIELD(ESP32C3_UART_CONF0, DTR_INV, 24, 1) + FIELD(ESP32C3_UART_CONF0, RTS_INV, 23, 1) + FIELD(ESP32C3_UART_CONF0, TXD_INV, 22, 1) + FIELD(ESP32C3_UART_CONF0, DSR_INV, 21, 1) + FIELD(ESP32C3_UART_CONF0, CTS_INV, 20, 1) + FIELD(ESP32C3_UART_CONF0, RXD_INV, 19, 1) + FIELD(ESP32C3_UART_CONF0, TXFIFO_RST, 18, 1) + FIELD(ESP32C3_UART_CONF0, RXFIFO_RST, 17, 1) + FIELD(ESP32C3_UART_CONF0, IRDA_EN, 16, 1) + FIELD(ESP32C3_UART_CONF0, TX_FLOW_EN, 15, 1) + FIELD(ESP32C3_UART_CONF0, LOOPBACK, 14, 1) + FIELD(ESP32C3_UART_CONF0, IRDA_RX_INV, 13, 1) + FIELD(ESP32C3_UART_CONF0, IRDA_TX_INV, 12, 1) + FIELD(ESP32C3_UART_CONF0, IRDA_WCTL, 11, 1) + FIELD(ESP32C3_UART_CONF0, IRDA_TX_EN, 10, 1) + FIELD(ESP32C3_UART_CONF0, IRDA_DPLX, 9, 1) + FIELD(ESP32C3_UART_CONF0, TXD_BRK, 8, 1) + FIELD(ESP32C3_UART_CONF0, SW_DTR, 7, 1) + FIELD(ESP32C3_UART_CONF0, SW_RTS, 6, 1) + FIELD(ESP32C3_UART_CONF0, STOP_BIT_NUM, 4, 2) + FIELD(ESP32C3_UART_CONF0, BIT_NUM, 2, 2) + FIELD(ESP32C3_UART_CONF0, PARITY_EN, 1, 1) + FIELD(ESP32C3_UART_CONF0, PARITY, 0, 1) From aed84c7ea52c564b325593b0a5c5730969879599 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 2 Jun 2023 11:37:33 +0800 Subject: [PATCH 45/56] hw/riscv: modify ESP32-C3 interrupt matrix to only generate interrupts on signals transitions --- hw/nvram/esp32c3_efuse.c | 6 +----- hw/riscv/esp32c3_intmatrix.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/hw/nvram/esp32c3_efuse.c b/hw/nvram/esp32c3_efuse.c index 86b16b1b2540..31111b27a4b0 100644 --- a/hw/nvram/esp32c3_efuse.c +++ b/hw/nvram/esp32c3_efuse.c @@ -360,8 +360,6 @@ static void esp32c3_efuse_write(void *opaque, hwaddr addr, } /* Treat the interrupt-related cases separately */ - const uint32_t former_status = s->efuses.int_st.val; - switch (addr) { case offsetof(ESP32C3EfuseRegs, int_clr): /* Only clear the bits that are set to 1 in the value */ @@ -417,9 +415,7 @@ static void esp32c3_efuse_write(void *opaque, hwaddr addr, const uint32_t new_status = (s->efuses.int_ena.val | s->efuses.int_raw.val) & 0b11; s->efuses.int_st.val = new_status; - if (former_status != new_status) { - qemu_set_irq(s->irq, new_status ? 1 : 0); - } + qemu_set_irq(s->irq, new_status ? 1 : 0); } diff --git a/hw/riscv/esp32c3_intmatrix.c b/hw/riscv/esp32c3_intmatrix.c index 58589268fb47..1a2c890e38e1 100644 --- a/hw/riscv/esp32c3_intmatrix.c +++ b/hw/riscv/esp32c3_intmatrix.c @@ -103,6 +103,12 @@ static void esp32c3_intmatrix_irq_handler(void *opaque, int n, int level) /* Update the level mirror */ assert(n <= ESP32C3_INT_MATRIX_INPUTS); + /* Make sure level is 0 or 1 */ + level = level ? 1 : 0; + + /* Save the former level of the pin */ + const int former_level = BIT_SET(s->irq_levels, n) ? 1 : 0; + if (level) { SET_BIT(s->irq_levels, n); } else { @@ -111,8 +117,9 @@ static void esp32c3_intmatrix_irq_handler(void *opaque, int n, int level) const int line = s->irq_map[n]; - /* If the line is not enable, don't do anything special, the level has been recorded already */ - if ((s->irq_enabled & BIT(line)) == 0) { + /* If the line is not enable, don't do anything special, the level has been recorded already. + * Don't do anything if the line is at the same level as before */ + if ((s->irq_enabled & BIT(line)) == 0 || former_level == level) { return; } From 8bae2a3563bcb5db4986becc76cf5172abe5a7d9 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 2 Jun 2023 12:29:17 +0800 Subject: [PATCH 46/56] hw/riscv: add support for 2, 4, 8, and 16MB SPI Flash for ESP32-C3 machine --- hw/riscv/esp32c3.c | 48 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/hw/riscv/esp32c3.c b/hw/riscv/esp32c3.c index 42fae7b0a9a4..8bd7d6108e8b 100644 --- a/hw/riscv/esp32c3.c +++ b/hw/riscv/esp32c3.c @@ -46,6 +46,8 @@ #define ESP32C3_RESET_ADDRESS 0x40000000 +#define MB (1024*1024) + /* Define a new "class" which derivates from "MachineState" */ struct Esp32C3MachineState { @@ -189,6 +191,41 @@ static void esp32c3_cpu_reset(void* opaque, int n, int level) } } +static void esp32c3_init_spi_flash(Esp32C3MachineState *ms, BlockBackend* blk) +{ + DeviceState *spi_master = DEVICE(&ms->spi1); + BusState* spi_bus = qdev_get_child_bus(spi_master, "spi"); + const char* flash_model = NULL; + int64_t image_size = blk_getlength(blk); + + switch (image_size) { + case 2 * MB: + flash_model = "w25x16"; + break; + case 4 * MB: + flash_model = "gd25q32"; + break; + case 8 * MB: + flash_model = "gd25q64"; + break; + case 16 * MB: + flash_model = "is25lp128"; + break; + default: + error_report("Drive size error: only 2, 4, 8, and 16MB images are supported"); + return; + } + + /* Create the SPI flash model */ + DeviceState *flash_dev = qdev_new(flash_model); + qdev_prop_set_drive(flash_dev, "drive", blk); + + /* Realize the SPI flash, its "drive" (blk) property must already be set! */ + qdev_realize(flash_dev, spi_bus, &error_fatal); + qdev_connect_gpio_out_named(spi_master, SSI_GPIO_CS, 0, + qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0)); +} + static void esp32c3_machine_init(MachineState *machine) { @@ -325,18 +362,9 @@ static void esp32c3_machine_init(MachineState *machine) qdev_realize(DEVICE(&ms->spi1), &ms->periph_bus, &error_fatal); MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->spi1), 0); memory_region_add_subregion_overlap(sys_mem, DR_REG_SPI1_BASE, mr, 0); - - - DeviceState *flash_dev = qdev_new("gd25q32"); - DeviceState *spi_master = DEVICE(&ms->spi1); - BusState* spi_bus = qdev_get_child_bus(spi_master, "spi"); - qdev_realize(flash_dev, spi_bus, &error_fatal); - qdev_connect_gpio_out_named(spi_master, SSI_GPIO_CS, 0, - qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0)); - qdev_prop_set_drive(flash_dev, "drive", blk); + esp32c3_init_spi_flash(ms, blk); } - for (int i = 0; i < ESP32C3_UART_COUNT; ++i) { const hwaddr uart_base[] = { DR_REG_UART_BASE, DR_REG_UART1_BASE }; qdev_realize(DEVICE(&ms->uart[i]), &ms->periph_bus, &error_fatal); From 90c8591b4b3e923a1e69fd59aa2a93deaefd90d3 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Fri, 2 Jun 2023 12:30:14 +0800 Subject: [PATCH 47/56] hw/ssi: implement SPI flash special commands for ESP32-C3 SPI controller * Closes https://github.com/espressif/qemu/issues/75 These commands are used by when bootstraping the chip. This lets the `esptool` flash any image to the emulated SPI flash. --- hw/ssi/esp32c3_spi.c | 263 ++++++++++++++++++++++++++++++----- include/hw/ssi/esp32c3_spi.h | 14 +- 2 files changed, 245 insertions(+), 32 deletions(-) diff --git a/hw/ssi/esp32c3_spi.c b/hw/ssi/esp32c3_spi.c index 8acda425bb31..59c6f1bc6ad1 100644 --- a/hw/ssi/esp32c3_spi.c +++ b/hw/ssi/esp32c3_spi.c @@ -19,11 +19,41 @@ #include "hw/qdev-properties.h" #include "hw/ssi/ssi.h" #include "hw/ssi/esp32c3_spi.h" +#include "qemu/error-report.h" #define SPI1_DEBUG 0 #define SPI1_WARNING 0 -#define ESP32C3_SPI_FLASH_ID 0xc84016 + +enum { + CMD_RES = 0xab, + CMD_DP = 0xb9, + CMD_CE = 0x60, + CMD_BE = 0xd8, + CMD_SE = 0x20, + CMD_PP = 0x02, + CMD_WRSR = 0x1, + CMD_RDSR = 0x5, + CMD_RDID = 0x9f, + CMD_WRDI = 0x4, + CMD_WREN = 0x6, + CMD_READ = 0x03, + CMD_HPM = 0xa3, +}; + + +typedef struct ESP32C3SpiTransaction { + uint32_t cmd; + uint32_t cmd_bytes; + + uint32_t addr; + uint32_t addr_bytes; + + void* data; + uint32_t tx_bytes; + uint32_t rx_bytes; +} ESP32C3SpiTransaction; + static uint64_t esp32c3_spi_read(void *opaque, hwaddr addr, unsigned int size) { @@ -40,12 +70,39 @@ static uint64_t esp32c3_spi_read(void *opaque, hwaddr addr, unsigned int size) case A_SPI_MEM_CTRL: r = s->mem_ctrl; break; + case A_SPI_MEM_CTRL1: + r = s->mem_ctrl1; + break; + case A_SPI_MEM_CTRL2: + r = s->mem_ctrl2; + break; + case A_SPI_MEM_CLOCK: + r = s->mem_clock; + break; case A_SPI_MEM_USER: r = s->mem_user; break; + case A_SPI_MEM_USER1: + r = s->mem_user1; + break; + case A_SPI_MEM_USER2: + r = s->mem_user2; + break; + case A_SPI_MEM_MISO_DLEN: + r = s->mem_miso_len; + break; + case A_SPI_MEM_MOSI_DLEN: + r = s->mem_mosi_len; + break; + case A_SPI_MEM_RD_STATUS: + r = s->mem_rd_st; + break; case A_SPI_MEM_W0...A_SPI_MEM_W15: r = s->data_reg[(addr - A_SPI_MEM_W0) / sizeof(uint32_t)]; break; + case A_SPI_MEM_SUS_STATUS: + r = s->mem_sus_st; + break; default: #if SPI1_WARNING warn_report("[SPI1] Unsupported read to 0x%lx\n", addr); @@ -79,33 +136,161 @@ static void esp32c3_spi_txrx_buffer(ESP32C3SpiState *s, } +static void esp32c3_spi_perform_transaction(ESP32C3SpiState *s, const ESP32C3SpiTransaction *t) +{ + qemu_set_irq(s->cs_gpio[0], 0); + esp32c3_spi_txrx_buffer(s, &t->cmd, t->cmd_bytes, NULL, 0); + esp32c3_spi_txrx_buffer(s, &t->addr, t->addr_bytes, NULL, 0); + esp32c3_spi_txrx_buffer(s, t->data, t->tx_bytes, t->data, t->rx_bytes); + qemu_set_irq(s->cs_gpio[0], 1); +} + + +static inline void esp32c3_spi_get_addr(ESP32C3SpiState *s, uint32_t* addr, uint32_t* len) +{ + const uint32_t address = FIELD_EX32(s->mem_addr, SPI_MEM_ADDR, USR_ADDR_VALUE); + /* SPI Flash expects the address to be sent with MSB first. We make the assumption that + * the host computer uses a little-endian CPU. */ + *addr = bswap32(address); + + const uint32_t address_len = FIELD_EX32(s->mem_user1, SPI_MEM_USER1, USR_ADDR_BITLEN); + *len = (address_len + 1) / 8; +} + + static void esp32c3_spi_begin_transaction(ESP32C3SpiState *s) { - /* Check if we are in the command state */ - if (s->mem_user & R_SPI_MEM_USER_USR_COMMAND_MASK) { - /* Get the number of bytes to read from the device */ - uint32_t miso_len = FIELD_EX32(s->mem_miso_len, SPI_MEM_MISO_DLEN, USR_MISO_DBITLEN); - miso_len = (miso_len + 1) / 8; - /* and the number of bytes to write to the device */ - uint32_t mosi_len = FIELD_EX32(s->mem_mosi_len, SPI_MEM_MOSI_DLEN, USR_MOSI_DBITLEN); - mosi_len = (mosi_len + 1) / 8; - - /* Get the command and its length, in bytes */ - uint32_t command = FIELD_EX32(s->mem_user2, SPI_MEM_USER2, USR_COMMAND_VALUE); - uint32_t commands_len = FIELD_EX32(s->mem_user2, SPI_MEM_USER2, USR_COMMAND_BITLEN); - commands_len = (commands_len + 1) / 8; - - /* Get the address and its length, in bytes */ - uint32_t address = FIELD_EX32(s->mem_addr, SPI_MEM_ADDR, USR_ADDR_VALUE); - uint32_t address_len = FIELD_EX32(s->mem_user1, SPI_MEM_USER1, USR_ADDR_BITLEN); - address_len = (address_len + 1) / 8; - - qemu_set_irq(s->cs_gpio[0], 0); - esp32c3_spi_txrx_buffer(s, &command, commands_len, NULL, 0); - esp32c3_spi_txrx_buffer(s, &address, address_len, NULL, 0); - esp32c3_spi_txrx_buffer(s, s->data_reg, mosi_len, s->data_reg, miso_len); - qemu_set_irq(s->cs_gpio[0], 1); + ESP32C3SpiTransaction t = { + .data = s->data_reg + }; + + /* Get the number of bytes to read from the device */ + if (s->mem_user & R_SPI_MEM_USER_USR_MISO_MASK) { + t.rx_bytes = FIELD_EX32(s->mem_miso_len, SPI_MEM_MISO_DLEN, USR_MISO_DBITLEN); + t.rx_bytes = (t.rx_bytes + 1) / 8; + } + + /* and the number of bytes to write to the device */ + if (s->mem_user & R_SPI_MEM_USER_USR_MOSI_MASK) { + t.tx_bytes = FIELD_EX32(s->mem_mosi_len, SPI_MEM_MOSI_DLEN, USR_MOSI_DBITLEN); + t.tx_bytes = (t.tx_bytes + 1) / 8; + } + + /* Get the command and its length, in bytes + * In theory we should test mem_user's command bit. In practice, if we do, `esptool` + * cannot write flash successfully and detects an error */ + t.cmd = FIELD_EX32(s->mem_user2, SPI_MEM_USER2, USR_COMMAND_VALUE); + t.cmd_bytes = FIELD_EX32(s->mem_user2, SPI_MEM_USER2, USR_COMMAND_BITLEN); + t.cmd_bytes = (t.cmd_bytes + 1) / 8; + + /* Get the address and its length, in bytes */ + if (s->mem_user & R_SPI_MEM_USER_USR_ADDR_MASK) { + esp32c3_spi_get_addr(s, &t.addr, &t.addr_bytes); + if (t.addr_bytes > 0 && t.addr_bytes <= 4) { + t.addr = t.addr >> (32 - t.addr_bytes * 8); + } + } + + esp32c3_spi_perform_transaction(s, &t); +} + + +static void esp32c3_spi_special_command(ESP32C3SpiState *s, uint32_t command) +{ + ESP32C3SpiTransaction t= { + .cmd_bytes = 1 + }; + + switch (command >> 19 << 19) { + case R_SPI_MEM_CMD_FLASH_READ_MASK: + t.cmd = CMD_READ; + esp32c3_spi_get_addr(s, &t.addr, &t.addr_bytes); + t.addr = t.addr >> (32 - t.addr_bytes * 8); + t.data = s->data_reg; + t.rx_bytes = (FIELD_EX32(s->mem_miso_len, SPI_MEM_MISO_DLEN, USR_MISO_DBITLEN) + 1) / 8; + break; + + case R_SPI_MEM_CMD_FLASH_WREN_MASK: + t.cmd = CMD_WREN; + break; + + case R_SPI_MEM_CMD_FLASH_WRDI_MASK: + t.cmd = CMD_WRDI; + break; + + case R_SPI_MEM_CMD_FLASH_RDID_MASK: + t.cmd = CMD_RDID; + t.data = s->data_reg; + t.rx_bytes = 3; + break; + + case R_SPI_MEM_CMD_FLASH_RDSR_MASK: + t.cmd = CMD_RDSR; + t.data = &s->mem_rd_st; + t.rx_bytes = 1; + break; + + case R_SPI_MEM_CMD_FLASH_WRSR_MASK: + t.cmd = CMD_WRSR; + t.data = &s->mem_rd_st; + t.tx_bytes = 1; + break; + + case R_SPI_MEM_CMD_FLASH_PP_MASK: + t.cmd = CMD_PP; + t.data = s->data_reg; + esp32c3_spi_get_addr(s, &t.addr, &t.addr_bytes); + /* The number of bytes to process is in the upper-byte of address */ + t.tx_bytes = (s->mem_addr >> 24) & 0xff; + /** + * Page program expects a 24-bit page address, if the one written in mem_addr was + * 0xNN_33_00_02 (where is "do not care"), after calling `esp32c3_spi_get_addr`, the + * address becomes 0x02_00_33_NN. Thus, if we cast it to a byte array, arr[0] would give + * `NN`, instead of `33`. We need to adjust the value in address. + */ + t.addr = t.addr >> 8; + break; + + case R_SPI_MEM_CMD_FLASH_SE_MASK: + t.cmd = CMD_SE; + esp32c3_spi_get_addr(s, &t.addr, &t.addr_bytes); + /* For the same reasons as explained above, we need to adjust `t.addr`, but here, the shift + * to perform is not fixed and depends on the address length */ + t.addr = t.addr >> (32 - t.addr_bytes * 8); + break; + + case R_SPI_MEM_CMD_FLASH_BE_MASK: + t.cmd = CMD_BE; + esp32c3_spi_get_addr(s, &t.addr, &t.addr_bytes); + t.addr = t.addr >> (32 - t.addr_bytes * 8); + break; + + case R_SPI_MEM_CMD_FLASH_CE_MASK: + t.cmd = CMD_CE; + break; + + case R_SPI_MEM_CMD_FLASH_DP_MASK: + t.cmd = CMD_DP; + break; + + case R_SPI_MEM_CMD_FLASH_RES_MASK: + t.cmd = CMD_RES; + t.data = s->data_reg; + t.rx_bytes = 3; + break; + + case R_SPI_MEM_CMD_FLASH_HPM_MASK: + t.cmd = CMD_HPM; + /* HPM needs 24 dummy cycles, so sent 3 random bytes */ + t.data = s->data_reg; + t.rx_bytes = 3; + break; + + default: + printf("[SPI1] Unsupported special command %x\n", command); + return; } + esp32c3_spi_perform_transaction(s, &t); } @@ -115,12 +300,16 @@ static void esp32c3_spi_write(void *opaque, hwaddr addr, ESP32C3SpiState *s = ESP32C3_SPI(opaque); uint32_t wvalue = (uint32_t) value; +#if SPI1_DEBUG + info_report("[SPI1] Writing 0x%lx = %08lx\n", addr, value); +#endif + switch (addr) { case A_SPI_MEM_CMD: - if (wvalue & R_SPI_MEM_CMD_FLASH_RDID_MASK) { - s->data_reg[0] = ESP32C3_SPI_FLASH_ID; - } else if(wvalue & R_SPI_MEM_CMD_USR_MASK) { + if(wvalue & R_SPI_MEM_CMD_USR_MASK) { esp32c3_spi_begin_transaction(s); + } else { + esp32c3_spi_special_command(s, wvalue); } break; case A_SPI_MEM_ADDR: @@ -129,6 +318,15 @@ static void esp32c3_spi_write(void *opaque, hwaddr addr, case A_SPI_MEM_CTRL: s->mem_ctrl = wvalue; break; + case A_SPI_MEM_CTRL1: + s->mem_ctrl1 = wvalue; + break; + case A_SPI_MEM_CTRL2: + s->mem_ctrl2 = wvalue; + break; + case A_SPI_MEM_CLOCK: + s->mem_clock = wvalue; + break; case A_SPI_MEM_USER: s->mem_user = wvalue; break; @@ -144,9 +342,15 @@ static void esp32c3_spi_write(void *opaque, hwaddr addr, case A_SPI_MEM_MOSI_DLEN: s->mem_mosi_len = wvalue; break; + case A_SPI_MEM_RD_STATUS: + s->mem_rd_st = wvalue; + break; case A_SPI_MEM_W0...A_SPI_MEM_W15: s->data_reg[(addr - A_SPI_MEM_W0) / sizeof(uint32_t)] = wvalue; break; + case A_SPI_MEM_SUS_STATUS: + s->mem_sus_st = wvalue; + break; default: #if SPI1_WARNING warn_report("[SPI1] Unsupported write to 0x%lx (%08lx)\n", addr, value); @@ -154,9 +358,6 @@ static void esp32c3_spi_write(void *opaque, hwaddr addr, break; } -#if SPI1_DEBUG - info_report("[SPI1] Writing 0x%lx = %08lx\n", addr, value); -#endif } /* Convert one of the hardware "bitlen" registers to a byte count */ diff --git a/include/hw/ssi/esp32c3_spi.h b/include/hw/ssi/esp32c3_spi.h index 53eb907e2f1e..14b64af25050 100644 --- a/include/hw/ssi/esp32c3_spi.h +++ b/include/hw/ssi/esp32c3_spi.h @@ -8,7 +8,7 @@ #define ESP32C3_SPI(obj) OBJECT_CHECK(ESP32C3SpiState, (obj), TYPE_ESP32C3_SPI) /** - * Size of the Timegroup I/O registers area + * Size of the SPI I/O registers area */ #define ESP32C3_SPI_IO_SIZE (A_SPI_MEM_DATE + 4) @@ -25,14 +25,24 @@ typedef struct ESP32C3SpiState { qemu_irq cs_gpio[ESP32C3_SPI_CS_COUNT]; uint32_t mem_cmd; + /** + * In user mode, this register represents the flash address. + * In other modes, bits 0 to 23 included is the memory address and bits 24 to 31 included + * is the number of bytes to process. + */ uint32_t mem_addr; uint32_t mem_ctrl; + uint32_t mem_ctrl1; + uint32_t mem_ctrl2; + uint32_t mem_clock; uint32_t mem_user; uint32_t mem_user1; uint32_t mem_user2; uint32_t mem_miso_len; uint32_t mem_mosi_len; + uint32_t mem_rd_st; uint32_t data_reg[ESP32C3_SPI_BUF_WORDS]; + uint32_t mem_sus_st; } ESP32C3SpiState; @@ -102,6 +112,8 @@ REG32(SPI_MEM_USER, 0x018) FIELD(SPI_MEM_USER, FWRITE_QUAD, 13, 1) FIELD(SPI_MEM_USER, FWRITE_DUAL, 12, 1) FIELD(SPI_MEM_USER, CK_OUT_EDGE, 9, 1) + FIELD(SPI_MEM_USER, CS_SETUP, 7, 1) + FIELD(SPI_MEM_USER, CS_HOLD, 6, 1) REG32(SPI_MEM_USER1, 0x01C) FIELD(SPI_MEM_USER1, USR_ADDR_BITLEN, 26, 6) From efe39d985007f11f11a1bd9b16efc186ad672522 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 20 Jun 2023 17:20:24 +0100 Subject: [PATCH 48/56] pc-bios/keymaps: Use the official xkb name for Arabic layout, not the legacy synonym MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The xkb official name for the Arabic keyboard layout is 'ara'. However xkb has for at least the past 15 years also permitted it to be named via the legacy synonym 'ar'. In xkeyboard-config 2.39 this synoynm was removed, which breaks compilation of QEMU: FAILED: pc-bios/keymaps/ar /home/fred/qemu-git/src/qemu/build-full/qemu-keymap -f pc-bios/keymaps/ar -l ar xkbcommon: ERROR: Couldn't find file "symbols/ar" in include paths xkbcommon: ERROR: 1 include paths searched: xkbcommon: ERROR: /usr/share/X11/xkb xkbcommon: ERROR: 3 include paths could not be added: xkbcommon: ERROR: /home/fred/.config/xkb xkbcommon: ERROR: /home/fred/.xkb xkbcommon: ERROR: /etc/xkb xkbcommon: ERROR: Abandoning symbols file "(unnamed)" xkbcommon: ERROR: Failed to compile xkb_symbols xkbcommon: ERROR: Failed to compile keymap The upstream xkeyboard-config change removing the compat mapping is: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/commit/470ad2cd8fea84d7210377161d86b31999bb5ea6 Make QEMU always ask for the 'ara' xkb layout, which should work on both older and newer xkeyboard-config. We leave the QEMU name for this keyboard layout as 'ar'; it is not the only one where our name for it deviates from the xkb standard name. Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Daniel P. Berrangé Message-id: 20230620162024.1132013-1-peter.maydell@linaro.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1709 --- pc-bios/keymaps/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/keymaps/meson.build b/pc-bios/keymaps/meson.build index 158a3b410c17..1cbcdebefa92 100644 --- a/pc-bios/keymaps/meson.build +++ b/pc-bios/keymaps/meson.build @@ -1,5 +1,5 @@ keymaps = { - 'ar': '-l ar', + 'ar': '-l ara', 'bepo': '-l fr -v dvorak', 'cz': '-l cz', 'da': '-l dk', From 24a669b80015d0fd79a77d80465dbe4b80a2f320 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Thu, 11 May 2023 12:17:48 +0800 Subject: [PATCH 49/56] hw/dma: implement GDMA Memory-To-Memory for ESP32-C3 --- hw/dma/esp32c3_gdma.c | 806 ++++++++++++++++++++++++++++++++++ hw/dma/meson.build | 1 + hw/riscv/esp32c3.c | 18 + include/hw/dma/esp32c3_gdma.h | 647 +++++++++++++++++++++++++++ 4 files changed, 1472 insertions(+) create mode 100644 hw/dma/esp32c3_gdma.c create mode 100644 include/hw/dma/esp32c3_gdma.h diff --git a/hw/dma/esp32c3_gdma.c b/hw/dma/esp32c3_gdma.c new file mode 100644 index 000000000000..e6dfe215024c --- /dev/null +++ b/hw/dma/esp32c3_gdma.c @@ -0,0 +1,806 @@ +/* + * ESP32-C3 GDMA emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "sysemu/dma.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/dma/esp32c3_gdma.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" + +#define GDMA_WARNING 0 +#define GDMA_DEBUG 0 + +/** + * Check the header file for more info about this function + */ +int esp32c3_gdma_get_channel_periph(ESP32C3GdmaState *s, GdmaPeripheral periph, int dir) +{ + /* If the state, the peripheral or the direction is invalid, return directly */ + if (s == NULL || + periph > GDMA_LAST || periph == GDMA_RSVD1 || periph == GDMA_RSVD4 || periph == GDMA_RSVD5 || + dir < 0 || dir >= ESP32C3_GDMA_CONF_COUNT) + { + return -1; + } + + /* Check all the channels of the GDMA */ + for (int i = 0; i < ESP32C3_GDMA_CHANNEL_COUNT; i++) { + /* IN/OUT PERI registers have the same organization, can use any macro */ + if (FIELD_EX32(s->ch_conf[i][dir].peripheral, DMA_IN_PERI_SEL_CH0, PERI_IN_SEL_CH0) == periph) { + return i; + } + } + + return -1; +} + + +/** + * @brief Structure defining how linked lists are represented in hardware for the GDMA module + */ +typedef struct GdmaLinkedList { + union { + struct { + uint32_t size: 12; // Size of the buffer (mainly used in a receive transaction) + uint32_t length: 12; // Number of valid bytes in the buffer. In a transmit, written by software. + // In receive, written by hardware. + uint32_t rsvd_24: 4; // Reserved + uint32_t err_eof: 1; // Set if received data has errors. Used with UHCI0 only. + uint32_t rsvd_29: 1; // Reserved + uint32_t suc_eof: 1; // Set if curent node is the last one (of the list). Set by software in a transmit transaction, + // Set by the hardware in case of a receive transaction. + uint32_t owner: 1; // 0: CPU can access the buffer, 1: GDMA can access the buffer. Cleared automatically + // by hardware in a transmit descriptor. In a receive descriptor, cleared by hardware + // only if GDMA_OUT_AUTO_WRBACK_CHn is set to 1. + }; + uint32_t val; + } config; + uint32_t buf_addr; + uint32_t next_addr; +} GdmaLinkedList; + + +static uint32_t read_addr_word(uint32_t* ptr, uint32_t offset) { + return ptr[offset / sizeof(uint32_t)]; +} + + +static uint64_t esp32c3_gdma_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3GdmaState *s = ESP32C3_GDMA(opaque); + uint64_t r = 0; + +#if GDMA_DEBUG + info_report("[GDMA] Reading from %08lx (%08lx)\n", addr, r); +#endif + + switch(addr) { + case A_DMA_INT_RAW_CH0 ... A_DMA_INT_CLR_CH2: + r = read_addr_word((uint32_t*) s->ch_int, addr - A_DMA_INT_RAW_CH0); + break; + + case A_DMA_MISC_CONF: + r = s->misc_conf; + break; + + case A_DMA_IN_CONF0_CH0 ... A_DMA_IN_PERI_SEL_CH0: + r = read_addr_word((uint32_t*) &s->ch_conf[0][ESP32C3_GDMA_IN_IDX], addr - A_DMA_IN_CONF0_CH0); + break; + + case A_DMA_OUT_CONF0_CH0 ... A_DMA_OUT_PERI_SEL_CH0: + r = read_addr_word((uint32_t*) &s->ch_conf[0][ESP32C3_GDMA_OUT_IDX], addr - A_DMA_OUT_CONF0_CH0); + break; + + case A_DMA_IN_CONF0_CH1 ... A_DMA_IN_PERI_SEL_CH1: + r = read_addr_word((uint32_t*) &s->ch_conf[1][ESP32C3_GDMA_IN_IDX], addr - A_DMA_IN_CONF0_CH1); + break; + + case A_DMA_OUT_CONF0_CH1 ... A_DMA_OUT_PERI_SEL_CH1: + r = read_addr_word((uint32_t*) &s->ch_conf[1][ESP32C3_GDMA_OUT_IDX], addr - A_DMA_OUT_CONF0_CH1); + break; + + case A_DMA_IN_CONF0_CH2 ... A_DMA_IN_PERI_SEL_CH2: + r = read_addr_word((uint32_t*) &s->ch_conf[2][ESP32C3_GDMA_IN_IDX], addr - A_DMA_IN_CONF0_CH2); + break; + + case A_DMA_OUT_CONF0_CH2 ... A_DMA_OUT_PERI_SEL_CH2: + r = read_addr_word((uint32_t*) &s->ch_conf[2][ESP32C3_GDMA_OUT_IDX], addr - A_DMA_OUT_CONF0_CH2); + break; + + default: +#if GDMA_WARNING + warn_report("[GDMA] Unsupported read to %08lx\n", addr); +#endif + break; + } + + return r; +} + + +/** + * @brief Check whether the new status of any interrupt should trigger an interrupt + * + * @param s GDMA state structure + * @param chan Channel that has just been updated + */ +static void esp32c3_gdma_check_interrupt_status(ESP32C3GdmaState *s, uint32_t chan) +{ + DmaIntState* const int_st = &s->ch_int[chan]; + const uint32_t former = int_st->st; + + /* Calculate the new status and check for any difference */ + int_st->st = int_st->raw & int_st->ena; + + if (former != int_st->st) { + /* If all the status bits became low, lower the IRQ pin, else, raise it */ + qemu_set_irq(s->irq[chan], int_st->st ? 1 : 0); + } +} + + +/** + * @brief Set the status bit for the given channel. If the status triggers an interrupt, the corresponding + * IRQ will be set. +*/ +static void esp32c3_gdma_set_status(ESP32C3GdmaState *s, uint32_t chan, uint32_t mask) +{ + s->ch_int[chan].raw |= mask; + esp32c3_gdma_check_interrupt_status(s, chan); +} + + + +/** + * @brief Clear the status bit for the given channel +*/ +static void esp32c3_gdma_clear_status(ESP32C3GdmaState *s, uint32_t chan, uint32_t mask) +{ + s->ch_int[chan].raw &= ~mask; + esp32c3_gdma_check_interrupt_status(s, chan); +} + + +/** + * @brief Function called when a write to a channel interrupt register is performed + * + * @param s GDMA state structure + * @param chan Index of the channel to be written + * @param reg Offset, in bytes, of the register to modify + * @param value New value for the register + */ +static void esp32c3_gdma_write_int_state(ESP32C3GdmaState *s, uint32_t chan, uint32_t reg, uint32_t value) +{ + switch (reg) { + case offsetof(DmaIntState, ena): + s->ch_int[chan].ena = value; + break; + + case offsetof(DmaIntState, raw): + case offsetof(DmaIntState, clr): + /* Clear the bits that are set to 1, keep the remaining to their original value */ + s->ch_int[chan].raw &= ~value; + break; + + case offsetof(DmaIntState, st): + default: + /* Nothing to do, read-only register, return directly */ + return; + } + + /* Update the status and check if any interrupt needs to occur */ + esp32c3_gdma_check_interrupt_status(s, chan); +} + + +/** + * @brief Function called when a reset FIFO is requested + * + * @param s GDMA state structure + * @param chan Index of the channel + * @param in_out Index of the direction, ESP32C3_GDMA_IN_IDX or ESP32C3_GDMA_OUT_IDX, + * that needs a FIFO reset + */ +static void esp32c3_gdma_reset_fifo(ESP32C3GdmaState *s, uint32_t chan, uint32_t in_out) +{ +#if GDMA_DEBUG + info_report("Resetting FIFO for chan %d, direction: %d\n", chan, in_out); +#endif + /* Set the FIFO empty bit to 1, full bit to 0, and number of bytes of data to 0 */ + s->ch_conf[chan][in_out].status = R_DMA_INFIFO_STATUS_CH0_INFIFO_EMPTY_CH0_MASK; +} + + +/** + * @brief Check that the given 32-bit address is in a given range + * + * @param range_start Start address of range + * @param range_size Size of the SoC DRAM + * @param addr Linked-list node address + * + * @returns true if the node is valid (in DRAM), false else + */ +static inline bool esp32c3_gdma_addr_in_range(uint32_t range_start, uint32_t range_size, uint32_t addr) +{ + return range_start <= addr && addr < (range_start + range_size); +} + + +/** + * @brief Read a descriptor from the guest machine + * + * @param s GDMA state structure + * @param addr Guest machine address + * + * @returns true if the transfer was a success, false else + */ +static bool esp32c3_gdma_read_descr(ESP32C3GdmaState *s, uint32_t addr, GdmaLinkedList* out) +{ + MemTxResult res = dma_memory_read(&s->dma_as, addr, out, sizeof(GdmaLinkedList), MEMTXATTRS_UNSPECIFIED); + return res == MEMTX_OK; +} + +/** + * @brief Write a descriptor to the guest machine + * + * @param s GDMA state structure + * @param addr Guest machine address + * + * @returns true if the transfer was a success, false else + */ +static bool esp32c3_gdma_write_descr(ESP32C3GdmaState *s, uint32_t addr, GdmaLinkedList* in) +{ + MemTxResult res = dma_memory_write(&s->dma_as, addr, in, sizeof(GdmaLinkedList), MEMTXATTRS_UNSPECIFIED); + return res == MEMTX_OK; +} + + + +/** + * @brief Read and write arbitrary data from and to the guest machine + * + * @param s GDMA state structure + * @param addr Guest machine address + * + * @returns true if the transfer was a success, false else + */ +static bool esp32c3_gdma_read_guest(ESP32C3GdmaState *s, uint32_t addr, void* data, uint32_t len) +{ + MemTxResult res = dma_memory_read(&s->dma_as, addr, data, len, MEMTXATTRS_UNSPECIFIED); + return res == MEMTX_OK; +} + +static bool esp32c3_gdma_write_guest(ESP32C3GdmaState *s, uint32_t addr, void* data, uint32_t len) +{ + MemTxResult res = dma_memory_write(&s->dma_as, addr, data, len, MEMTXATTRS_UNSPECIFIED); + return res == MEMTX_OK; +} + + +/** + * @brief Push current node (guest) address in the list of descriptors registers + * + * @param s GDMA state structure + * @param chan Channel to update + * @param chan Direction to update + * @param current New node (guest) address to set as the current + */ +static void esp32c3_gdma_push_descriptor(ESP32C3GdmaState *s, uint32_t chan, uint32_t dir, uint32_t current) +{ + GdmaLinkedList next_node; + uint32_t next = 0; + DmaConfigState* state = &s->ch_conf[chan][dir]; + + /* Assign the current descriptor address to the state register */ + state->state = current & R_DMA_OUT_STATE_CH0_OUTLINK_DSCR_ADDR_CH0_MASK; + + /* On real hardware, if the former address is incorrect, the current address is copied to this + * register. */ + state->bfr_bfr_desc_addr = state->bfr_desc_addr; + /* On real hardware, state->bfr_desc_addr is taken from state->desc_addr, even is `current` is valid */ + state->bfr_desc_addr = state->desc_addr; + + /* Get the next address out of the guest RAM */ + const bool valid = esp32c3_gdma_read_descr(s, current, &next_node); + if (valid) { + next = next_node.next_addr; + } + state->desc_addr = next; +} + + + +/** + * @brief Jump to the next node list and assign it to the given node + * + * @param s GDMA state structure + * @param node Node to get the next neighbor of + * + * @returns true if the next node is valid, false else + */ +static inline bool esp32c3_gdma_next_list_node(ESP32C3GdmaState *s, uint32_t chan, uint32_t dir, GdmaLinkedList* node) +{ + const uint32_t current = node->next_addr; + esp32c3_gdma_push_descriptor(s, chan, dir, current); + return esp32c3_gdma_read_descr(s, current, node); +} + + +/** + * @brief Get the first descriptor to process when a restart is requested. + * We need to get the "next" node of the last one processed, which is in `desc_addr` register + * + * @param s GDMA state structure + * @param chan Channel to restart + * @param dir Direction (INT or OUT) to restart + * @param out Filled with the output guest address + */ +static void esp32c3_gdma_get_restart_buffer(ESP32C3GdmaState *s, uint32_t chan, uint32_t dir, uint32_t* out) +{ + DmaConfigState* state = &s->ch_conf[chan][dir]; + // GdmaLinkedList* list = NULL; + /* The next node to use is taken from state->state's lowest 18 bit. Append it to the DRAM address */ + const uint32_t dram_upper_bits = ESP32C3_GDMA_RAM_ADDR & (~R_DMA_OUT_STATE_CH0_OUTLINK_DSCR_ADDR_CH0_MASK); + const uint32_t guest_addr = dram_upper_bits | FIELD_EX32(state->state, DMA_OUT_STATE_CH0, OUTLINK_DSCR_ADDR_CH0); + + *out = guest_addr; +} + + +/** + * @brief Check if a memory-to-memory transfer can be started and start it if possible + * + * @param s GDMA state structure + * @param chan Index of the channel + */ +static void esp32c3_gdma_check_and_start_mem_transfer(ESP32C3GdmaState *s, uint32_t chan) +{ + DmaConfigState* state = s->ch_conf[chan]; + /* Keep the distinction between start and restart because it influences the first descriptor to process */ + const bool in_start = FIELD_EX32(state[ESP32C3_GDMA_IN_IDX].link, DMA_IN_LINK_CH0, INLINK_START_CH0) ? true : false; + const bool in_restart = FIELD_EX32(state[ESP32C3_GDMA_IN_IDX].link, DMA_IN_LINK_CH0, INLINK_RESTART_CH0) ? true : false; + const bool out_start = FIELD_EX32(state[ESP32C3_GDMA_OUT_IDX].link, DMA_OUT_LINK_CH0, OUTLINK_START_CH0) ? true : false; + const bool out_restart = FIELD_EX32(state[ESP32C3_GDMA_OUT_IDX].link, DMA_OUT_LINK_CH0, OUTLINK_RESTART_CH0) ? true : false; + + /* A memory-to-memory transfer can be started if MEM_TRANS is enabled, OUTLINK_(RE)START is set + * and INLINK_(RE)START is set */ + if (FIELD_EX32(state[ESP32C3_GDMA_IN_IDX].conf0, DMA_IN_CONF0_CH0, MEM_TRANS_EN_CH0) + && (in_start || in_restart) + && (out_start || out_restart)) + { + /* Clear the (RE)START fields, i.e., only keep the link address */ + state[ESP32C3_GDMA_OUT_IDX].link &= R_DMA_OUT_LINK_CH0_OUTLINK_ADDR_CH0_MASK; + state[ESP32C3_GDMA_IN_IDX].link &= R_DMA_IN_LINK_CH0_INLINK_ADDR_CH0_MASK; + /* Same goes for the status */ + esp32c3_gdma_clear_status(s, chan, R_DMA_INT_RAW_CH0_IN_DONE_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_OUT_DONE_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_OUT_EOF_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_IN_SUC_EOF_CH0_INT_RAW_MASK); + + /* Get highest 12 bits of the DRAM address */ + const uint32_t high = (ESP32C3_GDMA_RAM_ADDR >> 20) << 20; + + /* TODO: in an inlink, when burst mode is enabled, size and buffer address must be word-aligned. */ + /* If a start was performed, the first descriptor address to process is in DMA_OUT_LINK_CHn register, + * if a restart was performed, the first buffer is the `next` node of `desc_addr` register */ + uint32_t out_addr = high; + uint32_t in_addr = high; + + if (out_start) { + out_addr |= FIELD_EX32(state[ESP32C3_GDMA_OUT_IDX].link, DMA_OUT_LINK_CH0, OUTLINK_ADDR_CH0); + } else { + esp32c3_gdma_get_restart_buffer(s, chan, ESP32C3_GDMA_OUT_IDX, &out_addr); + } + + if (in_start) { + in_addr |= FIELD_EX32(state[ESP32C3_GDMA_IN_IDX].link, DMA_IN_LINK_CH0, INLINK_ADDR_CH0); + } else { + esp32c3_gdma_get_restart_buffer(s, chan, ESP32C3_GDMA_IN_IDX, &in_addr); + } + + /* Boolean to mark whether we need to check the owner for in and out buffers */ + const bool owner_check_out = FIELD_EX32(state[ESP32C3_GDMA_OUT_IDX].conf1, DMA_OUT_CONF1_CH0, OUT_CHECK_OWNER_CH0); + const bool owner_check_in = FIELD_EX32(state[ESP32C3_GDMA_IN_IDX].conf1, DMA_IN_CONF1_CH0, IN_CHECK_OWNER_CH0); + /* Boolean to mark whether the transmit (out) buffers must have their owner bit cleared here */ + const bool clear_out = FIELD_EX32(state[ESP32C3_GDMA_OUT_IDX].conf0, DMA_OUT_CONF0_CH0, OUT_AUTO_WRBACK_CH0); + + /* Pointer to the lists that will be browsed by the loop below */ + GdmaLinkedList out_list = { 0 }; + GdmaLinkedList in_list = { 0 }; + /* Boolean to mark whether a descriptor error occurred during the transfer */ + bool valid = true; + bool error = false; + + /* Get the content of the descriptor located at guest address out_addr */ + valid = esp32c3_gdma_read_descr(s, out_addr, &out_list); + esp32c3_gdma_push_descriptor(s, chan, ESP32C3_GDMA_OUT_IDX, out_addr); + + /* Check that the address is valid. If the owner must be checked, make sure owner is the DMA controller. + * On the real hardware, both in and out are checked at the same time, so in case of an error, both bits + * are set. Replicate the same behavior here. */ + if ( !valid || (owner_check_out && !out_list.config.owner) ) { + /* In case of an error, go directly to the next node (as the C3 hardware does) */ + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } + + valid = esp32c3_gdma_read_descr(s, in_addr, &in_list); + esp32c3_gdma_push_descriptor(s, chan, ESP32C3_GDMA_IN_IDX, in_addr); + + if ( !valid || (owner_check_in && !in_list.config.owner) ) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } + + /* If any of the error bit has been set, return directly */ + if (error) { + return; + } + + /* We can keep track of the total amount of bytes written in order to simulate a more or less + * accurate timing (and an interrupt) */ + int total = 0; + + /* Clear the number of bytes written to the "in" buffer and the owner */ + in_list.config.length = 0; + + /* Number of bytes remaining in the current "out" buffer */ + uint32_t remaining = out_list.config.length; + /* Store the current number of bytes consumed in the "out" buffer */ + uint32_t consumed = 0; + + bool exit_loop = false; + + /* Allocate a temporary buffer big enough to store any descriptor data */ + void* tmp_buffer = g_malloc(4096 * sizeof(uint8_t)); + if (tmp_buffer == NULL) { + error_report("[GDMA] No more memory in host\n"); + return; + } + + while (!exit_loop && !error) { + + /* Calculate the number of bytes to send to the in channel */ + const uint32_t min = MIN(in_list.config.size, out_list.config.length); + + /* Perform the actual copy, for the same reasons as stated above, use the error boolean */ + valid = esp32c3_gdma_read_guest(s, out_list.buf_addr + consumed, tmp_buffer, min); + if (!valid) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } + valid = esp32c3_gdma_write_guest(s, in_list.buf_addr + in_list.config.length, tmp_buffer, min); + if (!valid) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } + + /* Update the number of bytes written to the "in" buffer */ + in_list.config.length += min; + consumed += min; + total += min; + + /* Even if we reached the end of the TX descriptor, we still have to update RX descriptors + * and registers, use `exit_loop` instead of break or return */ + /* If we don't have any more bytes in the "out" buffer, we can skip to the next buffer */ + if (remaining == consumed) { + /* Before jumping to the next node, clear the owner bit */ + if (clear_out) { + out_list.config.owner = 0; + /* Write back the modified descriptor, should always be valid */ + valid = esp32c3_gdma_write_descr(s, out_addr, &out_list); + assert(valid); + } + exit_loop = out_list.config.suc_eof ? true : false; + + const uint32_t next_addr = out_list.next_addr; + valid = esp32c3_gdma_next_list_node(s, chan, ESP32C3_GDMA_OUT_IDX, &out_list); + + /* Only check the valid flag and the owner if we don't have to exit the loop*/ + if ( !exit_loop && (!valid || (owner_check_out && !out_list.config.owner)) ) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } else { + /* Update "remaining" with the number of bytes to transfer from the new buffer */ + out_addr = next_addr; + remaining = out_list.config.length; + consumed = 0; + } + } + + + /* If we reached the end of the "node", go to the next one */ + if (in_list.config.size == in_list.config.length) { + + in_list.config.owner = 0; + + /* Write back the IN node to guest RAM */ + valid = esp32c3_gdma_write_descr(s, in_addr, &in_list); + assert(valid); + + /* Check that we do have more "in" buffers, if that's not the case, raise an error.. + * TODO: Check if the behavior is the same as Peripheral-to-Memory transfers, where + * this bit is only used to generate and interrupt. */ + if (!exit_loop && in_list.config.suc_eof) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DSCR_EMPTY_CH0_INT_RAW_MASK); + error = true; + break; + } + + const uint32_t next_addr = in_list.next_addr; + + /* In the case where the transfer is finished, we should still "push" the next node + * to our descriptors stack, but we should not modify the structure itself as we will + * reset the owner and update the suc_eof flag */ + if (exit_loop) { + esp32c3_gdma_push_descriptor(s, chan, ESP32C3_GDMA_IN_IDX, next_addr); + break; + } + + /* We have to continue the loop, so fetch the next node, it will also update the descriptors stack */ + valid = esp32c3_gdma_next_list_node(s, chan, ESP32C3_GDMA_IN_IDX, &in_list); + + /* Check the validity of the next node if we have to continue the loop (transfer finished) */ + if (!valid || (owner_check_in && !in_list.config.owner)) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } else { + /* Continue the loop normally, next RX descriptor set to current */ + in_list.config.length = 0; + + /* Update the current in guest address */ + in_addr = next_addr; + } + } + + } + + if (!error) { + /* In all cases (error or not), let's set the End-of-list in the receiver */ + in_list.config.suc_eof = 1; + in_list.config.owner = 0; + + /* Write back the previous changes */ + valid = esp32c3_gdma_write_descr(s, in_addr, &in_list); + assert(valid); + + /* And store the EOF RX descriptor GUEST address in the correct register. + * This can be used in the ISR to know which buffer has just been processed. */ + state[ESP32C3_GDMA_IN_IDX].suc_eof_desc_addr = in_addr; + + /* Set the transfer as completed for both the IN and OUT link */ + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DONE_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_OUT_DONE_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_OUT_EOF_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_IN_SUC_EOF_CH0_INT_RAW_MASK); + } + + g_free(tmp_buffer); + } +} + + + +/** + * @brief Check whether the given register offset corresponds to a read-only register + * + * @param offset Offset of the register in DmaConfigState structure, in bytes + * + * @return true is the register is read-only, false else + */ +static bool esp32c3_gdma_register_read_only(uint32_t offset) +{ + return offset >= offsetof(DmaConfigState, state) && offset < offsetof(DmaConfigState, priority); +} + + +/** + * @brief Function called when a configuration register was written to + * + * @param s GDMA state structure + * @param chan Index of the channel to be written + * @param in_out Index of the sub-channel, which is ESP32C3_GDMA_IN_IDX or ESP32C3_GDMA_OUT_IDX + * @param addr_in_block Address in bytes of the register being written to in the block + * @param value 32-bit value being written to the register + */ +static void esp32c3_gdma_write_chan_conf(ESP32C3GdmaState *s, uint32_t chan, uint32_t in_out, + uint32_t addr_in_block, uint32_t value) +{ + DmaConfigState* state = &s->ch_conf[chan][in_out]; + uint32_t* const reg_addr = (uint32_t*) ((uint8_t*) state + addr_in_block); + + /* Dereference the former value of the register being written to */ + const uint32_t former = *reg_addr; + + /* Write the new value to the register if not read-only! */ + if (!esp32c3_gdma_register_read_only(addr_in_block)) { + *reg_addr = value; + } + + /* We will only support a subset of GDMA registers for now. To add support for more registers, + * the following snippet can be update */ + uint32_t start_mask = 0; + uint32_t restart_mask = 0; + switch(addr_in_block) { + + /* No matter the channel and in/out direction, the registers are organized the same way, + * so we can use the macros for any channel */ + case offsetof(DmaConfigState, conf0): + /* Check the reset bit, call the reset function on negative edge */ + if (FIELD_EX32(value, DMA_IN_CONF0_CH0, IN_RST_CH0) == 0 && + FIELD_EX32(former, DMA_IN_CONF0_CH0, IN_RST_CH0) != 0) + { + esp32c3_gdma_reset_fifo(s, chan, in_out); + } + /* Check if memory transfer has just been enabled (only valid for IN channels) */ + if (in_out == ESP32C3_GDMA_IN_IDX && + FIELD_EX32(value, DMA_IN_CONF0_CH0, MEM_TRANS_EN_CH0)) + { + esp32c3_gdma_check_and_start_mem_transfer(s, chan); + } + break; + + case offsetof(DmaConfigState, link): + /* For IN and OUT, the START bit is not at the same offset, so we need to test both separately */ + start_mask = ESP32C3_GDMA_IN_IDX ? R_DMA_IN_LINK_CH0_INLINK_START_CH0_MASK : R_DMA_OUT_LINK_CH0_OUTLINK_START_CH0_MASK; + restart_mask = ESP32C3_GDMA_IN_IDX ? R_DMA_IN_LINK_CH0_INLINK_RESTART_CH0_MASK : R_DMA_OUT_LINK_CH0_OUTLINK_RESTART_CH0_MASK; + + /* Check if any of the previous two bits has just been enabled */ + if ((value & start_mask) || (value & restart_mask)) + { + esp32c3_gdma_check_and_start_mem_transfer(s, chan); + } + + default: + break; + } +} + + +static void esp32c3_gdma_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3GdmaState *s = ESP32C3_GDMA(opaque); + +#if GDMA_DEBUG + info_report("[GDMA] Writing to %08lx (%08lx)\n", addr, value); +#endif + + switch(addr) { + case A_DMA_INT_RAW_CH0 ... A_DMA_INT_CLR_CH2: + esp32c3_gdma_write_int_state(s, + addr / ESP32C3_GDMA_INT_REGS_SIZE, + addr % ESP32C3_GDMA_INT_REGS_SIZE, + value); + break; + + case A_DMA_MISC_CONF: + s->misc_conf = value; + break; + + case A_DMA_IN_CONF0_CH0 ... A_DMA_IN_PERI_SEL_CH0: + esp32c3_gdma_write_chan_conf(s, 0, ESP32C3_GDMA_IN_IDX, addr - A_DMA_IN_CONF0_CH0, value); + break; + + case A_DMA_OUT_CONF0_CH0 ... A_DMA_OUT_PERI_SEL_CH0: + esp32c3_gdma_write_chan_conf(s, 0, ESP32C3_GDMA_OUT_IDX, addr - A_DMA_OUT_CONF0_CH0, value); + break; + + case A_DMA_IN_CONF0_CH1 ... A_DMA_IN_PERI_SEL_CH1: + esp32c3_gdma_write_chan_conf(s, 1, ESP32C3_GDMA_IN_IDX, addr - A_DMA_IN_CONF0_CH1, value); + break; + + case A_DMA_OUT_CONF0_CH1 ... A_DMA_OUT_PERI_SEL_CH1: + esp32c3_gdma_write_chan_conf(s, 1, ESP32C3_GDMA_OUT_IDX, addr - A_DMA_OUT_CONF0_CH1, value); + break; + + case A_DMA_IN_CONF0_CH2 ... A_DMA_IN_PERI_SEL_CH2: + esp32c3_gdma_write_chan_conf(s, 2, ESP32C3_GDMA_IN_IDX, addr - A_DMA_IN_CONF0_CH2, value); + break; + + case A_DMA_OUT_CONF0_CH2 ... A_DMA_OUT_PERI_SEL_CH2: + esp32c3_gdma_write_chan_conf(s, 2, ESP32C3_GDMA_OUT_IDX, addr - A_DMA_OUT_CONF0_CH2, value); + break; + + default: +#if GDMA_WARNING + warn_report("[GDMA] Unsupported write to %08lx (%08lx)\n", addr, value); +#endif + break; + } + +} + +static const MemoryRegionOps esp32c3_gdma_ops = { + .read = esp32c3_gdma_read, + .write = esp32c3_gdma_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + + +static Property esp32c3_gdma_properties[] = { + DEFINE_PROP_LINK("soc_mr", ESP32C3GdmaState, soc_mr, TYPE_MEMORY_REGION, MemoryRegion*), + DEFINE_PROP_END_OF_LIST(), +}; + + +static void esp32c3_gdma_reset(DeviceState *dev) +{ + ESP32C3GdmaState *s = ESP32C3_GDMA(dev); + memset(s->ch_int, 0, sizeof(s->ch_int)); + memset(s->ch_conf, 0, sizeof(s->ch_conf)); + s->misc_conf = 0; + + /* Set the FIFOs as empty */ + for (int i = 0; i < ESP32C3_GDMA_CHANNEL_COUNT; i++) { + qemu_irq_lower(s->irq[i]); + + for (int j = 0; j < ESP32C3_GDMA_CONF_COUNT; j++) { + esp32c3_gdma_reset_fifo(s, i, j); + } + } + +} + + +static void esp32c3_gdma_realize(DeviceState *dev, Error **errp) +{ + ESP32C3GdmaState *s = ESP32C3_GDMA(dev); + + /* Make sure the DRAM MemoryRegion was set */ + assert(s->soc_mr != NULL); + + address_space_init(&s->dma_as, s->soc_mr, "esp32c3.gdma"); +} + + +static void esp32c3_gdma_init(Object *obj) +{ + ESP32C3GdmaState *s = ESP32C3_GDMA(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_gdma_ops, s, + TYPE_ESP32C3_GDMA, ESP32C3_GDMA_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + + for (int i = 0; i < ESP32C3_GDMA_CHANNEL_COUNT; i++) { + sysbus_init_irq(sbd, &s->irq[i]); + } + + esp32c3_gdma_reset((DeviceState*) s); +} + + +static void esp32c3_gdma_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_gdma_reset; + dc->realize = esp32c3_gdma_realize; + device_class_set_props(dc, esp32c3_gdma_properties); +} + +static const TypeInfo esp32c3_gdma_info = { + .name = TYPE_ESP32C3_GDMA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3GdmaState), + .instance_init = esp32c3_gdma_init, + .class_init = esp32c3_gdma_class_init +}; + +static void esp32c3_gdma_register_types(void) +{ + type_register_static(&esp32c3_gdma_info); +} + +type_init(esp32c3_gdma_register_types) diff --git a/hw/dma/meson.build b/hw/dma/meson.build index f3f0661bc3c3..925f3cc2bdc5 100644 --- a/hw/dma/meson.build +++ b/hw/dma/meson.build @@ -14,3 +14,4 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_dma.c')) softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_dma.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_PDMA', if_true: files('sifive_pdma.c')) softmmu_ss.add(when: 'CONFIG_XLNX_CSU_DMA', if_true: files('xlnx_csu_dma.c')) +softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files('esp32c3_gdma.c')) diff --git a/hw/riscv/esp32c3.c b/hw/riscv/esp32c3.c index 8bd7d6108e8b..bea0f720ec20 100644 --- a/hw/riscv/esp32c3.c +++ b/hw/riscv/esp32c3.c @@ -41,6 +41,7 @@ #include "hw/misc/esp32c3_rtc_cntl.h" #include "hw/misc/esp32c3_aes.h" #include "hw/misc/esp32c3_jtag.h" +#include "hw/dma/esp32c3_gdma.h" #define ESP32C3_IO_WARNING 0 @@ -66,6 +67,7 @@ struct Esp32C3MachineState { ESP32C3CacheState cache; ESP32C3EfuseState efuse; ESP32C3ClockState clock; + ESP32C3GdmaState gdma; ESP32C3AesState aes; ESP32C3ShaState sha; ESP32C3TimgState timg[2]; @@ -171,6 +173,7 @@ static void esp32c3_cpu_reset(void* opaque, int n, int level) device_cold_reset(DEVICE(&s->cache)); device_cold_reset(DEVICE(&s->efuse)); device_cold_reset(DEVICE(&s->clock)); + device_cold_reset(DEVICE(&s->gdma)); device_cold_reset(DEVICE(&s->aes)); device_cold_reset(DEVICE(&s->sha)); device_cold_reset(DEVICE(&s->systimer)); @@ -313,6 +316,7 @@ static void esp32c3_machine_init(MachineState *machine) object_initialize_child(OBJECT(machine), "clock", &ms->clock, TYPE_ESP32C3_CLOCK); object_initialize_child(OBJECT(machine), "sha", &ms->sha, TYPE_ESP32C3_SHA); object_initialize_child(OBJECT(machine), "aes", &ms->aes, TYPE_ESP32C3_AES); + object_initialize_child(OBJECT(machine), "gdma", &ms->gdma, TYPE_ESP32C3_GDMA); object_initialize_child(OBJECT(machine), "timg0", &ms->timg[0], TYPE_ESP32C3_TIMG); object_initialize_child(OBJECT(machine), "timg1", &ms->timg[1], TYPE_ESP32C3_TIMG); object_initialize_child(OBJECT(machine), "systimer", &ms->systimer, TYPE_ESP32C3_SYSTIMER); @@ -469,6 +473,20 @@ static void esp32c3_machine_init(MachineState *machine) } } + /* GDMA Realization */ + { + object_property_set_link(OBJECT(&ms->gdma), "soc_mr", OBJECT(dram), &error_abort); + qdev_realize(DEVICE(&ms->gdma), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->gdma), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_GDMA_BASE, mr, 0); + /* Connect the IRQs to the Interrupt Matrix */ + for (int i = 0; i < ESP32C3_GDMA_CHANNEL_COUNT; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&ms->gdma), i, + qdev_get_gpio_in(intmatrix_dev, ETS_DMA_CH0_INTR_SOURCE + i)); + } + + } + /* Open and load the "bios", which is the ROM binary, also named "first stage bootloader" */ char *rom_binary = qemu_find_file(QEMU_FILE_TYPE_BIOS, "esp32c3-rom.bin"); if (rom_binary == NULL) { diff --git a/include/hw/dma/esp32c3_gdma.h b/include/hw/dma/esp32c3_gdma.h new file mode 100644 index 000000000000..c3e81cf1294b --- /dev/null +++ b/include/hw/dma/esp32c3_gdma.h @@ -0,0 +1,647 @@ +/* + * ESP32-C3 GDMA emulation + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32c3_reg.h" + +#define TYPE_ESP32C3_GDMA "esp32c3.gdma" +#define ESP32C3_GDMA(obj) OBJECT_CHECK(ESP32C3GdmaState, (obj), TYPE_ESP32C3_GDMA) + +#define ESP32C3_GDMA_REGS_SIZE (A_DMA_OUT_PERI_SEL_CH2 + 4) + +#define ESP32C3_GDMA_CHANNEL_COUNT 3 + +#define ESP32C3_GDMA_IN_IDX 0 +#define ESP32C3_GDMA_OUT_IDX 1 +#define ESP32C3_GDMA_CONF_COUNT (ESP32C3_GDMA_OUT_IDX + 1) + +#define ESP32C3_GDMA_RAM_ADDR 0x3FC80000 + + +/** + * @brief Number for each peripheral that can access GDMA + */ +typedef enum { + GDMA_SPI2 = 0, + GDMA_RSVD1 = 1, + GDMA_UHCI0 = 2, + GDMA_I2S = 3, + GDMA_RSVD4 = 4, + GDMA_RSVD5 = 5, + GDMA_AES = 6, + GDMA_SHA = 7, + GDMA_ADC = 8, + GDMA_LAST = GDMA_ADC, +} GdmaPeripheral; + + +/** + * Size of the interrupt registers, in bytes, for a single channel + */ +#define ESP32C3_GDMA_INT_REGS_SIZE 0x10 + +typedef struct { + uint32_t raw; + uint32_t st; + uint32_t ena; + /* Not really necessary to have this variable here as it will never contain + * any data, but will simplify the code (offset calculation) */ + uint32_t clr; +} DmaIntState; + + +typedef struct { + uint32_t conf0; + uint32_t conf1; + uint32_t status; + uint32_t push_pop; + uint32_t link; + /* Status registers */ + uint32_t state; + uint32_t suc_eof_desc_addr; // Address of descriptor when EOF bit is 1 + uint32_t err_eof_desc_addr; // Address of descriptor when error occurs (UHCI0 only) + uint32_t desc_addr; // Address of the next descriptor (n + 1) + uint32_t bfr_desc_addr; // Address of the current descriptor (n) + uint32_t bfr_bfr_desc_addr; // Address of the previous descriptor (n - 1) + uint32_t priority; + uint32_t peripheral; +} DmaConfigState; + + +typedef struct ESP32C3GdmaState { + SysBusDevice parent_object; + MemoryRegion iomem; + qemu_irq irq[ESP32C3_GDMA_CHANNEL_COUNT]; + + DmaIntState ch_int[ESP32C3_GDMA_CHANNEL_COUNT]; + DmaConfigState ch_conf[ESP32C3_GDMA_CHANNEL_COUNT][ESP32C3_GDMA_CONF_COUNT]; + + /* Use this register mainly for enabling and disabling priorities */ + uint32_t misc_conf; + + /* Keep a pointer to the SoC DRAM */ + MemoryRegion* soc_mr; + AddressSpace dma_as; + +} ESP32C3GdmaState; + + +/** + * @brief Get the channel configured for the given peripheral + * + * @param s GDMA state + * @param periph Peripheral to search + * @param dir Direction: ESP32C3_GDMA_IN_IDX or ESP32C3_GDMA_OUT_IDX + * + * @returns index of the GDMA channel bound to the peripheral, -1 if not found + */ +int esp32c3_gdma_get_channel_periph(ESP32C3GdmaState *s, GdmaPeripheral periph, int dir); + + +REG32(DMA_INT_RAW_CH0, 0x000) + FIELD(DMA_INT_RAW_CH0, OUTFIFO_UDF_CH0_INT_RAW, 12, 1) + FIELD(DMA_INT_RAW_CH0, OUTFIFO_OVF_CH0_INT_RAW, 11, 1) + FIELD(DMA_INT_RAW_CH0, INFIFO_UDF_CH0_INT_RAW, 10, 1) + FIELD(DMA_INT_RAW_CH0, INFIFO_OVF_CH0_INT_RAW, 9, 1) + FIELD(DMA_INT_RAW_CH0, OUT_TOTAL_EOF_CH0_INT_RAW, 8, 1) + FIELD(DMA_INT_RAW_CH0, IN_DSCR_EMPTY_CH0_INT_RAW, 7, 1) + FIELD(DMA_INT_RAW_CH0, OUT_DSCR_ERR_CH0_INT_RAW, 6, 1) + FIELD(DMA_INT_RAW_CH0, IN_DSCR_ERR_CH0_INT_RAW, 5, 1) + FIELD(DMA_INT_RAW_CH0, OUT_EOF_CH0_INT_RAW, 4, 1) + FIELD(DMA_INT_RAW_CH0, OUT_DONE_CH0_INT_RAW, 3, 1) + FIELD(DMA_INT_RAW_CH0, IN_ERR_EOF_CH0_INT_RAW, 2, 1) + FIELD(DMA_INT_RAW_CH0, IN_SUC_EOF_CH0_INT_RAW, 1, 1) + FIELD(DMA_INT_RAW_CH0, IN_DONE_CH0_INT_RAW, 0, 1) + +REG32(DMA_INT_ST_CH0, 0x004) + FIELD(DMA_INT_ST_CH0, OUTFIFO_UDF_CH0_INT_ST, 12, 1) + FIELD(DMA_INT_ST_CH0, OUTFIFO_OVF_CH0_INT_ST, 11, 1) + FIELD(DMA_INT_ST_CH0, INFIFO_UDF_CH0_INT_ST, 10, 1) + FIELD(DMA_INT_ST_CH0, INFIFO_OVF_CH0_INT_ST, 9, 1) + FIELD(DMA_INT_ST_CH0, OUT_TOTAL_EOF_CH0_INT_ST, 8, 1) + FIELD(DMA_INT_ST_CH0, IN_DSCR_EMPTY_CH0_INT_ST, 7, 1) + FIELD(DMA_INT_ST_CH0, OUT_DSCR_ERR_CH0_INT_ST, 6, 1) + FIELD(DMA_INT_ST_CH0, IN_DSCR_ERR_CH0_INT_ST, 5, 1) + FIELD(DMA_INT_ST_CH0, OUT_EOF_CH0_INT_ST, 4, 1) + FIELD(DMA_INT_ST_CH0, OUT_DONE_CH0_INT_ST, 3, 1) + FIELD(DMA_INT_ST_CH0, IN_ERR_EOF_CH0_INT_ST, 2, 1) + FIELD(DMA_INT_ST_CH0, IN_SUC_EOF_CH0_INT_ST, 1, 1) + FIELD(DMA_INT_ST_CH0, IN_DONE_CH0_INT_ST, 0, 1) + +REG32(DMA_INT_ENA_CH0, 0x008) + FIELD(DMA_INT_ENA_CH0, OUTFIFO_UDF_CH0_INT_ENA, 12, 1) + FIELD(DMA_INT_ENA_CH0, OUTFIFO_OVF_CH0_INT_ENA, 11, 1) + FIELD(DMA_INT_ENA_CH0, INFIFO_UDF_CH0_INT_ENA, 10, 1) + FIELD(DMA_INT_ENA_CH0, INFIFO_OVF_CH0_INT_ENA, 9, 1) + FIELD(DMA_INT_ENA_CH0, OUT_TOTAL_EOF_CH0_INT_ENA, 8, 1) + FIELD(DMA_INT_ENA_CH0, IN_DSCR_EMPTY_CH0_INT_ENA, 7, 1) + FIELD(DMA_INT_ENA_CH0, OUT_DSCR_ERR_CH0_INT_ENA, 6, 1) + FIELD(DMA_INT_ENA_CH0, IN_DSCR_ERR_CH0_INT_ENA, 5, 1) + FIELD(DMA_INT_ENA_CH0, OUT_EOF_CH0_INT_ENA, 4, 1) + FIELD(DMA_INT_ENA_CH0, OUT_DONE_CH0_INT_ENA, 3, 1) + FIELD(DMA_INT_ENA_CH0, IN_ERR_EOF_CH0_INT_ENA, 2, 1) + FIELD(DMA_INT_ENA_CH0, IN_SUC_EOF_CH0_INT_ENA, 1, 1) + FIELD(DMA_INT_ENA_CH0, IN_DONE_CH0_INT_ENA, 0, 1) + +REG32(DMA_INT_CLR_CH0, 0x00C) + FIELD(DMA_INT_CLR_CH0, OUTFIFO_UDF_CH0_INT_CLR, 12, 1) + FIELD(DMA_INT_CLR_CH0, OUTFIFO_OVF_CH0_INT_CLR, 11, 1) + FIELD(DMA_INT_CLR_CH0, INFIFO_UDF_CH0_INT_CLR, 10, 1) + FIELD(DMA_INT_CLR_CH0, INFIFO_OVF_CH0_INT_CLR, 9, 1) + FIELD(DMA_INT_CLR_CH0, OUT_TOTAL_EOF_CH0_INT_CLR, 8, 1) + FIELD(DMA_INT_CLR_CH0, IN_DSCR_EMPTY_CH0_INT_CLR, 7, 1) + FIELD(DMA_INT_CLR_CH0, OUT_DSCR_ERR_CH0_INT_CLR, 6, 1) + FIELD(DMA_INT_CLR_CH0, IN_DSCR_ERR_CH0_INT_CLR, 5, 1) + FIELD(DMA_INT_CLR_CH0, OUT_EOF_CH0_INT_CLR, 4, 1) + FIELD(DMA_INT_CLR_CH0, OUT_DONE_CH0_INT_CLR, 3, 1) + FIELD(DMA_INT_CLR_CH0, IN_ERR_EOF_CH0_INT_CLR, 2, 1) + FIELD(DMA_INT_CLR_CH0, IN_SUC_EOF_CH0_INT_CLR, 1, 1) + FIELD(DMA_INT_CLR_CH0, IN_DONE_CH0_INT_CLR, 0, 1) + +REG32(DMA_INT_RAW_CH1, 0x010) + FIELD(DMA_INT_RAW_CH1, OUTFIFO_UDF_CH1_INT_RAW, 12, 1) + FIELD(DMA_INT_RAW_CH1, OUTFIFO_OVF_CH1_INT_RAW, 11, 1) + FIELD(DMA_INT_RAW_CH1, INFIFO_UDF_CH1_INT_RAW, 10, 1) + FIELD(DMA_INT_RAW_CH1, INFIFO_OVF_CH1_INT_RAW, 9, 1) + FIELD(DMA_INT_RAW_CH1, OUT_TOTAL_EOF_CH1_INT_RAW, 8, 1) + FIELD(DMA_INT_RAW_CH1, IN_DSCR_EMPTY_CH1_INT_RAW, 7, 1) + FIELD(DMA_INT_RAW_CH1, OUT_DSCR_ERR_CH1_INT_RAW, 6, 1) + FIELD(DMA_INT_RAW_CH1, IN_DSCR_ERR_CH1_INT_RAW, 5, 1) + FIELD(DMA_INT_RAW_CH1, OUT_EOF_CH1_INT_RAW, 4, 1) + FIELD(DMA_INT_RAW_CH1, OUT_DONE_CH1_INT_RAW, 3, 1) + FIELD(DMA_INT_RAW_CH1, IN_ERR_EOF_CH1_INT_RAW, 2, 1) + FIELD(DMA_INT_RAW_CH1, IN_SUC_EOF_CH1_INT_RAW, 1, 1) + FIELD(DMA_INT_RAW_CH1, IN_DONE_CH1_INT_RAW, 0, 1) + +REG32(DMA_INT_ST_CH1, 0x014) + FIELD(DMA_INT_ST_CH1, OUTFIFO_UDF_CH1_INT_ST, 12, 1) + FIELD(DMA_INT_ST_CH1, OUTFIFO_OVF_CH1_INT_ST, 11, 1) + FIELD(DMA_INT_ST_CH1, INFIFO_UDF_CH1_INT_ST, 10, 1) + FIELD(DMA_INT_ST_CH1, INFIFO_OVF_CH1_INT_ST, 9, 1) + FIELD(DMA_INT_ST_CH1, OUT_TOTAL_EOF_CH1_INT_ST, 8, 1) + FIELD(DMA_INT_ST_CH1, IN_DSCR_EMPTY_CH1_INT_ST, 7, 1) + FIELD(DMA_INT_ST_CH1, OUT_DSCR_ERR_CH1_INT_ST, 6, 1) + FIELD(DMA_INT_ST_CH1, IN_DSCR_ERR_CH1_INT_ST, 5, 1) + FIELD(DMA_INT_ST_CH1, OUT_EOF_CH1_INT_ST, 4, 1) + FIELD(DMA_INT_ST_CH1, OUT_DONE_CH1_INT_ST, 3, 1) + FIELD(DMA_INT_ST_CH1, IN_ERR_EOF_CH1_INT_ST, 2, 1) + FIELD(DMA_INT_ST_CH1, IN_SUC_EOF_CH1_INT_ST, 1, 1) + FIELD(DMA_INT_ST_CH1, IN_DONE_CH1_INT_ST, 0, 1) + +REG32(DMA_INT_ENA_CH1, 0x018) + FIELD(DMA_INT_ENA_CH1, OUTFIFO_UDF_CH1_INT_ENA, 12, 1) + FIELD(DMA_INT_ENA_CH1, OUTFIFO_OVF_CH1_INT_ENA, 11, 1) + FIELD(DMA_INT_ENA_CH1, INFIFO_UDF_CH1_INT_ENA, 10, 1) + FIELD(DMA_INT_ENA_CH1, INFIFO_OVF_CH1_INT_ENA, 9, 1) + FIELD(DMA_INT_ENA_CH1, OUT_TOTAL_EOF_CH1_INT_ENA, 8, 1) + FIELD(DMA_INT_ENA_CH1, IN_DSCR_EMPTY_CH1_INT_ENA, 7, 1) + FIELD(DMA_INT_ENA_CH1, OUT_DSCR_ERR_CH1_INT_ENA, 6, 1) + FIELD(DMA_INT_ENA_CH1, IN_DSCR_ERR_CH1_INT_ENA, 5, 1) + FIELD(DMA_INT_ENA_CH1, OUT_EOF_CH1_INT_ENA, 4, 1) + FIELD(DMA_INT_ENA_CH1, OUT_DONE_CH1_INT_ENA, 3, 1) + FIELD(DMA_INT_ENA_CH1, IN_ERR_EOF_CH1_INT_ENA, 2, 1) + FIELD(DMA_INT_ENA_CH1, IN_SUC_EOF_CH1_INT_ENA, 1, 1) + FIELD(DMA_INT_ENA_CH1, IN_DONE_CH1_INT_ENA, 0, 1) + +REG32(DMA_INT_CLR_CH1, 0x01C) + FIELD(DMA_INT_CLR_CH1, OUTFIFO_UDF_CH1_INT_CLR, 12, 1) + FIELD(DMA_INT_CLR_CH1, OUTFIFO_OVF_CH1_INT_CLR, 11, 1) + FIELD(DMA_INT_CLR_CH1, INFIFO_UDF_CH1_INT_CLR, 10, 1) + FIELD(DMA_INT_CLR_CH1, INFIFO_OVF_CH1_INT_CLR, 9, 1) + FIELD(DMA_INT_CLR_CH1, OUT_TOTAL_EOF_CH1_INT_CLR, 8, 1) + FIELD(DMA_INT_CLR_CH1, IN_DSCR_EMPTY_CH1_INT_CLR, 7, 1) + FIELD(DMA_INT_CLR_CH1, OUT_DSCR_ERR_CH1_INT_CLR, 6, 1) + FIELD(DMA_INT_CLR_CH1, IN_DSCR_ERR_CH1_INT_CLR, 5, 1) + FIELD(DMA_INT_CLR_CH1, OUT_EOF_CH1_INT_CLR, 4, 1) + FIELD(DMA_INT_CLR_CH1, OUT_DONE_CH1_INT_CLR, 3, 1) + FIELD(DMA_INT_CLR_CH1, IN_ERR_EOF_CH1_INT_CLR, 2, 1) + FIELD(DMA_INT_CLR_CH1, IN_SUC_EOF_CH1_INT_CLR, 1, 1) + FIELD(DMA_INT_CLR_CH1, IN_DONE_CH1_INT_CLR, 0, 1) + +REG32(DMA_INT_RAW_CH2, 0x020) + FIELD(DMA_INT_RAW_CH2, OUTFIFO_UDF_CH2_INT_RAW, 12, 1) + FIELD(DMA_INT_RAW_CH2, OUTFIFO_OVF_CH2_INT_RAW, 11, 1) + FIELD(DMA_INT_RAW_CH2, INFIFO_UDF_CH2_INT_RAW, 10, 1) + FIELD(DMA_INT_RAW_CH2, INFIFO_OVF_CH2_INT_RAW, 9, 1) + FIELD(DMA_INT_RAW_CH2, OUT_TOTAL_EOF_CH2_INT_RAW, 8, 1) + FIELD(DMA_INT_RAW_CH2, IN_DSCR_EMPTY_CH2_INT_RAW, 7, 1) + FIELD(DMA_INT_RAW_CH2, OUT_DSCR_ERR_CH2_INT_RAW, 6, 1) + FIELD(DMA_INT_RAW_CH2, IN_DSCR_ERR_CH2_INT_RAW, 5, 1) + FIELD(DMA_INT_RAW_CH2, OUT_EOF_CH2_INT_RAW, 4, 1) + FIELD(DMA_INT_RAW_CH2, OUT_DONE_CH2_INT_RAW, 3, 1) + FIELD(DMA_INT_RAW_CH2, IN_ERR_EOF_CH2_INT_RAW, 2, 1) + FIELD(DMA_INT_RAW_CH2, IN_SUC_EOF_CH2_INT_RAW, 1, 1) + FIELD(DMA_INT_RAW_CH2, IN_DONE_CH2_INT_RAW, 0, 1) + +REG32(DMA_INT_ST_CH2, 0x024) + FIELD(DMA_INT_ST_CH2, OUTFIFO_UDF_CH2_INT_ST, 12, 1) + FIELD(DMA_INT_ST_CH2, OUTFIFO_OVF_CH2_INT_ST, 11, 1) + FIELD(DMA_INT_ST_CH2, INFIFO_UDF_CH2_INT_ST, 10, 1) + FIELD(DMA_INT_ST_CH2, INFIFO_OVF_CH2_INT_ST, 9, 1) + FIELD(DMA_INT_ST_CH2, OUT_TOTAL_EOF_CH2_INT_ST, 8, 1) + FIELD(DMA_INT_ST_CH2, IN_DSCR_EMPTY_CH2_INT_ST, 7, 1) + FIELD(DMA_INT_ST_CH2, OUT_DSCR_ERR_CH2_INT_ST, 6, 1) + FIELD(DMA_INT_ST_CH2, IN_DSCR_ERR_CH2_INT_ST, 5, 1) + FIELD(DMA_INT_ST_CH2, OUT_EOF_CH2_INT_ST, 4, 1) + FIELD(DMA_INT_ST_CH2, OUT_DONE_CH2_INT_ST, 3, 1) + FIELD(DMA_INT_ST_CH2, IN_ERR_EOF_CH2_INT_ST, 2, 1) + FIELD(DMA_INT_ST_CH2, IN_SUC_EOF_CH2_INT_ST, 1, 1) + FIELD(DMA_INT_ST_CH2, IN_DONE_CH2_INT_ST, 0, 1) + +REG32(DMA_INT_ENA_CH2, 0x028) + FIELD(DMA_INT_ENA_CH2, OUTFIFO_UDF_CH2_INT_ENA, 12, 1) + FIELD(DMA_INT_ENA_CH2, OUTFIFO_OVF_CH2_INT_ENA, 11, 1) + FIELD(DMA_INT_ENA_CH2, INFIFO_UDF_CH2_INT_ENA, 10, 1) + FIELD(DMA_INT_ENA_CH2, INFIFO_OVF_CH2_INT_ENA, 9, 1) + FIELD(DMA_INT_ENA_CH2, OUT_TOTAL_EOF_CH2_INT_ENA, 8, 1) + FIELD(DMA_INT_ENA_CH2, IN_DSCR_EMPTY_CH2_INT_ENA, 7, 1) + FIELD(DMA_INT_ENA_CH2, OUT_DSCR_ERR_CH2_INT_ENA, 6, 1) + FIELD(DMA_INT_ENA_CH2, IN_DSCR_ERR_CH2_INT_ENA, 5, 1) + FIELD(DMA_INT_ENA_CH2, OUT_EOF_CH2_INT_ENA, 4, 1) + FIELD(DMA_INT_ENA_CH2, OUT_DONE_CH2_INT_ENA, 3, 1) + FIELD(DMA_INT_ENA_CH2, IN_ERR_EOF_CH2_INT_ENA, 2, 1) + FIELD(DMA_INT_ENA_CH2, IN_SUC_EOF_CH2_INT_ENA, 1, 1) + FIELD(DMA_INT_ENA_CH2, IN_DONE_CH2_INT_ENA, 0, 1) + +REG32(DMA_INT_CLR_CH2, 0x02C) + FIELD(DMA_INT_CLR_CH2, OUTFIFO_UDF_CH2_INT_CLR, 12, 1) + FIELD(DMA_INT_CLR_CH2, OUTFIFO_OVF_CH2_INT_CLR, 11, 1) + FIELD(DMA_INT_CLR_CH2, INFIFO_UDF_CH2_INT_CLR, 10, 1) + FIELD(DMA_INT_CLR_CH2, INFIFO_OVF_CH2_INT_CLR, 9, 1) + FIELD(DMA_INT_CLR_CH2, OUT_TOTAL_EOF_CH2_INT_CLR, 8, 1) + FIELD(DMA_INT_CLR_CH2, IN_DSCR_EMPTY_CH2_INT_CLR, 7, 1) + FIELD(DMA_INT_CLR_CH2, OUT_DSCR_ERR_CH2_INT_CLR, 6, 1) + FIELD(DMA_INT_CLR_CH2, IN_DSCR_ERR_CH2_INT_CLR, 5, 1) + FIELD(DMA_INT_CLR_CH2, OUT_EOF_CH2_INT_CLR, 4, 1) + FIELD(DMA_INT_CLR_CH2, OUT_DONE_CH2_INT_CLR, 3, 1) + FIELD(DMA_INT_CLR_CH2, IN_ERR_EOF_CH2_INT_CLR, 2, 1) + FIELD(DMA_INT_CLR_CH2, IN_SUC_EOF_CH2_INT_CLR, 1, 1) + FIELD(DMA_INT_CLR_CH2, IN_DONE_CH2_INT_CLR, 0, 1) + +REG32(DMA_AHB_TEST, 0x040) + FIELD(DMA_AHB_TEST, AHB_TESTADDR, 4, 2) + FIELD(DMA_AHB_TEST, AHB_TESTMODE, 0, 3) + +REG32(DMA_MISC_CONF, 0x044) + FIELD(DMA_MISC_CONF, CLK_EN, 3, 1) + FIELD(DMA_MISC_CONF, ARB_PRI_DIS, 2, 1) + FIELD(DMA_MISC_CONF, AHBM_RST_INTER, 0, 1) + +REG32(DMA_DATE, 0x048) + FIELD(DMA_DATE, DATE, 0, 32) + +REG32(DMA_IN_CONF0_CH0, 0x070) + FIELD(DMA_IN_CONF0_CH0, MEM_TRANS_EN_CH0, 4, 1) + FIELD(DMA_IN_CONF0_CH0, IN_DATA_BURST_EN_CH0, 3, 1) + FIELD(DMA_IN_CONF0_CH0, INDSCR_BURST_EN_CH0, 2, 1) + FIELD(DMA_IN_CONF0_CH0, IN_LOOP_TEST_CH0, 1, 1) + FIELD(DMA_IN_CONF0_CH0, IN_RST_CH0, 0, 1) + +REG32(DMA_IN_CONF1_CH0, 0x074) + FIELD(DMA_IN_CONF1_CH0, IN_CHECK_OWNER_CH0, 12, 1) + +REG32(DMA_INFIFO_STATUS_CH0, 0x078) + FIELD(DMA_INFIFO_STATUS_CH0, IN_BUF_HUNGRY_CH0, 27, 1) + FIELD(DMA_INFIFO_STATUS_CH0, IN_REMAIN_UNDER_4B_CH0, 26, 1) + FIELD(DMA_INFIFO_STATUS_CH0, IN_REMAIN_UNDER_3B_CH0, 25, 1) + FIELD(DMA_INFIFO_STATUS_CH0, IN_REMAIN_UNDER_2B_CH0, 24, 1) + FIELD(DMA_INFIFO_STATUS_CH0, IN_REMAIN_UNDER_1B_CH0, 23, 1) + FIELD(DMA_INFIFO_STATUS_CH0, INFIFO_CNT_CH0, 2, 6) + FIELD(DMA_INFIFO_STATUS_CH0, INFIFO_EMPTY_CH0, 1, 1) + FIELD(DMA_INFIFO_STATUS_CH0, INFIFO_FULL_CH0, 0, 1) + +REG32(DMA_IN_POP_CH0, 0x07C) + FIELD(DMA_IN_POP_CH0, INFIFO_POP_CH0, 12, 1) + FIELD(DMA_IN_POP_CH0, INFIFO_RDATA_CH0, 0, 12) + +REG32(DMA_IN_LINK_CH0, 0x080) + FIELD(DMA_IN_LINK_CH0, INLINK_PARK_CH0, 24, 1) + FIELD(DMA_IN_LINK_CH0, INLINK_RESTART_CH0, 23, 1) + FIELD(DMA_IN_LINK_CH0, INLINK_START_CH0, 22, 1) + FIELD(DMA_IN_LINK_CH0, INLINK_STOP_CH0, 21, 1) + FIELD(DMA_IN_LINK_CH0, INLINK_AUTO_RET_CH0, 20, 1) + FIELD(DMA_IN_LINK_CH0, INLINK_ADDR_CH0, 0, 20) + +REG32(DMA_IN_STATE_CH0, 0x084) + FIELD(DMA_IN_STATE_CH0, IN_STATE_CH0, 20, 3) + FIELD(DMA_IN_STATE_CH0, IN_DSCR_STATE_CH0, 18, 2) + FIELD(DMA_IN_STATE_CH0, INLINK_DSCR_ADDR_CH0, 0, 18) + +REG32(DMA_IN_SUC_EOF_DES_ADDR_CH0, 0x088) + FIELD(DMA_IN_SUC_EOF_DES_ADDR_CH0, IN_SUC_EOF_DES_ADDR_CH0, 0, 32) + +REG32(DMA_IN_ERR_EOF_DES_ADDR_CH0, 0x08C) + FIELD(DMA_IN_ERR_EOF_DES_ADDR_CH0, IN_ERR_EOF_DES_ADDR_CH0, 0, 32) + +REG32(DMA_IN_DSCR_CH0, 0x090) + FIELD(DMA_IN_DSCR_CH0, INLINK_DSCR_CH0, 0, 32) + +REG32(DMA_IN_DSCR_BF0_CH0, 0x094) + FIELD(DMA_IN_DSCR_BF0_CH0, INLINK_DSCR_BF0_CH0, 0, 32) + +REG32(DMA_IN_DSCR_BF1_CH0, 0x098) + FIELD(DMA_IN_DSCR_BF1_CH0, INLINK_DSCR_BF1_CH0, 0, 32) + +REG32(DMA_IN_PRI_CH0, 0x09C) + FIELD(DMA_IN_PRI_CH0, RX_PRI_CH0, 0, 4) + +REG32(DMA_IN_PERI_SEL_CH0, 0x0A0) + FIELD(DMA_IN_PERI_SEL_CH0, PERI_IN_SEL_CH0, 0, 6) + +REG32(DMA_OUT_CONF0_CH0, 0x0D0) + FIELD(DMA_OUT_CONF0_CH0, OUT_DATA_BURST_EN_CH0, 5, 1) + FIELD(DMA_OUT_CONF0_CH0, OUTDSCR_BURST_EN_CH0, 4, 1) + FIELD(DMA_OUT_CONF0_CH0, OUT_EOF_MODE_CH0, 3, 1) + FIELD(DMA_OUT_CONF0_CH0, OUT_AUTO_WRBACK_CH0, 2, 1) + FIELD(DMA_OUT_CONF0_CH0, OUT_LOOP_TEST_CH0, 1, 1) + FIELD(DMA_OUT_CONF0_CH0, OUT_RST_CH0, 0, 1) + +REG32(DMA_OUT_CONF1_CH0, 0x0D4) + FIELD(DMA_OUT_CONF1_CH0, OUT_CHECK_OWNER_CH0, 12, 1) + +REG32(DMA_OUTFIFO_STATUS_CH0, 0x0D8) + FIELD(DMA_OUTFIFO_STATUS_CH0, OUT_REMAIN_UNDER_4B_CH0, 26, 1) + FIELD(DMA_OUTFIFO_STATUS_CH0, OUT_REMAIN_UNDER_3B_CH0, 25, 1) + FIELD(DMA_OUTFIFO_STATUS_CH0, OUT_REMAIN_UNDER_2B_CH0, 24, 1) + FIELD(DMA_OUTFIFO_STATUS_CH0, OUT_REMAIN_UNDER_1B_CH0, 23, 1) + FIELD(DMA_OUTFIFO_STATUS_CH0, OUTFIFO_CNT_CH0, 2, 6) + FIELD(DMA_OUTFIFO_STATUS_CH0, OUTFIFO_EMPTY_CH0, 1, 1) + FIELD(DMA_OUTFIFO_STATUS_CH0, OUTFIFO_FULL_CH0, 0, 1) + +REG32(DMA_OUT_PUSH_CH0, 0x0DC) + FIELD(DMA_OUT_PUSH_CH0, OUTFIFO_PUSH_CH0, 9, 1) + FIELD(DMA_OUT_PUSH_CH0, OUTFIFO_WDATA_CH0, 0, 9) + +REG32(DMA_OUT_LINK_CH0, 0x0E0) + FIELD(DMA_OUT_LINK_CH0, OUTLINK_PARK_CH0, 23, 1) + FIELD(DMA_OUT_LINK_CH0, OUTLINK_RESTART_CH0, 22, 1) + FIELD(DMA_OUT_LINK_CH0, OUTLINK_START_CH0, 21, 1) + FIELD(DMA_OUT_LINK_CH0, OUTLINK_STOP_CH0, 20, 1) + FIELD(DMA_OUT_LINK_CH0, OUTLINK_ADDR_CH0, 0, 20) + +REG32(DMA_OUT_STATE_CH0, 0x0E4) + FIELD(DMA_OUT_STATE_CH0, OUT_STATE_CH0, 20, 3) + FIELD(DMA_OUT_STATE_CH0, OUT_DSCR_STATE_CH0, 18, 2) + FIELD(DMA_OUT_STATE_CH0, OUTLINK_DSCR_ADDR_CH0, 0, 18) + +REG32(DMA_OUT_EOF_DES_ADDR_CH0, 0x0E8) + FIELD(DMA_OUT_EOF_DES_ADDR_CH0, OUT_EOF_DES_ADDR_CH0, 0, 32) + +REG32(DMA_OUT_EOF_BFR_DES_ADDR_CH0, 0x0EC) + FIELD(DMA_OUT_EOF_BFR_DES_ADDR_CH0, OUT_EOF_BFR_DES_ADDR_CH0, 0, 32) + +REG32(DMA_OUT_DSCR_CH0, 0x0F0) + FIELD(DMA_OUT_DSCR_CH0, OUTLINK_DSCR_CH0, 0, 32) + +REG32(DMA_OUT_DSCR_BF0_CH0, 0x0F4) + FIELD(DMA_OUT_DSCR_BF0_CH0, OUTLINK_DSCR_BF0_CH0, 0, 32) + +REG32(DMA_OUT_DSCR_BF1_CH0, 0x0F8) + FIELD(DMA_OUT_DSCR_BF1_CH0, OUTLINK_DSCR_BF1_CH0, 0, 32) + +REG32(DMA_OUT_PRI_CH0, 0x0FC) + FIELD(DMA_OUT_PRI_CH0, TX_PRI_CH0, 0, 4) + +REG32(DMA_OUT_PERI_SEL_CH0, 0x100) + FIELD(DMA_OUT_PERI_SEL_CH0, PERI_OUT_SEL_CH0, 0, 6) + +REG32(DMA_IN_CONF0_CH1, 0x130) + FIELD(DMA_IN_CONF0_CH1, MEM_TRANS_EN_CH1, 4, 1) + FIELD(DMA_IN_CONF0_CH1, IN_DATA_BURST_EN_CH1, 3, 1) + FIELD(DMA_IN_CONF0_CH1, INDSCR_BURST_EN_CH1, 2, 1) + FIELD(DMA_IN_CONF0_CH1, IN_LOOP_TEST_CH1, 1, 1) + FIELD(DMA_IN_CONF0_CH1, IN_RST_CH1, 0, 1) + +REG32(DMA_IN_CONF1_CH1, 0x134) + FIELD(DMA_IN_CONF1_CH1, IN_CHECK_OWNER_CH1, 12, 1) + +REG32(DMA_INFIFO_STATUS_CH1, 0x138) + FIELD(DMA_INFIFO_STATUS_CH1, IN_BUF_HUNGRY_CH1, 27, 1) + FIELD(DMA_INFIFO_STATUS_CH1, IN_REMAIN_UNDER_4B_CH1, 26, 1) + FIELD(DMA_INFIFO_STATUS_CH1, IN_REMAIN_UNDER_3B_CH1, 25, 1) + FIELD(DMA_INFIFO_STATUS_CH1, IN_REMAIN_UNDER_2B_CH1, 24, 1) + FIELD(DMA_INFIFO_STATUS_CH1, IN_REMAIN_UNDER_1B_CH1, 23, 1) + FIELD(DMA_INFIFO_STATUS_CH1, INFIFO_CNT_CH1, 2, 6) + FIELD(DMA_INFIFO_STATUS_CH1, INFIFO_EMPTY_CH1, 1, 1) + FIELD(DMA_INFIFO_STATUS_CH1, INFIFO_FULL_CH1, 0, 1) + +REG32(DMA_IN_POP_CH1, 0x13C) + FIELD(DMA_IN_POP_CH1, INFIFO_POP_CH1, 12, 1) + FIELD(DMA_IN_POP_CH1, INFIFO_RDATA_CH1, 0, 12) + +REG32(DMA_IN_LINK_CH1, 0x140) + FIELD(DMA_IN_LINK_CH1, INLINK_PARK_CH1, 24, 1) + FIELD(DMA_IN_LINK_CH1, INLINK_RESTART_CH1, 23, 1) + FIELD(DMA_IN_LINK_CH1, INLINK_START_CH1, 22, 1) + FIELD(DMA_IN_LINK_CH1, INLINK_STOP_CH1, 21, 1) + FIELD(DMA_IN_LINK_CH1, INLINK_AUTO_RET_CH1, 20, 1) + FIELD(DMA_IN_LINK_CH1, INLINK_ADDR_CH1, 0, 20) + +REG32(DMA_IN_STATE_CH1, 0x144) + FIELD(DMA_IN_STATE_CH1, IN_STATE_CH1, 20, 3) + FIELD(DMA_IN_STATE_CH1, IN_DSCR_STATE_CH1, 18, 2) + FIELD(DMA_IN_STATE_CH1, INLINK_DSCR_ADDR_CH1, 0, 18) + +REG32(DMA_IN_SUC_EOF_DES_ADDR_CH1, 0x148) + FIELD(DMA_IN_SUC_EOF_DES_ADDR_CH1, IN_SUC_EOF_DES_ADDR_CH1, 0, 32) + +REG32(DMA_IN_ERR_EOF_DES_ADDR_CH1, 0x14C) + FIELD(DMA_IN_ERR_EOF_DES_ADDR_CH1, IN_ERR_EOF_DES_ADDR_CH1, 0, 32) + +REG32(DMA_IN_DSCR_CH1, 0x150) + FIELD(DMA_IN_DSCR_CH1, INLINK_DSCR_CH1, 0, 32) + +REG32(DMA_IN_DSCR_BF0_CH1, 0x154) + FIELD(DMA_IN_DSCR_BF0_CH1, INLINK_DSCR_BF0_CH1, 0, 32) + +REG32(DMA_IN_DSCR_BF1_CH1, 0x158) + FIELD(DMA_IN_DSCR_BF1_CH1, INLINK_DSCR_BF1_CH1, 0, 32) + +REG32(DMA_IN_PRI_CH1, 0x15C) + FIELD(DMA_IN_PRI_CH1, RX_PRI_CH1, 0, 4) + +REG32(DMA_IN_PERI_SEL_CH1, 0x160) + FIELD(DMA_IN_PERI_SEL_CH1, PERI_IN_SEL_CH1, 0, 6) + +REG32(DMA_OUT_CONF0_CH1, 0x190) + FIELD(DMA_OUT_CONF0_CH1, OUT_DATA_BURST_EN_CH1, 5, 1) + FIELD(DMA_OUT_CONF0_CH1, OUTDSCR_BURST_EN_CH1, 4, 1) + FIELD(DMA_OUT_CONF0_CH1, OUT_EOF_MODE_CH1, 3, 1) + FIELD(DMA_OUT_CONF0_CH1, OUT_AUTO_WRBACK_CH1, 2, 1) + FIELD(DMA_OUT_CONF0_CH1, OUT_LOOP_TEST_CH1, 1, 1) + FIELD(DMA_OUT_CONF0_CH1, OUT_RST_CH1, 0, 1) + +REG32(DMA_OUT_CONF1_CH1, 0x194) + FIELD(DMA_OUT_CONF1_CH1, OUT_CHECK_OWNER_CH1, 12, 1) + +REG32(DMA_OUTFIFO_STATUS_CH1, 0x198) + FIELD(DMA_OUTFIFO_STATUS_CH1, OUT_REMAIN_UNDER_4B_CH1, 26, 1) + FIELD(DMA_OUTFIFO_STATUS_CH1, OUT_REMAIN_UNDER_3B_CH1, 25, 1) + FIELD(DMA_OUTFIFO_STATUS_CH1, OUT_REMAIN_UNDER_2B_CH1, 24, 1) + FIELD(DMA_OUTFIFO_STATUS_CH1, OUT_REMAIN_UNDER_1B_CH1, 23, 1) + FIELD(DMA_OUTFIFO_STATUS_CH1, OUTFIFO_CNT_CH1, 2, 6) + FIELD(DMA_OUTFIFO_STATUS_CH1, OUTFIFO_EMPTY_CH1, 1, 1) + FIELD(DMA_OUTFIFO_STATUS_CH1, OUTFIFO_FULL_CH1, 0, 1) + +REG32(DMA_OUT_PUSH_CH1, 0x19C) + FIELD(DMA_OUT_PUSH_CH1, OUTFIFO_PUSH_CH1, 9, 1) + FIELD(DMA_OUT_PUSH_CH1, OUTFIFO_WDATA_CH1, 0, 9) + +REG32(DMA_OUT_LINK_CH1, 0x1A0) + FIELD(DMA_OUT_LINK_CH1, OUTLINK_PARK_CH1, 23, 1) + FIELD(DMA_OUT_LINK_CH1, OUTLINK_RESTART_CH1, 22, 1) + FIELD(DMA_OUT_LINK_CH1, OUTLINK_START_CH1, 21, 1) + FIELD(DMA_OUT_LINK_CH1, OUTLINK_STOP_CH1, 20, 1) + FIELD(DMA_OUT_LINK_CH1, OUTLINK_ADDR_CH1, 0, 20) + +REG32(DMA_OUT_STATE_CH1, 0x1A4) + FIELD(DMA_OUT_STATE_CH1, OUT_STATE_CH1, 20, 3) + FIELD(DMA_OUT_STATE_CH1, OUT_DSCR_STATE_CH1, 18, 2) + FIELD(DMA_OUT_STATE_CH1, OUTLINK_DSCR_ADDR_CH1, 0, 18) + +REG32(DMA_OUT_EOF_DES_ADDR_CH1, 0x1A8) + FIELD(DMA_OUT_EOF_DES_ADDR_CH1, OUT_EOF_DES_ADDR_CH1, 0, 32) + +REG32(DMA_OUT_EOF_BFR_DES_ADDR_CH1, 0x1AC) + FIELD(DMA_OUT_EOF_BFR_DES_ADDR_CH1, OUT_EOF_BFR_DES_ADDR_CH1, 0, 32) + +REG32(DMA_OUT_DSCR_CH1, 0x1B0) + FIELD(DMA_OUT_DSCR_CH1, OUTLINK_DSCR_CH1, 0, 32) + +REG32(DMA_OUT_DSCR_BF0_CH1, 0x1B4) + FIELD(DMA_OUT_DSCR_BF0_CH1, OUTLINK_DSCR_BF0_CH1, 0, 32) + +REG32(DMA_OUT_DSCR_BF1_CH1, 0x1B8) + FIELD(DMA_OUT_DSCR_BF1_CH1, OUTLINK_DSCR_BF1_CH1, 0, 32) + +REG32(DMA_OUT_PRI_CH1, 0x1BC) + FIELD(DMA_OUT_PRI_CH1, TX_PRI_CH1, 0, 4) + +REG32(DMA_OUT_PERI_SEL_CH1, 0x1C0) + FIELD(DMA_OUT_PERI_SEL_CH1, PERI_OUT_SEL_CH1, 0, 6) + +REG32(DMA_IN_CONF0_CH2, 0x1F0) + FIELD(DMA_IN_CONF0_CH2, MEM_TRANS_EN_CH2, 4, 1) + FIELD(DMA_IN_CONF0_CH2, IN_DATA_BURST_EN_CH2, 3, 1) + FIELD(DMA_IN_CONF0_CH2, INDSCR_BURST_EN_CH2, 2, 1) + FIELD(DMA_IN_CONF0_CH2, IN_LOOP_TEST_CH2, 1, 1) + FIELD(DMA_IN_CONF0_CH2, IN_RST_CH2, 0, 1) + +REG32(DMA_IN_CONF1_CH2, 0x1F4) + FIELD(DMA_IN_CONF1_CH2, IN_CHECK_OWNER_CH2, 12, 1) + +REG32(DMA_INFIFO_STATUS_CH2, 0x1F8) + FIELD(DMA_INFIFO_STATUS_CH2, IN_BUF_HUNGRY_CH2, 27, 1) + FIELD(DMA_INFIFO_STATUS_CH2, IN_REMAIN_UNDER_4B_CH2, 26, 1) + FIELD(DMA_INFIFO_STATUS_CH2, IN_REMAIN_UNDER_3B_CH2, 25, 1) + FIELD(DMA_INFIFO_STATUS_CH2, IN_REMAIN_UNDER_2B_CH2, 24, 1) + FIELD(DMA_INFIFO_STATUS_CH2, IN_REMAIN_UNDER_1B_CH2, 23, 1) + FIELD(DMA_INFIFO_STATUS_CH2, INFIFO_CNT_CH2, 2, 6) + FIELD(DMA_INFIFO_STATUS_CH2, INFIFO_EMPTY_CH2, 1, 1) + FIELD(DMA_INFIFO_STATUS_CH2, INFIFO_FULL_CH2, 0, 1) + +REG32(DMA_IN_POP_CH2, 0x1FC) + FIELD(DMA_IN_POP_CH2, INFIFO_POP_CH2, 12, 1) + FIELD(DMA_IN_POP_CH2, INFIFO_RDATA_CH2, 0, 12) + +REG32(DMA_IN_LINK_CH2, 0x200) + FIELD(DMA_IN_LINK_CH2, INLINK_PARK_CH2, 24, 1) + FIELD(DMA_IN_LINK_CH2, INLINK_RESTART_CH2, 23, 1) + FIELD(DMA_IN_LINK_CH2, INLINK_START_CH2, 22, 1) + FIELD(DMA_IN_LINK_CH2, INLINK_STOP_CH2, 21, 1) + FIELD(DMA_IN_LINK_CH2, INLINK_AUTO_RET_CH2, 20, 1) + FIELD(DMA_IN_LINK_CH2, INLINK_ADDR_CH2, 0, 20) + +REG32(DMA_IN_STATE_CH2, 0x204) + FIELD(DMA_IN_STATE_CH2, IN_STATE_CH2, 20, 3) + FIELD(DMA_IN_STATE_CH2, IN_DSCR_STATE_CH2, 18, 2) + FIELD(DMA_IN_STATE_CH2, INLINK_DSCR_ADDR_CH2, 0, 18) + +REG32(DMA_IN_SUC_EOF_DES_ADDR_CH2, 0x208) + FIELD(DMA_IN_SUC_EOF_DES_ADDR_CH2, IN_SUC_EOF_DES_ADDR_CH2, 0, 32) + +REG32(DMA_IN_ERR_EOF_DES_ADDR_CH2, 0x20C) + FIELD(DMA_IN_ERR_EOF_DES_ADDR_CH2, IN_ERR_EOF_DES_ADDR_CH2, 0, 32) + +REG32(DMA_IN_DSCR_CH2, 0x210) + FIELD(DMA_IN_DSCR_CH2, INLINK_DSCR_CH2, 0, 32) + +REG32(DMA_IN_DSCR_BF0_CH2, 0x214) + FIELD(DMA_IN_DSCR_BF0_CH2, INLINK_DSCR_BF0_CH2, 0, 32) + +REG32(DMA_IN_DSCR_BF1_CH2, 0x218) + FIELD(DMA_IN_DSCR_BF1_CH2, INLINK_DSCR_BF1_CH2, 0, 32) + +REG32(DMA_IN_PRI_CH2, 0x21C) + FIELD(DMA_IN_PRI_CH2, RX_PRI_CH2, 0, 4) + +REG32(DMA_IN_PERI_SEL_CH2, 0x220) + FIELD(DMA_IN_PERI_SEL_CH2, PERI_IN_SEL_CH2, 0, 6) + +REG32(DMA_OUT_CONF0_CH2, 0x250) + FIELD(DMA_OUT_CONF0_CH2, OUT_DATA_BURST_EN_CH2, 5, 1) + FIELD(DMA_OUT_CONF0_CH2, OUTDSCR_BURST_EN_CH2, 4, 1) + FIELD(DMA_OUT_CONF0_CH2, OUT_EOF_MODE_CH2, 3, 1) + FIELD(DMA_OUT_CONF0_CH2, OUT_AUTO_WRBACK_CH2, 2, 1) + FIELD(DMA_OUT_CONF0_CH2, OUT_LOOP_TEST_CH2, 1, 1) + FIELD(DMA_OUT_CONF0_CH2, OUT_RST_CH2, 0, 1) + +REG32(DMA_OUT_CONF1_CH2, 0x254) + FIELD(DMA_OUT_CONF1_CH2, OUT_CHECK_OWNER_CH2, 12, 1) + +REG32(DMA_OUTFIFO_STATUS_CH2, 0x258) + FIELD(DMA_OUTFIFO_STATUS_CH2, OUT_REMAIN_UNDER_4B_CH2, 26, 1) + FIELD(DMA_OUTFIFO_STATUS_CH2, OUT_REMAIN_UNDER_3B_CH2, 25, 1) + FIELD(DMA_OUTFIFO_STATUS_CH2, OUT_REMAIN_UNDER_2B_CH2, 24, 1) + FIELD(DMA_OUTFIFO_STATUS_CH2, OUT_REMAIN_UNDER_1B_CH2, 23, 1) + FIELD(DMA_OUTFIFO_STATUS_CH2, OUTFIFO_CNT_CH2, 2, 6) + FIELD(DMA_OUTFIFO_STATUS_CH2, OUTFIFO_EMPTY_CH2, 1, 1) + FIELD(DMA_OUTFIFO_STATUS_CH2, OUTFIFO_FULL_CH2, 0, 1) + +REG32(DMA_OUT_PUSH_CH2, 0x25C) + FIELD(DMA_OUT_PUSH_CH2, OUTFIFO_PUSH_CH2, 9, 1) + FIELD(DMA_OUT_PUSH_CH2, OUTFIFO_WDATA_CH2, 0, 9) + +REG32(DMA_OUT_LINK_CH2, 0x260) + FIELD(DMA_OUT_LINK_CH2, OUTLINK_PARK_CH2, 23, 1) + FIELD(DMA_OUT_LINK_CH2, OUTLINK_RESTART_CH2, 22, 1) + FIELD(DMA_OUT_LINK_CH2, OUTLINK_START_CH2, 21, 1) + FIELD(DMA_OUT_LINK_CH2, OUTLINK_STOP_CH2, 20, 1) + FIELD(DMA_OUT_LINK_CH2, OUTLINK_ADDR_CH2, 0, 20) + +REG32(DMA_OUT_STATE_CH2, 0x264) + FIELD(DMA_OUT_STATE_CH2, OUT_STATE_CH2, 20, 3) + FIELD(DMA_OUT_STATE_CH2, OUT_DSCR_STATE_CH2, 18, 2) + FIELD(DMA_OUT_STATE_CH2, OUTLINK_DSCR_ADDR_CH2, 0, 18) + +REG32(DMA_OUT_EOF_DES_ADDR_CH2, 0x268) + FIELD(DMA_OUT_EOF_DES_ADDR_CH2, OUT_EOF_DES_ADDR_CH2, 0, 32) + +REG32(DMA_OUT_EOF_BFR_DES_ADDR_CH2, 0x26C) + FIELD(DMA_OUT_EOF_BFR_DES_ADDR_CH2, OUT_EOF_BFR_DES_ADDR_CH2, 0, 32) + +REG32(DMA_OUT_DSCR_CH2, 0x270) + FIELD(DMA_OUT_DSCR_CH2, OUTLINK_DSCR_CH2, 0, 32) + +REG32(DMA_OUT_DSCR_BF0_CH2, 0x274) + FIELD(DMA_OUT_DSCR_BF0_CH2, OUTLINK_DSCR_BF0_CH2, 0, 32) + +REG32(DMA_OUT_DSCR_BF1_CH2, 0x278) + FIELD(DMA_OUT_DSCR_BF1_CH2, OUTLINK_DSCR_BF1_CH2, 0, 32) + +REG32(DMA_OUT_PRI_CH2, 0x27C) + FIELD(DMA_OUT_PRI_CH2, TX_PRI_CH2, 0, 4) + +REG32(DMA_OUT_PERI_SEL_CH2, 0x280) + FIELD(DMA_OUT_PERI_SEL_CH2, PERI_OUT_SEL_CH2, 0, 6) From 9b36b5d2a7fd2bcfe9be312472ba1a671b50ab34 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Tue, 27 Jun 2023 14:02:27 +0800 Subject: [PATCH 50/56] hw/dma: implement GDMA Peripheral-to-Memory interface for ESP32-C3 Implement a first interface for Peripheral-to-Memory and Memory-to-Peripheral transfers. --- hw/dma/esp32c3_gdma.c | 324 +++++++++++++++++++++++++++++----- include/hw/dma/esp32c3_gdma.h | 10 +- 2 files changed, 286 insertions(+), 48 deletions(-) diff --git a/hw/dma/esp32c3_gdma.c b/hw/dma/esp32c3_gdma.c index e6dfe215024c..98c2c6a7f9b0 100644 --- a/hw/dma/esp32c3_gdma.c +++ b/hw/dma/esp32c3_gdma.c @@ -16,34 +16,11 @@ #include "hw/dma/esp32c3_gdma.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" +#include "qemu/error-report.h" #define GDMA_WARNING 0 #define GDMA_DEBUG 0 -/** - * Check the header file for more info about this function - */ -int esp32c3_gdma_get_channel_periph(ESP32C3GdmaState *s, GdmaPeripheral periph, int dir) -{ - /* If the state, the peripheral or the direction is invalid, return directly */ - if (s == NULL || - periph > GDMA_LAST || periph == GDMA_RSVD1 || periph == GDMA_RSVD4 || periph == GDMA_RSVD5 || - dir < 0 || dir >= ESP32C3_GDMA_CONF_COUNT) - { - return -1; - } - - /* Check all the channels of the GDMA */ - for (int i = 0; i < ESP32C3_GDMA_CHANNEL_COUNT; i++) { - /* IN/OUT PERI registers have the same organization, can use any macro */ - if (FIELD_EX32(s->ch_conf[i][dir].peripheral, DMA_IN_PERI_SEL_CH0, PERI_IN_SEL_CH0) == periph) { - return i; - } - } - - return -1; -} - /** * @brief Structure defining how linked lists are represented in hardware for the GDMA module @@ -80,9 +57,6 @@ static uint64_t esp32c3_gdma_read(void *opaque, hwaddr addr, unsigned int size) ESP32C3GdmaState *s = ESP32C3_GDMA(opaque); uint64_t r = 0; -#if GDMA_DEBUG - info_report("[GDMA] Reading from %08lx (%08lx)\n", addr, r); -#endif switch(addr) { case A_DMA_INT_RAW_CH0 ... A_DMA_INT_CLR_CH2: @@ -119,11 +93,15 @@ static uint64_t esp32c3_gdma_read(void *opaque, hwaddr addr, unsigned int size) default: #if GDMA_WARNING - warn_report("[GDMA] Unsupported read to %08lx\n", addr); + warn_report("[GDMA] Unsupported read to %08lx", addr); #endif break; } +#if GDMA_DEBUG + info_report("[GDMA] Reading from %08lx (%08lx)", addr, r); +#endif + return r; } @@ -214,28 +192,13 @@ static void esp32c3_gdma_write_int_state(ESP32C3GdmaState *s, uint32_t chan, uin static void esp32c3_gdma_reset_fifo(ESP32C3GdmaState *s, uint32_t chan, uint32_t in_out) { #if GDMA_DEBUG - info_report("Resetting FIFO for chan %d, direction: %d\n", chan, in_out); + info_report("Resetting FIFO for chan %d, direction: %d", chan, in_out); #endif /* Set the FIFO empty bit to 1, full bit to 0, and number of bytes of data to 0 */ s->ch_conf[chan][in_out].status = R_DMA_INFIFO_STATUS_CH0_INFIFO_EMPTY_CH0_MASK; } -/** - * @brief Check that the given 32-bit address is in a given range - * - * @param range_start Start address of range - * @param range_size Size of the SoC DRAM - * @param addr Linked-list node address - * - * @returns true if the node is valid (in DRAM), false else - */ -static inline bool esp32c3_gdma_addr_in_range(uint32_t range_start, uint32_t range_size, uint32_t addr) -{ - return range_start <= addr && addr < (range_start + range_size); -} - - /** * @brief Read a descriptor from the guest machine * @@ -357,6 +320,275 @@ static void esp32c3_gdma_get_restart_buffer(ESP32C3GdmaState *s, uint32_t chan, } +/** + * Check the header file for more info about this function + */ +bool esp32c3_gdma_get_channel_periph(ESP32C3GdmaState *s, GdmaPeripheral periph, int dir, uint32_t* chan) +{ + /* If the state, the peripheral or the direction is invalid, return directly */ + if (s == NULL || chan == NULL || + periph > GDMA_LAST || periph == GDMA_RSVD1 || periph == GDMA_RSVD4 || periph == GDMA_RSVD5 || + dir < 0 || dir >= ESP32C3_GDMA_CONF_COUNT) + { + return false; + } + + /* Check all the channels of the GDMA */ + for (int i = 0; i < ESP32C3_GDMA_CHANNEL_COUNT; i++) { + /* IN/OUT PERI registers have the same organization, can use any macro. + * Look for the channel that was configured with the given peripheral. It must be marked as "started" too */ + if ( FIELD_EX32(s->ch_conf[i][dir].peripheral, DMA_IN_PERI_SEL_CH0, PERI_IN_SEL_CH0) == periph || + FIELD_EX32(s->ch_conf[i][dir].link, DMA_OUT_LINK_CH0, OUTLINK_START_CH0)) { + + *chan = i; + return true; + } + } + + return false; +} + + +/** + * @brief Read data from guest RAM pointed by the linked list configured in the given DmaConfigState index. + * `size` bytes will be read and stored in `buffer`. + */ +bool esp32c3_gdma_read_channel(ESP32C3GdmaState *s, uint32_t chan, uint8_t* buffer, uint32_t size) +{ + DmaConfigState* state = &s->ch_conf[chan][ESP32C3_GDMA_OUT_IDX]; + + state->link &= R_DMA_OUT_LINK_CH0_OUTLINK_ADDR_CH0_MASK; + + /* Same goes for the status */ + esp32c3_gdma_clear_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DONE_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_OUT_EOF_CH0_INT_RAW_MASK); + + /* Get the guest DRAM address */ + uint32_t out_addr = ((ESP32C3_GDMA_RAM_ADDR >> 20) << 20) | FIELD_EX32(state->link, DMA_OUT_LINK_CH0, OUTLINK_ADDR_CH0); + + /* Boolean to mark whether we need to check the owner for in and out buffers */ + const bool owner_check_out = FIELD_EX32(state[ESP32C3_GDMA_OUT_IDX].conf1, DMA_OUT_CONF1_CH0, OUT_CHECK_OWNER_CH0); + + /* Boolean to mark whether the transmit (out) buffers must have their owner bit cleared here */ + const bool clear_out = FIELD_EX32(state[ESP32C3_GDMA_OUT_IDX].conf0, DMA_OUT_CONF0_CH0, OUT_AUTO_WRBACK_CH0); + + /* Pointer to the lists that will be browsed by the loop below */ + GdmaLinkedList out_list; + + /* Boolean to mark whether a descriptor error occurred during the transfer */ + bool valid = true; + + /* Set the current buffer (guest address) in the `desc_addr` register */ + valid = esp32c3_gdma_read_descr(s, out_addr, &out_list); + esp32c3_gdma_push_descriptor(s, chan, ESP32C3_GDMA_OUT_IDX, out_addr); + + /* Check that the address is valid. If the owner must be checked, make sure owner is the DMA controller. + * On the real hardware, both in and out are checked at the same time, so in case of an error, both bits + * are set. Replicate the same behavior here. */ + if ( !valid || (owner_check_out && !out_list.config.owner) ) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DSCR_ERR_CH0_INT_RAW_MASK); + return false; + } + + /* Store the current number of bytes written to `buffer` parameter */ + uint32_t consumed = 0; + bool exit_loop = false; + bool error = false; + + while (!exit_loop && !error) { + /* Calculate the number of bytes to read from the OUT channel */ + const uint32_t remaining = size - consumed; + const uint32_t min = MIN(out_list.config.length, remaining); + + valid = esp32c3_gdma_read_guest(s, out_list.buf_addr, buffer + consumed, min); + if (!valid) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + break; + } + consumed += min; + + if (consumed == size) { + exit_loop = true; + } + + /* If we reached the end of the TX descriptor, we can jump to the next buffer */ + if (min == out_list.config.length) { + + /* Before jumping to the next node, clear the owner bit if needed */ + if (clear_out) { + out_list.config.owner = 0; + + /* Write back the modified descriptor, should always be valid */ + valid = esp32c3_gdma_read_descr(s, out_addr, &out_list); + assert(valid); + } + + const bool eof_bit = out_list.config.suc_eof; + + /* Retrieve the next node while updating the virtual guest address */ + out_addr = out_list.next_addr; + valid = esp32c3_gdma_next_list_node(s, chan, ESP32C3_GDMA_OUT_IDX, &out_list); + + /* Only check the valid flag and the owner if we don't have to exit the loop*/ + if ( !exit_loop && (!valid || (owner_check_out && !out_list.config.owner)) ) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } + + /* If the EOF bit was set, the real controller doesn't stop the transfer, it simply + * sets the status accordingly (and generates an interrupt if enabled) */ + if (eof_bit) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_EOF_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_OUT_TOTAL_EOF_CH0_INT_RAW_MASK); + } + } + } + + /* Check if all the bytes were sent successfully */ + if (exit_loop && consumed != size) { + /* TODO: which error should be triggered ?*/ + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } + + if (!error) { + /* Set the transfer as completed. EOF should have already been triggered within the loop */ + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_OUT_DONE_CH0_INT_RAW_MASK); + } + + return !error; +} + + +/** + * @brief Write data to the guest RAM pointed by the linked list configured in the given DmaConfigState index. + * `size` bytes from `buffer` will be written to guest machine's RAM. + */ +bool esp32c3_gdma_write_channel(ESP32C3GdmaState *s, uint32_t chan, uint8_t* buffer, uint32_t size) +{ + DmaConfigState* state = &s->ch_conf[chan][ESP32C3_GDMA_IN_IDX]; + + /* Clear the (RE)START fields, i.e., only keep the link address */ + state->link &= R_DMA_OUT_LINK_CH0_OUTLINK_ADDR_CH0_MASK; + + /* Same goes for the status */ + esp32c3_gdma_clear_status(s, chan, R_DMA_INT_RAW_CH0_IN_DONE_CH0_INT_RAW_MASK | + R_DMA_INT_RAW_CH0_IN_SUC_EOF_CH0_INT_RAW_MASK); + + /* Get highest 12 bits of the DRAM address */ + uint32_t in_addr = ((ESP32C3_GDMA_RAM_ADDR >> 20) << 20) | FIELD_EX32(state->link, DMA_IN_LINK_CH0, INLINK_ADDR_CH0); + + /* Boolean to mark whether we need to check the owner for in buffers */ + const bool owner_check_in = FIELD_EX32(state->conf1, DMA_IN_CONF1_CH0, IN_CHECK_OWNER_CH0); + + /* Pointer to the lists that will be browsed by the loop below */ + GdmaLinkedList in_list = { 0 }; + /* Boolean to mark whether a descriptor error occurred during the transfer */ + bool valid = true; + + valid = esp32c3_gdma_read_descr(s, in_addr, &in_list); + esp32c3_gdma_push_descriptor(s, chan, ESP32C3_GDMA_IN_IDX, in_addr); + + if ( !valid || (owner_check_in && !in_list.config.owner) ) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DSCR_ERR_CH0_INT_RAW_MASK); + return false; + } + + /* Clear the number of bytes written to the "in" buffer and the owner */ + in_list.config.length = 0; + + uint32_t consumed = 0; + bool exit_loop = false; + bool error = false; + + while (!exit_loop && !error) { + + /* Calculate the number of bytes to write to the in channel */ + const uint32_t remaining = size - consumed; + const uint32_t min = MIN(in_list.config.size, remaining); + + /* Perform the actual copy, the in buffer address will always be at the beginning because the data + * to write to it are contiguous (`buffer` parameter) */ + valid = esp32c3_gdma_write_guest(s, in_list.buf_addr, buffer + consumed, min); + if (!valid) { + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } + + /* Update the number of bytes written to the "in" buffer */ + in_list.config.length += min; + consumed += min; + + if (size == consumed) { + exit_loop = true; + } + + /* If we reached the end of the "node", go to the next one */ + if (in_list.config.size == in_list.config.length) { + /* Clear the owner bit, set the length to the maximum bytes readable */ + in_list.config.owner = 0; + + /* During peripheral-to-memory transfers, the eof bit is only used to set a status bit, and generate + * an interrupt if enabled. If we still have bytes to send, we won't stop the transfer. + * In all cases, reset this bit as it must be only set at the end of the buffer. */ + if (in_list.config.suc_eof) { + in_list.config.suc_eof = 0; + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_SUC_EOF_CH0_INT_RAW_MASK); + } + + /* Write back the IN node to guest RAM */ + valid = esp32c3_gdma_write_descr(s, in_addr, &in_list); + assert(valid); + + /* Get the next virtual address before replacing the current list node content */ + const uint32_t next_addr = in_list.next_addr; + + /* Even if we have to exit the loop, we still have to push the next address to the descriptors stack */ + if (exit_loop) { + esp32c3_gdma_push_descriptor(s, chan, ESP32C3_GDMA_IN_IDX, next_addr); + break; + } + + /* In the case where the transfer is finished, we should still fetch the next node, + * but we should not override the current in_list variable as it is used outside the loop + * to reset the owner and update the suc_eof flag */ + valid = esp32c3_gdma_next_list_node(s, chan, ESP32C3_GDMA_IN_IDX, &in_list); + + if (!valid || (owner_check_in && !in_list.config.owner)) { + /* Check the validity of the next node if we have to continue the loop (transfer finished) */ + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DSCR_ERR_CH0_INT_RAW_MASK); + error = true; + } else { + /* Continue the loop normally, next RX descriptor set to current */ + in_list.config.length = 0; + + /* Update the current in guest address */ + in_addr = next_addr; + } + } + } + + if (!error) { + /* In all cases (error or not), let's set the End-of-list in the receiver */ + in_list.config.suc_eof = 1; + in_list.config.owner = 0; + + valid = esp32c3_gdma_write_descr(s, in_addr, &in_list); + assert(valid); + + /* And store the EOF RX descriptor GUEST address in the correct register. + * This can be used in the ISR to know which buffer has just been processed. */ + state->suc_eof_desc_addr = in_addr; + + /* Set the transfer as completed for both the IN and OUT link */ + esp32c3_gdma_set_status(s, chan, R_DMA_INT_RAW_CH0_IN_DONE_CH0_INT_RAW_MASK); + } + + return !error; +} + + /** * @brief Check if a memory-to-memory transfer can be started and start it if possible * @@ -673,7 +905,7 @@ static void esp32c3_gdma_write(void *opaque, hwaddr addr, ESP32C3GdmaState *s = ESP32C3_GDMA(opaque); #if GDMA_DEBUG - info_report("[GDMA] Writing to %08lx (%08lx)\n", addr, value); + info_report("[GDMA] Writing to %08lx (%08lx)", addr, value); #endif switch(addr) { @@ -714,7 +946,7 @@ static void esp32c3_gdma_write(void *opaque, hwaddr addr, default: #if GDMA_WARNING - warn_report("[GDMA] Unsupported write to %08lx (%08lx)\n", addr, value); + warn_report("[GDMA] Unsupported write to %08lx (%08lx)", addr, value); #endif break; } diff --git a/include/hw/dma/esp32c3_gdma.h b/include/hw/dma/esp32c3_gdma.h index c3e81cf1294b..c3191f489d3f 100644 --- a/include/hw/dma/esp32c3_gdma.h +++ b/include/hw/dma/esp32c3_gdma.h @@ -102,12 +102,18 @@ typedef struct ESP32C3GdmaState { * * @param s GDMA state * @param periph Peripheral to search - * @param dir Direction: ESP32C3_GDMA_IN_IDX or ESP32C3_GDMA_OUT_IDX + * @param dir Direction from the GDMA point of view: ESP32C3_GDMA_IN_IDX or ESP32C3_GDMA_OUT_IDX. + * For example, to find a channel that needs to be written to, use ESP32C3_GDMA_IN_IDX + * (because GDMA receives the data) + * @param chan Returned channel index linked to the peripheral * * @returns index of the GDMA channel bound to the peripheral, -1 if not found */ -int esp32c3_gdma_get_channel_periph(ESP32C3GdmaState *s, GdmaPeripheral periph, int dir); +bool esp32c3_gdma_get_channel_periph(ESP32C3GdmaState *s, GdmaPeripheral periph, int dir, + uint32_t* chan); +bool esp32c3_gdma_read_channel(ESP32C3GdmaState *s, uint32_t chan, uint8_t* buffer, uint32_t size); +bool esp32c3_gdma_write_channel(ESP32C3GdmaState *s, uint32_t chan, uint8_t* buffer, uint32_t size); REG32(DMA_INT_RAW_CH0, 0x000) FIELD(DMA_INT_RAW_CH0, OUTFIFO_UDF_CH0_INT_RAW, 12, 1) From a00a687710957cfaa87af33ca9846a4857a04cf6 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Thu, 15 Jun 2023 14:54:22 +0800 Subject: [PATCH 51/56] hw/misc: implement AES-DMA working mode for ESP32-C3 --- hw/misc/esp32c3_aes.c | 249 +++++++++++++++++++++++++++++++--- hw/misc/meson.build | 6 +- hw/riscv/esp32c3.c | 17 ++- include/hw/misc/esp32c3_aes.h | 20 ++- 4 files changed, 265 insertions(+), 27 deletions(-) diff --git a/hw/misc/esp32c3_aes.c b/hw/misc/esp32c3_aes.c index 26cd50cce3ed..90a1b7f1ebe6 100644 --- a/hw/misc/esp32c3_aes.c +++ b/hw/misc/esp32c3_aes.c @@ -10,8 +10,11 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" #include "hw/misc/esp32c3_aes.h" -#include "crypto/aes.h" #include "qemu/error-report.h" +#include +#include +#include "hw/irq.h" +#include "crypto/aes.h" #define AES_WARNING 0 #define AES_DEBUG 0 @@ -19,21 +22,197 @@ static void esp32c3_aes_dma_exit(ESP32C3AesState *s) { - /* DMA is not supported yet */ - (void) s; + s->state_reg = ESP32C3_AES_IDLE; } +static void* esp32c3_aes_get_buffer(uint32_t size) +{ + /* Instead of reallocating a buffer every time, keep a watermark and a single buffer */ + static void* buffer = NULL; + static uint32_t buf_size = 0; -static void esp32c3_aes_start(ESP32C3AesState *s) + if (buf_size < size) { + buffer = g_realloc(buffer, size); + buf_size = size; + } + + return buffer; +} + + +/** + * @brief Interpret data in IV memory as a counter and add a block count to its value. + * Used in CTR block mode. + */ +static void esp32c3_aes_ctr_add_counter(ESP32C3AesState *s, uint32_t blocks) { - AES_KEY aes_key; + /* Check the length of this counter in bits. In both cases, it is stored in BIG-ENDIAN */ + if (FIELD_EX32(s->inc_sel_reg, AES_INC_SEL_REG, AES_INC_SEL) == 1) { + /* 128-bit mode, no native 128 integer type, use two 64-bit types */ + uint64_t* low_ptr = (uint64_t*) (s->iv_mem + sizeof(uint64_t)); + uint64_t* high_ptr = (uint64_t*) s->iv_mem; + const uint64_t original = be64toh(*low_ptr); + uint64_t value = original + blocks; + *low_ptr = htobe64(value); + /* If the value overflowed, we have to update the upper part too */ + if (original > value) { + value = be64toh(*high_ptr) + 1; + *high_ptr = htobe64(value); + } + } else { + /* 32-bit mode */ + uint32_t* counter_ptr = (uint32_t*) &s->iv_mem[ESP32C3_AES_IV_REG_CNT - sizeof(uint32_t)]; + const uint32_t value = be32toh(*counter_ptr) + blocks; + *counter_ptr = htobe32(value); + } +} + - /* DMA mode is not supported yet! */ - if (FIELD_EX32(s->dma_enable_reg , AES_DMA_ENA_REG, AES_DMA_ENA) != 0) { - error_report("[AES] DMA-AES is not supported yet\n"); +static void esp32c3_aes_dma_start(ESP32C3AesState *s) +{ + gcry_cipher_hd_t ghandle; + uint32_t gdma_out_idx; + uint32_t gdma_in_idx; + + const enum gcry_cipher_modes cipher_map[ESP32C3_AES_CIPHER_COUNT] = { + [ESP32C3_AES_ECB_CIPHER] = GCRY_CIPHER_MODE_ECB, + [ESP32C3_AES_CBC_CIPHER] = GCRY_CIPHER_MODE_CBC, + [ESP32C3_AES_OFB_CIPHER] = GCRY_CIPHER_MODE_OFB, + [ESP32C3_AES_CTR_CIPHER] = GCRY_CIPHER_MODE_CTR, + [ESP32C3_AES_CFB8_CIPHER] = GCRY_CIPHER_MODE_CFB8, + [ESP32C3_AES_CFB128_CIPHER] = GCRY_CIPHER_MODE_CFB, + }; + + /* Get the block Cipher mode */ + const uint32_t cipher_mode = FIELD_EX32(s->block_mode_reg , AES_BLK_MODE_REG, AES_BLOCK_MODE); + + /* Check whether we have to encrypt or decrypt */ + const uint32_t mode = FIELD_EX32(s->mode_reg , AES_MODE_REG, AES_MODE); + const bool encrypt = (mode == ESP32C3_AES_MODE_128_ENC) || (mode == ESP32C3_AES_MODE_256_ENC); + const bool decrypt = (mode == ESP32C3_AES_MODE_128_DEC) || (mode == ESP32C3_AES_MODE_256_DEC); + + /* Get the length, in bits of the key */ + const int length = (mode == ESP32C3_AES_MODE_128_ENC || mode == ESP32C3_AES_MODE_128_DEC) ? 128 : 256; + const int algo = length == 128 ? GCRY_CIPHER_AES128 : GCRY_CIPHER_AES256; + + if (cipher_mode >= ESP32C3_AES_CIPHER_COUNT) { + error_report("[AES] Invalid or unsupported Cipher block mode!"); return; + } else if (!decrypt && !encrypt) { + error_report("[AES] Invalid mode!"); + return; + } + + gcry_error_t err = gcry_cipher_open(&ghandle, algo, cipher_map[cipher_mode], 0); + if (err) { + error_report("[AES] error 0x%x when opening cipher", err); + return; + } + + /* Cast the keys and data to byte array. + * This can only work as-is if the host computer is has a little-endian CPU. */ + const uint8_t* key = (uint8_t*) &s->key; + uint8_t* iv_mem = (uint8_t*) &s->iv_mem; + + /* Set the algorithm key */ + err = gcry_cipher_setkey(ghandle, key, length / 8); + if (err) { + error_report("[AES] error 0x%x setting key", err); + goto close_exit; + } + + /* `iv_mem` field represents the Initialization Vector for CBC/OFB/CFB operations + * But it represents the Initial Counter Block for CTR operation. + * It shall be ignored for ECB block operation. */ + if (cipher_mode == ESP32C3_AES_CTR_CIPHER) { + err = gcry_cipher_setctr(ghandle, iv_mem, ESP32C3_AES_IV_REG_CNT); + } else if (cipher_mode != ESP32C3_AES_ECB_CIPHER) { + err = gcry_cipher_setiv(ghandle, iv_mem, ESP32C3_AES_IV_REG_CNT); + } + + if (err) { + error_report("[AES] error 0x%x setting IV memory", err); + goto close_exit; + } + + /* Get the GDMA input channel index for AES peripheral */ + assert(s->gdma != NULL); + + if ( !esp32c3_gdma_get_channel_periph(s->gdma, GDMA_AES, ESP32C3_GDMA_OUT_IDX, &gdma_out_idx) || + !esp32c3_gdma_get_channel_periph(s->gdma, GDMA_AES, ESP32C3_GDMA_IN_IDX, &gdma_in_idx) ) { + warn_report("[AES] GDMA requested but no properly configured channel found"); + goto close_exit; + } + + /* Block number represents the number of 128-bit (16-byte) blocks to encrypt. + * If block_num_reg is 100, we have to encrypt 100*128/8 = 1600 bytes */ + uint32_t buf_size = s->block_num_reg * 16; + uint8_t* buffer = esp32c3_aes_get_buffer(buf_size); + + if ( !esp32c3_gdma_read_channel(s->gdma, gdma_out_idx, buffer, buf_size) ) { + warn_report("[AES] Error reading from GDMA buffer"); + goto close_exit; } + /* Reading was successful, process the buffer (encrypt/decrypt) and write back to the GDMA OUT buffer */ + if (encrypt) { + err = gcry_cipher_encrypt(ghandle, buffer, buf_size, NULL, 0); + + if (cipher_mode != ESP32C3_AES_CTR_CIPHER) { + /* On the real hardware, IV memory is used in-place for encrypting data, so copy the last encrypted block to IV memory */ + memcpy(iv_mem, buffer + buf_size - 16, ESP32C3_AES_IV_REG_CNT); + } + } else { + /* Store the last block of plaintext, needed for OFB */ + const uint8_t* buffer_last_block = buffer + buf_size - ESP32C3_AES_IV_REG_CNT; + uint8_t plaintext[ESP32C3_AES_IV_REG_CNT]; + memcpy(plaintext, buffer_last_block, ESP32C3_AES_IV_REG_CNT); + + /* The IV memory is initalized with the encrypted data, so do the copy now */ + if (cipher_mode != ESP32C3_AES_OFB_CIPHER && cipher_mode != ESP32C3_AES_CTR_CIPHER) { + memcpy(iv_mem, buffer + buf_size - 16, ESP32C3_AES_IV_REG_CNT); + } + + err = gcry_cipher_decrypt(ghandle, buffer, buf_size, NULL, 0); + + /* For OFB, it is done after the decryption. Moreover, the hardware XOR the original plaintext with the output + * and stores the result in IV memory. */ + if (cipher_mode == ESP32C3_AES_OFB_CIPHER) { + for (int i = 0; i < ESP32C3_AES_IV_REG_CNT; i++) { + iv_mem[i] = buffer_last_block[i] ^ plaintext[i]; + } + } + } + + if (cipher_mode == ESP32C3_AES_CTR_CIPHER) { + esp32c3_aes_ctr_add_counter(s, s->block_num_reg); + } + + if (err) { + error_report("[AES] error processing memory"); + goto close_exit; + } + + if ( !esp32c3_gdma_write_channel(s->gdma, gdma_in_idx, buffer, buf_size) ) { + warn_report("[AES] Error writing to GDMA buffer"); + goto close_exit; + } + + s->state_reg = ESP32C3_AES_DONE; + + if (s->int_ena_reg) { + qemu_irq_raise(s->irq); + } + +close_exit: + gcry_cipher_close(ghandle); +} + + +static void esp32c3_aes_start(ESP32C3AesState *s) +{ + AES_KEY aes_key; + /* Check whether we have to encrypt or decrypt */ const uint32_t mode = FIELD_EX32(s->mode_reg , AES_MODE_REG, AES_MODE); const bool encrypt = (mode == ESP32C3_AES_MODE_128_ENC) || (mode == ESP32C3_AES_MODE_256_ENC); @@ -68,6 +247,10 @@ static uint64_t esp32c3_aes_read(void *opaque, hwaddr addr, unsigned int size) ESP32C3AesState *s = ESP32C3_AES(opaque); uint64_t r = 0; + /* At the moment, make the assumption that we always write a 32-bit word, except for IV memory */ + assert((addr >= A_AES_IV_MEM_0_REG && addr <= A_AES_IV_MEM_15_REG) || + size == sizeof(uint32_t)); + switch (addr) { case A_AES_KEY_0_REG ... A_AES_KEY_7_REG: r = s->key[(addr - A_AES_KEY_0_REG) / sizeof(uint32_t)]; @@ -82,7 +265,13 @@ static uint64_t esp32c3_aes_read(void *opaque, hwaddr addr, unsigned int size) break; case A_AES_IV_MEM_0_REG ... A_AES_IV_MEM_15_REG: - r = s->iv_mem[(addr - A_AES_IV_MEM_0_REG) / sizeof(uint32_t)]; + /* Use r as the offset */ + r = addr - A_AES_IV_MEM_0_REG; + if (size == sizeof(uint32_t)) { + r = *((uint32_t*) (s->iv_mem + r)); + } else if (size == sizeof(uint8_t)) { + r = s->iv_mem[r]; + } break; case A_AES_STATE_REG: @@ -116,13 +305,13 @@ static uint64_t esp32c3_aes_read(void *opaque, hwaddr addr, unsigned int size) default: #if AES_WARNING /* Other registers are not supported yet */ - warn_report("[AES] Unsupported read to %08lx\n", addr); + warn_report("[AES] Unsupported read to %08lx", addr); #endif break; } #if AES_DEBUG - info_report("[AES] Reading from %08lx (%08lx)\n", addr, r); + info_report("[AES] Reading from %08lx (%08lx)", addr, r); #endif @@ -134,6 +323,11 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) { ESP32C3AesState *s = ESP32C3_AES(opaque); + uint32_t offset = 0; + + /* At the moment, make the assumption that we always write a 32-bit word, except for IV memory */ + assert((addr >= A_AES_IV_MEM_0_REG && addr <= A_AES_IV_MEM_15_REG) || + size == sizeof(uint32_t)); switch (addr) { case A_AES_KEY_0_REG ... A_AES_KEY_7_REG: @@ -145,7 +339,12 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr, break; case A_AES_IV_MEM_0_REG ... A_AES_IV_MEM_15_REG: - s->iv_mem[(addr - A_AES_IV_MEM_0_REG) / sizeof(uint32_t)] = value; + offset = addr - A_AES_IV_MEM_0_REG; + if (size == sizeof(uint32_t)) { + *((uint32_t*) (s->iv_mem + offset)) = value; + } else if (size == sizeof(uint8_t)) { + s->iv_mem[offset] = value & 0xff; + } break; case A_AES_MODE_REG: @@ -154,7 +353,12 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr, case A_AES_TRIGGER_REG: if (FIELD_EX32(value, AES_TRIGGER_REG, AES_TRIGGER)) { - esp32c3_aes_start(s); + /* DMA mode is different than "regular" mode */ + if (FIELD_EX32(s->dma_enable_reg , AES_DMA_ENA_REG, AES_DMA_ENA) != 0) { + esp32c3_aes_dma_start(s); + } else { + esp32c3_aes_start(s); + } } break; @@ -176,7 +380,7 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr, case A_AES_INT_CLR_REG: if (FIELD_EX32(value, AES_INT_CLR_REG, AES_INT_CLR)) { - s->int_st = 0; + qemu_irq_lower(s->irq); } break; @@ -191,13 +395,13 @@ static void esp32c3_aes_write(void *opaque, hwaddr addr, default: #if AES_WARNING /* Other registers are not supported yet */ - warn_report("[AES] Unsupported write to %08lx (%08lx)\n", addr, value); + warn_report("[AES] Unsupported write to %08lx (%08lx)", addr, value); #endif break; } #if AES_DEBUG - info_report("[AES] Writing to %08lx (%08lx)\n", addr, value); + info_report("[AES] Writing to %08lx (%08lx)", addr, value); #endif } @@ -224,6 +428,16 @@ static void esp32c3_aes_reset(DeviceState *dev) s->int_ena_reg = 0; } +static void esp32c3_aes_realize(DeviceState *dev, Error **errp) +{ + ESP32C3AesState *s = ESP32C3_AES(dev); + + /* Make sure GDMA was set of issue an error */ + if (s->gdma == NULL) { + error_report("[AES] GDMA controller must be set!"); + } +} + static void esp32c3_aes_init(Object *obj) { ESP32C3AesState *s = ESP32C3_AES(obj); @@ -232,12 +446,15 @@ static void esp32c3_aes_init(Object *obj) memory_region_init_io(&s->iomem, obj, &esp32c3_aes_ops, s, TYPE_ESP32C3_AES, ESP32C3_AES_REGS_SIZE); sysbus_init_mmio(sbd, &s->iomem); + + sysbus_init_irq(sbd, &s->irq); } static void esp32_aes_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + dc->realize = esp32c3_aes_realize; dc->reset = esp32c3_aes_reset; } diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 78f2c968e394..9a34c6e96e94 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -140,14 +140,16 @@ softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files( 'esp32c3_cache.c', 'esp32c3_sha.c', 'esp32c3_jtag.c', - 'esp32c3_rtc_cntl.c', - 'esp32c3_aes.c' + 'esp32c3_rtc_cntl.c' )) if gcrypt.found() softmmu_ss.add(when: [gcrypt, 'CONFIG_XTENSA_ESP32'], if_true: files( 'esp32_rsa.c', )) + softmmu_ss.add(when: [gcrypt, 'CONFIG_RISCV_ESP32C3'], if_true: files( + 'esp32c3_aes.c', + )) endif softmmu_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_ahb_apb_pnp.c')) diff --git a/hw/riscv/esp32c3.c b/hw/riscv/esp32c3.c index bea0f720ec20..caa426d5b13d 100644 --- a/hw/riscv/esp32c3.c +++ b/hw/riscv/esp32c3.c @@ -426,13 +426,6 @@ static void esp32c3_machine_init(MachineState *machine) memory_region_add_subregion_overlap(sys_mem, DR_REG_SHA_BASE, mr, 0); } - /* AES realization */ - { - qdev_realize(DEVICE(&ms->aes), &ms->periph_bus, &error_fatal); - MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->aes), 0); - memory_region_add_subregion_overlap(sys_mem, DR_REG_AES_BASE, mr, 0); - } - /* Timer Groups realization */ { qdev_realize(DEVICE(&ms->timg[0]), &ms->periph_bus, &error_fatal); @@ -487,6 +480,16 @@ static void esp32c3_machine_init(MachineState *machine) } + /* AES realization */ + { + ms->aes.gdma = &ms->gdma; + qdev_realize(DEVICE(&ms->aes), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->aes), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_AES_BASE, mr, 0); + sysbus_connect_irq(SYS_BUS_DEVICE(&ms->aes), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_AES_INTR_SOURCE)); + } + /* Open and load the "bios", which is the ROM binary, also named "first stage bootloader" */ char *rom_binary = qemu_find_file(QEMU_FILE_TYPE_BIOS, "esp32c3-rom.bin"); if (rom_binary == NULL) { diff --git a/include/hw/misc/esp32c3_aes.h b/include/hw/misc/esp32c3_aes.h index 2a168e05007e..6469866ea9e1 100644 --- a/include/hw/misc/esp32c3_aes.h +++ b/include/hw/misc/esp32c3_aes.h @@ -12,6 +12,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/registerfields.h" +#include "hw/dma/esp32c3_gdma.h" #define TYPE_ESP32C3_AES "misc.esp32c3.aes" #define ESP32C3_AES(obj) OBJECT_CHECK(ESP32C3AesState, (obj), TYPE_ESP32C3_AES) @@ -35,6 +36,18 @@ #define ESP32C3_AES_MODE_256_DEC 6 +/** + * Block Cipher modes + */ +#define ESP32C3_AES_ECB_CIPHER 0 +#define ESP32C3_AES_CBC_CIPHER 1 +#define ESP32C3_AES_OFB_CIPHER 2 +#define ESP32C3_AES_CTR_CIPHER 3 +#define ESP32C3_AES_CFB8_CIPHER 4 +#define ESP32C3_AES_CFB128_CIPHER 5 +#define ESP32C3_AES_CIPHER_COUNT 6 + + typedef struct ESP32C3AesState { SysBusDevice parent_object; MemoryRegion iomem; @@ -42,7 +55,7 @@ typedef struct ESP32C3AesState { uint32_t key[ESP32C3_AES_KEY_REG_CNT]; uint32_t text_in[ESP32C3_AES_TEXT_REG_CNT]; uint32_t text_out[ESP32C3_AES_TEXT_REG_CNT]; - uint32_t iv_mem[ESP32C3_AES_IV_REG_CNT]; + uint8_t iv_mem[ESP32C3_AES_IV_REG_CNT]; uint32_t mode_reg; uint32_t state_reg; @@ -51,8 +64,11 @@ typedef struct ESP32C3AesState { uint32_t block_num_reg; uint32_t inc_sel_reg; - uint32_t int_st; uint32_t int_ena_reg; + qemu_irq irq; + + /* Public: must be set by the machine before realizing current instance */ + ESP32C3GdmaState *gdma; } ESP32C3AesState; From 6a8b06c53ce8144486d4b6e7771769a5e8b12d96 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Mon, 19 Jun 2023 17:57:25 +0800 Subject: [PATCH 52/56] hw/misc: implement DMA mode in SHA controller for ESP32-C3 --- hw/misc/esp32c3_sha.c | 173 ++++++++++++++++++++++++++++--- hw/riscv/esp32c3.c | 17 +-- include/hw/misc/esp32c3_sha.h | 14 ++- include/hw/nvram/esp32c3_efuse.h | 2 +- 4 files changed, 182 insertions(+), 24 deletions(-) diff --git a/hw/misc/esp32c3_sha.c b/hw/misc/esp32c3_sha.c index 12864f000718..f332694ac5f4 100644 --- a/hw/misc/esp32c3_sha.c +++ b/hw/misc/esp32c3_sha.c @@ -16,9 +16,20 @@ #include "hw/sysbus.h" #include "hw/registerfields.h" #include "hw/misc/esp32c3_sha.h" - +#include "hw/irq.h" #define SHA_WARNING 0 +#define SHA_DEBUG 0 + +#define SHA_OP_TYPE_MASK (1 << 0) +#define SHA_OP_DMA_MASK (1 << 1) + +typedef enum { + OP_START = 0, + OP_CONTINUE = 1, + OP_DMA_START = SHA_OP_DMA_MASK | OP_START, + OP_DMA_CONTINUE = SHA_OP_DMA_MASK | OP_CONTINUE, +} ESP32C3ShaOperation; static ESP32C3HashAlg esp32c3_algs[] = { @@ -40,28 +51,83 @@ static ESP32C3HashAlg esp32c3_algs[] = { }; -static void esp32c3_resume_hash(ESP32C3ShaState *s) +static void esp32c3_sha_continue_hash(ESP32C3ShaState *s) { - /* TODO: we can imagine a scenario where the application wants to calculate the hash of a - * precalculated context, in that case, the application would fill the `hash` registers and - * call `continue` instead of using `start`. We don't support that for the moment. */ assert(s->mode <= ESP32C3_SHA_256_MODE); ESP32C3HashAlg alg = esp32c3_algs[s->mode]; + alg.compress(&s->context, (uint8_t*) s->message); + memcpy(s->hash, &s->context, alg.len); +} + + +static void esp32c3_sha_continue_dma(ESP32C3ShaState *s) +{ + assert(s->mode <= ESP32C3_SHA_256_MODE); + ESP32C3HashAlg alg = esp32c3_algs[s->mode]; + uint32_t gdma_out_idx = 0; + assert(alg.compress); - alg.compress(&s->context, (uint8_t*) s->message); + /* Number of blocks to process, each block is ESP32C3_MESSAGE_SIZE bytes big */ + const uint32_t blocks = s->block; + const uint32_t buf_size = blocks * ESP32C3_MESSAGE_SIZE; + + /* Get the GDMA channel connected to SHA module. + * Specify ESP32C3_GDMA_OUT_IDX since the data are going OUT of GDMA but IN our current component. */ + if ( !esp32c3_gdma_get_channel_periph(s->gdma, GDMA_SHA, ESP32C3_GDMA_OUT_IDX, &gdma_out_idx) ) + { + warn_report("[SHA] GDMA requested but no properly configured channel found"); + return; + } + + /* Allocate the buffer that will contain the data and get teh actual data */ + uint8_t* buffer = g_malloc(blocks * ESP32C3_MESSAGE_SIZE); + if (buffer == NULL) + { + error_report("[SHA] No more memory in host!"); + return; + } + + if ( !esp32c3_gdma_read_channel(s->gdma, gdma_out_idx, buffer, buf_size) ) { + warn_report("[SHA] Error reading from GDMA buffer"); + g_free(buffer); + } + + /* Perform the actual SHA operation on the whole buffer */ + for (uint32_t i = 0; i < blocks; i++) + { + alg.compress(&s->context, buffer + i * ESP32C3_MESSAGE_SIZE); + } + memcpy(s->hash, &s->context, alg.len); + + g_free(buffer); + + /* Trigger an interrupt if enabled! */ + if (s->int_ena) { + qemu_irq_raise(s->irq); + } } -static void esp32c3_start_hash(ESP32C3ShaState *s) +static void esp32c3_sha_start(ESP32C3ShaState *s, ESP32C3ShaOperation op) { ESP32C3HashAlg alg = esp32c3_algs[s->mode]; + assert(alg.init && alg.compress); - if (alg.init && alg.compress) { + if ((op & SHA_OP_TYPE_MASK) == OP_START) { alg.init(&s->context); - esp32c3_resume_hash(s); + } else { + /* Continue operation: initialize the context from the current hash. + * We don't have any accessor to do it so ... do it the "dirty" way */ + memcpy(&s->context, s->hash, alg.len); + } + + if ((op & SHA_OP_DMA_MASK) == SHA_OP_DMA_MASK) { + esp32c3_sha_continue_dma(s); + } else { + esp32c3_sha_continue_hash(s); } } @@ -86,14 +152,18 @@ static uint64_t esp32c3_sha_read(void *opaque, hwaddr addr, unsigned int size) break; case A_SHA_H_MEM ... A_SHA_M_MEM - 1: index = (addr - A_SHA_H_MEM) / sizeof(uint32_t); - r = __builtin_bswap32(s->hash[index]); + r = bswap32(s->hash[index]); break; case A_SHA_M_MEM ... ESP32C3_SHA_REGS_SIZE - 1: index = (addr - A_SHA_M_MEM) / sizeof(uint32_t); r = s->message[index]; break; case A_SHA_DMA_BLOCK_NUM: + r = s->block; + break; case A_SHA_IRQ_ENA: + r = s->int_ena ? 1 : 0; + break; default: #if SHA_WARNING warn_report("[ESP32-C3] SHA DMA and IRQ unsupported for now, ignoring...\n"); @@ -101,6 +171,10 @@ static uint64_t esp32c3_sha_read(void *opaque, hwaddr addr, unsigned int size) break; } +#if SHA_DEBUG + info_report("[ESP32-C3] SHA reading %08lx (%08lx)", addr, r); +#endif + return r; } @@ -111,35 +185,71 @@ static void esp32c3_sha_write(void *opaque, hwaddr addr, ESP32C3ShaState *s = ESP32C3_SHA(opaque); hwaddr index = 0; +#if SHA_DEBUG + info_report("[ESP32-C3] SHA writing %08lx (%08lx)", addr, value); +#endif + switch (addr) { case A_SHA_MODE: /* Make sure the value is always between 0 and 2 as the real hardware doesn't * accept a value of 3. Choose SHA-1 by default in that case. */ s->mode = (value & 0b11) % 3; break; + case A_SHA_START: - esp32c3_start_hash(s); + if (FIELD_EX32(value, SHA_START, START)) { + esp32c3_sha_start(s, OP_START); + } break; + case A_SHA_CONTINUE: - esp32c3_resume_hash(s); + if (FIELD_EX32(value, SHA_CONTINUE, CONTINUE)) { + esp32c3_sha_start(s, OP_CONTINUE); + } break; + case A_SHA_H_MEM ... A_SHA_M_MEM - 1: + /* Only support word aligned access for the moment */ + if (size != sizeof(uint32_t)) { + error_report("[SHA] Only 32-bit word access supported at the moment"); + } index = (addr - A_SHA_H_MEM) / sizeof(uint32_t); - s->hash[index] = (uint32_t) value; + s->hash[index] = bswap32((uint32_t) value); break; + case A_SHA_M_MEM ... ESP32C3_SHA_REGS_SIZE - 1: index = (addr - A_SHA_M_MEM) / sizeof(uint32_t); s->message[index] = (uint32_t) value; break; + case A_SHA_DMA_BLOCK_NUM: + s->block = FIELD_EX32(value, SHA_DMA_BLOCK_NUM, DMA_BLOCK_NUM); + break; + case A_SHA_DMA_START: + if (FIELD_EX32(value, SHA_DMA_START, DMA_START)) { + esp32c3_sha_start(s, OP_DMA_START); + } + break; + case A_SHA_DMA_CONTINUE: + if (FIELD_EX32(value, SHA_DMA_CONTINUE, DMA_CONTINUE)) { + esp32c3_sha_start(s, OP_DMA_CONTINUE); + } + break; + case A_SHA_CLEAR_IRQ: + qemu_irq_lower(s->irq); + break; + case A_SHA_IRQ_ENA: + s->int_ena = FIELD_EX32(value, SHA_IRQ_ENA, INTERRUPT_ENA) != 0; + break; + default: #if SHA_WARNING /* Unsupported for now, do nothing */ - warn_report("[SHA] DMA and IRQ unsupported for now, ignoring\n"); + warn_report("[SHA] Unsupported write to %08lx\n", addr); #endif break; } @@ -151,6 +261,30 @@ static const MemoryRegionOps esp32c3_sha_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; + +static void esp32c3_sha_reset(DeviceState *dev) +{ + ESP32C3ShaState *s = ESP32C3_SHA(dev); + memset(s->hash, 0, 8 * sizeof(uint32_t)); + memset(s->message, 0, ESP32C3_MESSAGE_WORDS * sizeof(uint32_t)); + + s->block = 0; + s->int_ena = 0; + qemu_irq_lower(s->irq); +} + + +static void esp32c3_sha_realize(DeviceState *dev, Error **errp) +{ + ESP32C3ShaState *s = ESP32C3_SHA(dev); + + /* Make sure GDMA was set of issue an error */ + if (s->gdma == NULL) { + error_report("[SHA] GDMA controller must be set!"); + } +} + + static void esp32c3_sha_init(Object *obj) { ESP32C3ShaState *s = ESP32C3_SHA(obj); @@ -159,6 +293,16 @@ static void esp32c3_sha_init(Object *obj) memory_region_init_io(&s->iomem, obj, &esp32c3_sha_ops, s, TYPE_ESP32C3_SHA, ESP32C3_SHA_REGS_SIZE); sysbus_init_mmio(sbd, &s->iomem); + + sysbus_init_irq(sbd, &s->irq); +} + +static void esp32_sha_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = esp32c3_sha_realize; + dc->reset = esp32c3_sha_reset; } static const TypeInfo esp32c3_sha_info = { @@ -166,6 +310,7 @@ static const TypeInfo esp32c3_sha_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ESP32C3ShaState), .instance_init = esp32c3_sha_init, + .class_init = esp32_sha_class_init, }; static void esp32c3_sha_register_types(void) diff --git a/hw/riscv/esp32c3.c b/hw/riscv/esp32c3.c index caa426d5b13d..fb1a0ccde15d 100644 --- a/hw/riscv/esp32c3.c +++ b/hw/riscv/esp32c3.c @@ -419,13 +419,6 @@ static void esp32c3_machine_init(MachineState *machine) } } - /* SHA realization */ - { - qdev_realize(DEVICE(&ms->sha), &ms->periph_bus, &error_fatal); - MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->sha), 0); - memory_region_add_subregion_overlap(sys_mem, DR_REG_SHA_BASE, mr, 0); - } - /* Timer Groups realization */ { qdev_realize(DEVICE(&ms->timg[0]), &ms->periph_bus, &error_fatal); @@ -480,6 +473,16 @@ static void esp32c3_machine_init(MachineState *machine) } + /* SHA realization */ + { + ms->sha.gdma = &ms->gdma; + qdev_realize(DEVICE(&ms->sha), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->sha), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_SHA_BASE, mr, 0); + sysbus_connect_irq(SYS_BUS_DEVICE(&ms->sha), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_SHA_INTR_SOURCE)); + } + /* AES realization */ { ms->aes.gdma = &ms->gdma; diff --git a/include/hw/misc/esp32c3_sha.h b/include/hw/misc/esp32c3_sha.h index 960147e38fd0..598dae2b826d 100644 --- a/include/hw/misc/esp32c3_sha.h +++ b/include/hw/misc/esp32c3_sha.h @@ -7,6 +7,7 @@ #include "crypto/sha256_i.h" #include "crypto/sha224_i.h" #include "crypto/sha1_i.h" +#include "hw/dma/esp32c3_gdma.h" #define TYPE_ESP32C3_SHA "misc.esp32c3.sha" #define ESP32C3_SHA(obj) OBJECT_CHECK(ESP32C3ShaState, (obj), TYPE_ESP32C3_SHA) @@ -62,6 +63,15 @@ typedef struct ESP32C3ShaState { uint32_t hash[8]; /* User data value */ uint32_t message[ESP32C3_MESSAGE_WORDS]; + + /* DMA related */ + /* Number of block to process in DMA mode */ + uint32_t block; + bool int_ena; + qemu_irq irq; + + /* Public: must be set before realizing instance*/ + ESP32C3GdmaState *gdma; } ESP32C3ShaState; @@ -76,10 +86,10 @@ REG32(SHA_DMA_BLOCK_NUM, 0x00C) FIELD(SHA_DMA_BLOCK_NUM, DMA_BLOCK_NUM, 0, 6) REG32(SHA_START, 0x010) - FIELD(SHA_START, START, 1, 31) + FIELD(SHA_START, START, 0, 1) REG32(SHA_CONTINUE, 0x014) - FIELD(SHA_CONTINUE, CONTINUE, 1, 31) + FIELD(SHA_CONTINUE, CONTINUE, 0, 1) REG32(SHA_BUSY, 0x018) FIELD(SHA_BUSY, BUSY_STATE, 0, 1) diff --git a/include/hw/nvram/esp32c3_efuse.h b/include/hw/nvram/esp32c3_efuse.h index fe43b244fad4..9df827c96ba3 100644 --- a/include/hw/nvram/esp32c3_efuse.h +++ b/include/hw/nvram/esp32c3_efuse.h @@ -259,7 +259,7 @@ struct ESP32C3EfuseRegs { uint32_t rd_key5_data6; /*Register $n of BLOCK9 (KEY5).*/ uint32_t rd_key5_data7; /*Register $n of BLOCK9 (KEY5).*/ uint32_t rd_sys_part2_data0; /*Register $n of BLOCK10 (system).*/ - uint32_t rd_sys_part2_data1; /*Register $n of BLOCK9 (KEY5).*/ + uint32_t rd_sys_part2_data1; /*Register $n of BLOCK10 (system).*/ uint32_t rd_sys_part2_data2; /*Register $n of BLOCK10 (system).*/ uint32_t rd_sys_part2_data3; /*Register $n of BLOCK10 (system).*/ uint32_t rd_sys_part2_data4; /*Register $n of BLOCK10 (system).*/ From 96ab065d802165297075df81f3fabc29284cdb78 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Wed, 21 Jun 2023 18:08:09 +0800 Subject: [PATCH 53/56] hw/misc: implement RSA controller for ESP32-C3 --- hw/misc/esp32c3_rsa.c | 425 ++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + hw/riscv/esp32c3.c | 13 ++ include/hw/misc/esp32c3_rsa.h | 88 +++++++ 4 files changed, 527 insertions(+) create mode 100644 hw/misc/esp32c3_rsa.c create mode 100644 include/hw/misc/esp32c3_rsa.h diff --git a/hw/misc/esp32c3_rsa.c b/hw/misc/esp32c3_rsa.c new file mode 100644 index 000000000000..545e0af23e67 --- /dev/null +++ b/hw/misc/esp32c3_rsa.c @@ -0,0 +1,425 @@ +/* + * ESP32-C3 RSA accelerator + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/boards.h" +#include "hw/misc/esp32c3_rsa.h" +#include "hw/irq.h" +#include + +#define ESP32C3_RSA_REGS_SIZE (A_RSA_DATE_REG + 4) + +#define RSA_WARNING 0 + +static void copy_reversed(unsigned char* dest, size_t dst_size, const unsigned char* src, size_t src_size); +static bool mpi_block_to_gcrypt(const uint32_t* mem_block, size_t n_bytes, gcry_mpi_t *out); +static bool mpi_gcrypt_to_block(gcry_mpi_t in, uint32_t* mem_block); +static void esp32c3_rsa_exp_mod(ESP32C3RsaState *s); +static void esp32c3_rsa_modmul_start(ESP32C3RsaState *s); + +/** + * Convert between libgcrypt big-endian representation and little-endian hardware, or vice versa. + * src_size should not exceed dst_size. The remaining part of dst is filled with 0. + */ +static void copy_reversed(unsigned char* dst, size_t dst_size, const unsigned char* src, size_t src_size) +{ + assert(src_size <= dst_size); + size_t i; + for (i = 0; i < src_size; ++i) { + dst[i] = src[src_size - i - 1]; + } + for (; i < dst_size; ++i) { + dst[i] = 0; + } +} + + +/** + * Converts the little-endian memory block of the RSA peripheral to a new gcry_mpi_t object. + * The caller is responsible for freeing the returned object. + */ +static bool mpi_block_to_gcrypt(const uint32_t* mem_block, size_t n_bytes, gcry_mpi_t *out) +{ + size_t scanned; + const unsigned char* mem_u8 = (const unsigned char*) mem_block; + unsigned char temp_buffer[ESP32C3_RSA_MEM_BLK_SIZE] = {}; + copy_reversed(temp_buffer, n_bytes, mem_u8, n_bytes); + gcry_error_t err = gcry_mpi_scan(out, GCRYMPI_FMT_USG, temp_buffer, n_bytes, &scanned); + if (err) { + error_report("%s: gcry_mpi_scan failed with error: %s (%d)", __func__, gcry_strerror(err), err); + return false; + } + if (scanned != n_bytes) { + error_report("%s: gcry_mpi_scan scanned %zu, expected %zu", __func__, scanned, n_bytes); + return false; + } + return true; +} + + +/** + * Copies an MPI from gcry_mpi_t object to the RSA peripheral memory block. + */ +static bool mpi_gcrypt_to_block(gcry_mpi_t in, uint32_t* mem_block) +{ + size_t written; + unsigned char* mem_u8 = (unsigned char*) mem_block; + unsigned char temp_buffer[ESP32C3_RSA_MEM_BLK_SIZE] = {}; + gcry_error_t err = gcry_mpi_print(GCRYMPI_FMT_USG, temp_buffer, ESP32C3_RSA_MEM_BLK_SIZE, &written, in); + if (err) { + error_report("%s: gcry_mpi_print failed with error: %s (%d)", __func__, gcry_strerror(err), err); + return false; + } + copy_reversed(mem_u8, ESP32C3_RSA_MEM_BLK_SIZE, temp_buffer, written); + return true; +} + + +/** Calculates Z_MEM = X_MEM ^ Y_MEM mod M_MEM. + * Unlike the real hardware, doesn't use the mprime register. + */ +static void esp32c3_rsa_exp_mod(ESP32C3RsaState *s) +{ + gcry_mpi_t x, y, z, m; + + /* Get the length of the operands in bytes. Register mode_reg designates the length + * in 32-bit words. */ + size_t n_bytes = (s->mode_reg + 1) * 4; + + /* Convert inputs to gcry_mpi_t */ + if (!mpi_block_to_gcrypt(s->x_mem, n_bytes, &x)) { + goto error_ret; + } + if (!mpi_block_to_gcrypt(s->y_mem, n_bytes, &y)) { + goto error_x; + } + if (!mpi_block_to_gcrypt(s->m_mem, n_bytes, &m)) { + goto error_y; + } + + /* calculate the result and write it back */ + z = gcry_mpi_new(n_bytes * 8); + gcry_mpi_powm(z, x, y, m); + mpi_gcrypt_to_block(z, s->z_mem); + + /* Trigger an interrupt on completion */ + if (s->int_ena) { + qemu_set_irq(s->irq, 1); + } + + /* Clean up */ + gcry_mpi_release(m); + gcry_mpi_release(z); +error_y: + gcry_mpi_release(y); +error_x: + gcry_mpi_release(x); +error_ret: + return; +} + + +/* Calculates Z_MEM = X_MEM * Y_MEM mod M_MEM. */ +static void esp32c3_rsa_modmul_start(ESP32C3RsaState *s) +{ + assert(s->mode_reg < (1 << 7)); + gcry_mpi_t m, x, z, y; + + /* In this mode, the output and input lengths are the same, mode_reg represents the length of + * the operands in 32-bit word. Multiply by 4 to get the size in bytes. */ + const size_t n_bytes = (s->mode_reg + 1) * 4; + + /* Convert inputs to gcry_mpi_t */ + if (!mpi_block_to_gcrypt(s->x_mem, n_bytes, &x)) { + goto error_ret; + } + if (!mpi_block_to_gcrypt(s->y_mem, n_bytes, &y)) { + goto error_x; + } + if (!mpi_block_to_gcrypt(s->m_mem, n_bytes, &m)) { + goto error_y; + } + + z = gcry_mpi_new(n_bytes * 8 * 2); + + /* Z = X * Y mod M */ + gcry_mpi_mulm(z, x, y, m); + + /* Write back */ + mpi_gcrypt_to_block(z, s->z_mem); + + /* Trigger an interrupt on completion */ + if (s->int_ena) { + qemu_set_irq(s->irq, 1); + } + + /* Clean up */ + gcry_mpi_release(z); + gcry_mpi_release(m); +error_y: + gcry_mpi_release(y); +error_x: + gcry_mpi_release(x); +error_ret: + return; +} + + +/** Calculates Z_MEM = X_MEM * Z_MEM */ +static void esp32c3_rsa_mul_start(ESP32C3RsaState *s) +{ + /* In this mode, the output length, in 32-bit word, is set by mode_reg. The input is length / 2. + * Thus, multiply mode_reg by 4 to get the number of bytes. */ + size_t n_bytes = (s->mode_reg + 1) * 4; + size_t n_bytes_input = n_bytes / 2; + + memcpy(s->z_mem, s->z_mem + n_bytes_input / sizeof(uint32_t), n_bytes_input); + memset(s->z_mem + n_bytes_input / sizeof(uint32_t), 0, n_bytes_input); + + /* Convert inputs to gcry_mpi_t */ + gcry_mpi_t x, z, result; + if (!mpi_block_to_gcrypt(s->x_mem, n_bytes, &x)) { + goto error_ret; + } + if (!mpi_block_to_gcrypt(s->z_mem, n_bytes, &z)) { + goto error_x; + } + + /* Multiply */ + result = gcry_mpi_new(n_bytes * 8); + gcry_mpi_mul(result, x, z); + mpi_gcrypt_to_block(result, s->z_mem); + + /* Trigger an interrupt on completion */ + if (s->int_ena) { + qemu_set_irq(s->irq, 1); + } + + /* Clean up */ + gcry_mpi_release(result); + gcry_mpi_release(z); +error_x: + gcry_mpi_release(x); +error_ret: + return; +} + + +static void esp32c3_rsa_clean_mem(ESP32C3RsaState *s) +{ + memset(s->m_mem, 0, sizeof(s->m_mem)); + memset(s->x_mem, 0, sizeof(s->x_mem)); + memset(s->y_mem, 0, sizeof(s->y_mem)); + memset(s->z_mem, 0, sizeof(s->z_mem)); +} + +static uint64_t esp32c3_rsa_read(void *opaque, hwaddr addr, unsigned int size) +{ + ESP32C3RsaState *s = ESP32C3_RSA(opaque); + uint64_t r = 0; + + switch (addr) { + case A_RSA_MEM_M_BLOCK_BASE ... (A_RSA_MEM_M_BLOCK_BASE + ESP32C3_RSA_MEM_BLK_SIZE - 1): + r = s->m_mem[(addr - A_RSA_MEM_M_BLOCK_BASE) / sizeof(uint32_t)]; + break; + + case A_RSA_MEM_Z_BLOCK_BASE ... (A_RSA_MEM_Z_BLOCK_BASE + ESP32C3_RSA_MEM_BLK_SIZE - 1): + r = s->z_mem[(addr - A_RSA_MEM_Z_BLOCK_BASE) / sizeof(uint32_t)]; + break; + + case A_RSA_MEM_Y_BLOCK_BASE ... (A_RSA_MEM_Y_BLOCK_BASE + ESP32C3_RSA_MEM_BLK_SIZE - 1): + r = s->y_mem[(addr - A_RSA_MEM_Y_BLOCK_BASE) / sizeof(uint32_t)]; + break; + + case A_RSA_MEM_X_BLOCK_BASE ... (A_RSA_MEM_X_BLOCK_BASE + ESP32C3_RSA_MEM_BLK_SIZE - 1): + r = s->x_mem[(addr - A_RSA_MEM_X_BLOCK_BASE) / sizeof(uint32_t)]; + break; + + case A_RSA_M_PRIME_REG: + r = s->mprime_reg; + break; + + case A_RSA_MODE_REG: + r = s->mode_reg; + break; + + case A_RSA_CONSTANT_TIME_REG: + r = s->const_time_reg; + break; + + case A_RSA_SEARCH_ENABLE_REG: + r = s->search_ena_reg; + break; + + case A_RSA_SEARCH_POS_REG: + r = s->search_pos_reg; + break; + + case A_RSA_CLEAN_REG: + esp32c3_rsa_clean_mem(s); + r = 1; + break; + + case A_RSA_IDLE_REG: + /* Always Idle */ + r = 1; + break; + + case A_RSA_INTERRUPT_ENA_REG: + r = s->int_ena; + break; + + default: +#if RSA_WARNING + warn_report("[RSA] Unsupported read to register %08x\n", addr); +#endif + break; + + } + + return r; +} + + +static void esp32c3_rsa_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + ESP32C3RsaState *s = ESP32C3_RSA(opaque); + + switch (addr) { + + case A_RSA_MEM_M_BLOCK_BASE ... (A_RSA_MEM_M_BLOCK_BASE + ESP32C3_RSA_MEM_BLK_SIZE - 1): + s->m_mem[(addr - A_RSA_MEM_M_BLOCK_BASE) / sizeof(uint32_t)] = (uint32_t)value; + break; + + case A_RSA_MEM_Z_BLOCK_BASE ... (A_RSA_MEM_Z_BLOCK_BASE + ESP32C3_RSA_MEM_BLK_SIZE - 1): + s->z_mem[(addr - A_RSA_MEM_Z_BLOCK_BASE) / sizeof(uint32_t)] = (uint32_t)value; + break; + + case A_RSA_MEM_Y_BLOCK_BASE ... (A_RSA_MEM_Y_BLOCK_BASE + ESP32C3_RSA_MEM_BLK_SIZE - 1): + s->y_mem[(addr - A_RSA_MEM_Y_BLOCK_BASE) / sizeof(uint32_t)] = (uint32_t)value; + break; + + case A_RSA_MEM_X_BLOCK_BASE ... (A_RSA_MEM_X_BLOCK_BASE + ESP32C3_RSA_MEM_BLK_SIZE - 1): + s->x_mem[(addr - A_RSA_MEM_X_BLOCK_BASE) / sizeof(uint32_t)] = (uint32_t)value; + break; + + case A_RSA_M_PRIME_REG: + s->mprime_reg = value; + break; + + case A_RSA_MODE_REG: + s->mode_reg = FIELD_EX32(value, RSA_MODE_REG, RSA_MODE); + break; + + case A_RSA_CONSTANT_TIME_REG: + s->const_time_reg = FIELD_EX32(value, RSA_CONSTANT_TIME_REG, RSA_CONSTANT_TIME); + break; + + case A_RSA_SEARCH_ENABLE_REG: + s->search_ena_reg = FIELD_EX32(value, RSA_SEARCH_ENABLE_REG, RSA_SEARCH_ENABLE); + break; + + case A_RSA_SEARCH_POS_REG: + s->search_pos_reg = FIELD_EX32(value, RSA_SEARCH_POS_REG, RSA_SEARCH_POS); + break; + + case A_RSA_MODEXP_START_REG: + if (FIELD_EX32(value, RSA_MODEXP_START_REG, RSA_MODEXP_START)) { + esp32c3_rsa_exp_mod(s); + } + break; + + case A_RSA_MODMULT_START_REG: + if (FIELD_EX32(value, RSA_MODMULT_START_REG, RSA_MODMULT_START)) { + esp32c3_rsa_modmul_start(s); + } + break; + + case A_RSA_MULT_START_REG: + if (FIELD_EX32(value, RSA_MULT_START_REG, RSA_MULT_START)) { + esp32c3_rsa_mul_start(s); + } + break; + + case A_RSA_CLEAR_INTERRUPT_REG: + if (FIELD_EX32(value, RSA_CLEAR_INTERRUPT_REG, RSA_CLEAR_INTERRUPT)) { + qemu_irq_lower(s->irq); + } + break; + + case A_RSA_INTERRUPT_ENA_REG: + s->int_ena = FIELD_EX32(value, RSA_INTERRUPT_ENA_REG, RSA_INTERRUPT_ENA); + break; + + default: +#if RSA_WARNING + warn_report("[RSA] Unsupported write to register %08x\n", addr); +#endif + break; + } + +} + +static const MemoryRegionOps esp32c3_rsa_ops = { + .read = esp32c3_rsa_read, + .write = esp32c3_rsa_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32c3_rsa_reset(DeviceState *dev) +{ + ESP32C3RsaState *s = ESP32C3_RSA(dev); + + esp32c3_rsa_clean_mem(s); + + /* Clear any spurious interrupt */ + s->int_ena = 0; + qemu_irq_lower(s->irq); +} + +static void esp32c3_rsa_init(Object *obj) +{ + ESP32C3RsaState *s = ESP32C3_RSA(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32c3_rsa_ops, s, + TYPE_ESP32C3_RSA, ESP32C3_RSA_REGS_SIZE); + sysbus_init_mmio(sbd, &s->iomem); + + sysbus_init_irq(sbd, &s->irq); +} + +static void esp32c3_rsa_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->reset = esp32c3_rsa_reset; +} + +static const TypeInfo esp32c3_rsa_info = { + .name = TYPE_ESP32C3_RSA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(ESP32C3RsaState), + .instance_init = esp32c3_rsa_init, + .class_init = esp32c3_rsa_class_init +}; + +static void esp32c3_rsa_register_types(void) +{ + type_register_static(&esp32c3_rsa_info); +} + +type_init(esp32c3_rsa_register_types) diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 9a34c6e96e94..a062aa255368 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -149,6 +149,7 @@ if gcrypt.found() )) softmmu_ss.add(when: [gcrypt, 'CONFIG_RISCV_ESP32C3'], if_true: files( 'esp32c3_aes.c', + 'esp32c3_rsa.c' )) endif diff --git a/hw/riscv/esp32c3.c b/hw/riscv/esp32c3.c index fb1a0ccde15d..e43b4ba63a05 100644 --- a/hw/riscv/esp32c3.c +++ b/hw/riscv/esp32c3.c @@ -40,6 +40,7 @@ #include "hw/ssi/esp32c3_spi.h" #include "hw/misc/esp32c3_rtc_cntl.h" #include "hw/misc/esp32c3_aes.h" +#include "hw/misc/esp32c3_rsa.h" #include "hw/misc/esp32c3_jtag.h" #include "hw/dma/esp32c3_gdma.h" @@ -70,6 +71,7 @@ struct Esp32C3MachineState { ESP32C3GdmaState gdma; ESP32C3AesState aes; ESP32C3ShaState sha; + ESP32C3RsaState rsa; ESP32C3TimgState timg[2]; ESP32C3SysTimerState systimer; ESP32C3SpiState spi1; @@ -176,6 +178,7 @@ static void esp32c3_cpu_reset(void* opaque, int n, int level) device_cold_reset(DEVICE(&s->gdma)); device_cold_reset(DEVICE(&s->aes)); device_cold_reset(DEVICE(&s->sha)); + device_cold_reset(DEVICE(&s->rsa)); device_cold_reset(DEVICE(&s->systimer)); device_cold_reset(DEVICE(&s->spi1)); device_cold_reset(DEVICE(&s->rtccntl)); @@ -317,6 +320,7 @@ static void esp32c3_machine_init(MachineState *machine) object_initialize_child(OBJECT(machine), "sha", &ms->sha, TYPE_ESP32C3_SHA); object_initialize_child(OBJECT(machine), "aes", &ms->aes, TYPE_ESP32C3_AES); object_initialize_child(OBJECT(machine), "gdma", &ms->gdma, TYPE_ESP32C3_GDMA); + object_initialize_child(OBJECT(machine), "rsa", &ms->rsa, TYPE_ESP32C3_RSA); object_initialize_child(OBJECT(machine), "timg0", &ms->timg[0], TYPE_ESP32C3_TIMG); object_initialize_child(OBJECT(machine), "timg1", &ms->timg[1], TYPE_ESP32C3_TIMG); object_initialize_child(OBJECT(machine), "systimer", &ms->systimer, TYPE_ESP32C3_SYSTIMER); @@ -493,6 +497,15 @@ static void esp32c3_machine_init(MachineState *machine) qdev_get_gpio_in(intmatrix_dev, ETS_AES_INTR_SOURCE)); } + /* RSA realization */ + { + qdev_realize(DEVICE(&ms->rsa), &ms->periph_bus, &error_fatal); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&ms->rsa), 0); + memory_region_add_subregion_overlap(sys_mem, DR_REG_RSA_BASE, mr, 0); + sysbus_connect_irq(SYS_BUS_DEVICE(&ms->rsa), 0, + qdev_get_gpio_in(intmatrix_dev, ETS_RSA_INTR_SOURCE)); + } + /* Open and load the "bios", which is the ROM binary, also named "first stage bootloader" */ char *rom_binary = qemu_find_file(QEMU_FILE_TYPE_BIOS, "esp32c3-rom.bin"); if (rom_binary == NULL) { diff --git a/include/hw/misc/esp32c3_rsa.h b/include/hw/misc/esp32c3_rsa.h new file mode 100644 index 000000000000..961c55562cc8 --- /dev/null +++ b/include/hw/misc/esp32c3_rsa.h @@ -0,0 +1,88 @@ +/* + * ESP32-C3 RSA accelerator + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co. Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32c3_reg.h" + + +#define TYPE_ESP32C3_RSA "misc.esp32c3.rsa" +#define ESP32C3_RSA(obj) OBJECT_CHECK(ESP32C3RsaState, (obj), TYPE_ESP32C3_RSA) + +#define ESP32C3_RSA_MEM_BLK_SIZE 384 + +typedef struct ESP32C3RsaState { + SysBusDevice parent_obj; + MemoryRegion iomem; + + uint32_t m_mem[ESP32C3_RSA_MEM_BLK_SIZE / 4]; + uint32_t z_mem[ESP32C3_RSA_MEM_BLK_SIZE / 4]; + uint32_t y_mem[ESP32C3_RSA_MEM_BLK_SIZE / 4]; + uint32_t x_mem[ESP32C3_RSA_MEM_BLK_SIZE / 4]; + + /* Configuration registers */ + uint32_t mprime_reg; + uint32_t mode_reg; + uint32_t const_time_reg; + uint32_t search_ena_reg; + uint32_t search_pos_reg; + + /* Status/Control registers */ + uint32_t int_ena; + qemu_irq irq; +} ESP32C3RsaState; + + +REG32(RSA_MEM_M_BLOCK_BASE, 0x000) + +REG32(RSA_MEM_Z_BLOCK_BASE, 0x200) + +REG32(RSA_MEM_Y_BLOCK_BASE, 0x400) + +REG32(RSA_MEM_X_BLOCK_BASE, 0x600) + +REG32(RSA_M_PRIME_REG, 0x800) + +REG32(RSA_MODE_REG, 0x804) + FIELD(RSA_MODE_REG, RSA_MODE, 0, 7) + +REG32(RSA_CLEAN_REG, 0x808) + FIELD(RSA_CLEAN_REG, RSA_CLEAN, 0, 1) + +REG32(RSA_MODEXP_START_REG, 0x80C) + FIELD(RSA_MODEXP_START_REG, RSA_MODEXP_START, 0, 1) + +REG32(RSA_MODMULT_START_REG, 0x810) + FIELD(RSA_MODMULT_START_REG, RSA_MODMULT_START, 0, 1) + +REG32(RSA_MULT_START_REG, 0x814) + FIELD(RSA_MULT_START_REG, RSA_MULT_START, 0, 1) + +REG32(RSA_IDLE_REG, 0x818) + FIELD(RSA_IDLE_REG, RSA_IDLE, 0, 1) + +REG32(RSA_CLEAR_INTERRUPT_REG, 0x81C) + FIELD(RSA_CLEAR_INTERRUPT_REG, RSA_CLEAR_INTERRUPT, 0, 1) + +REG32(RSA_CONSTANT_TIME_REG, 0x820) + FIELD(RSA_CONSTANT_TIME_REG, RSA_CONSTANT_TIME, 0, 1) + +REG32(RSA_SEARCH_ENABLE_REG, 0x824) + FIELD(RSA_SEARCH_ENABLE_REG, RSA_SEARCH_ENABLE, 0, 1) + +REG32(RSA_SEARCH_POS_REG, 0x828) + FIELD(RSA_SEARCH_POS_REG, RSA_SEARCH_POS, 0, 12) + +REG32(RSA_INTERRUPT_ENA_REG, 0x82C) + FIELD(RSA_INTERRUPT_ENA_REG, RSA_INTERRUPT_ENA, 0, 1) + +REG32(RSA_DATE_REG, 0x830) From 5eda8b62353a86095ebc70af97bdbb73a825dc2d Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Thu, 29 Jun 2023 10:35:22 +0800 Subject: [PATCH 54/56] hw/ssi: add support for dummy cycles in ESP32-C3 SPI controller --- hw/ssi/esp32c3_spi.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/hw/ssi/esp32c3_spi.c b/hw/ssi/esp32c3_spi.c index 59c6f1bc6ad1..365a6e991c39 100644 --- a/hw/ssi/esp32c3_spi.c +++ b/hw/ssi/esp32c3_spi.c @@ -49,6 +49,8 @@ typedef struct ESP32C3SpiTransaction { uint32_t addr; uint32_t addr_bytes; + uint32_t dummy_bytes; + void* data; uint32_t tx_bytes; uint32_t rx_bytes; @@ -105,13 +107,13 @@ static uint64_t esp32c3_spi_read(void *opaque, hwaddr addr, unsigned int size) break; default: #if SPI1_WARNING - warn_report("[SPI1] Unsupported read to 0x%lx\n", addr); + warn_report("[SPI1] Unsupported read to 0x%lx", addr); #endif break; } #if SPI1_DEBUG - info_report("[SPI1] Reading 0x%lx (0x%lx)\n", addr, r); + info_report("[SPI1] Reading 0x%lx (0x%lx)", addr, r); #endif return r; @@ -135,12 +137,18 @@ static void esp32c3_spi_txrx_buffer(ESP32C3SpiState *s, } } +static void esp32c3_spi_dummy_cycles(ESP32C3SpiState *s, uint32_t dummy_bytes) { + for (int i = 0; i < dummy_bytes; i++) { + ssi_transfer(s->spi, 0); + } +} static void esp32c3_spi_perform_transaction(ESP32C3SpiState *s, const ESP32C3SpiTransaction *t) { qemu_set_irq(s->cs_gpio[0], 0); esp32c3_spi_txrx_buffer(s, &t->cmd, t->cmd_bytes, NULL, 0); esp32c3_spi_txrx_buffer(s, &t->addr, t->addr_bytes, NULL, 0); + esp32c3_spi_dummy_cycles(s, t->dummy_bytes); esp32c3_spi_txrx_buffer(s, t->data, t->tx_bytes, t->data, t->rx_bytes); qemu_set_irq(s->cs_gpio[0], 1); } @@ -157,6 +165,21 @@ static inline void esp32c3_spi_get_addr(ESP32C3SpiState *s, uint32_t* addr, uint *len = (address_len + 1) / 8; } +static inline void esp32c3_spi_get_dummy(ESP32C3SpiState *s, uint32_t* len) +{ + const uint32_t dummy_count = FIELD_EX32(s->mem_user1, SPI_MEM_USER1, USR_DUMMY_CYCLELEN); + + /* Dummy cycles are interpreted as bytes by the emulated SPI Flash. As such, we shall convert + * our dummy cycles count in bytes, rounding it up. For example: + * 0 cycles = 0 byte + * 1 cycle = 1 byte + * ... + * 8 cycles = 1 byte + * 9 cycles = 2 bytes + * etc.. + */ + *len = (dummy_count + 7) / 8; +} static void esp32c3_spi_begin_transaction(ESP32C3SpiState *s) { @@ -189,6 +212,11 @@ static void esp32c3_spi_begin_transaction(ESP32C3SpiState *s) if (t.addr_bytes > 0 && t.addr_bytes <= 4) { t.addr = t.addr >> (32 - t.addr_bytes * 8); } + + /* Only calculate and include dummy cycles when the USR_DUMMY bit is set! */ + if (s->mem_user & R_SPI_MEM_USER_USR_DUMMY_MASK) { + esp32c3_spi_get_dummy(s, &t.dummy_bytes); + } } esp32c3_spi_perform_transaction(s, &t); @@ -287,7 +315,9 @@ static void esp32c3_spi_special_command(ESP32C3SpiState *s, uint32_t command) break; default: - printf("[SPI1] Unsupported special command %x\n", command); +#if SPI1_WARNING + warn_report("[SPI1] Unsupported special command %x", command); +#endif return; } esp32c3_spi_perform_transaction(s, &t); @@ -301,7 +331,7 @@ static void esp32c3_spi_write(void *opaque, hwaddr addr, uint32_t wvalue = (uint32_t) value; #if SPI1_DEBUG - info_report("[SPI1] Writing 0x%lx = %08lx\n", addr, value); + info_report("[SPI1] Writing 0x%lx = %08lx", addr, value); #endif switch (addr) { @@ -353,7 +383,7 @@ static void esp32c3_spi_write(void *opaque, hwaddr addr, break; default: #if SPI1_WARNING - warn_report("[SPI1] Unsupported write to 0x%lx (%08lx)\n", addr, value); + warn_report("[SPI1] Unsupported write to 0x%lx (%08lx)", addr, value); #endif break; } From d96ca95c64438be08319d6c15432df5b4c736e55 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Thu, 29 Jun 2023 10:35:58 +0800 Subject: [PATCH 55/56] hw/misc: fix a bug in ESP32-C3 cache entries fields Cache entries where incorrectly described, which resulted in wrong values being returned to the guest programs. --- hw/misc/esp32c3_cache.c | 17 +++++++++-------- include/hw/misc/esp32c3_cache.h | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/hw/misc/esp32c3_cache.c b/hw/misc/esp32c3_cache.c index 3ac8e1283dac..c9cfe7cf92db 100644 --- a/hw/misc/esp32c3_cache.c +++ b/hw/misc/esp32c3_cache.c @@ -49,7 +49,7 @@ static inline uint32_t check_and_reset_ena(uint32_t* hwreg, uint32_t ena_mask, u static inline uint32_t esp32c3_read_mmu_value(ESP32C3CacheState *s, hwaddr reg_addr) { /* Make the assumption that the address is aligned on sizeof(uint32_t) */ - const int index = reg_addr / sizeof(uint32_t); + const uint32_t index = reg_addr / sizeof(uint32_t); return (uint32_t) s->mmu[index].val; } @@ -57,10 +57,11 @@ static inline uint32_t esp32c3_read_mmu_value(ESP32C3CacheState *s, hwaddr reg_a static inline void esp32c3_write_mmu_value(ESP32C3CacheState *s, hwaddr reg_addr, uint32_t value) { /* Make the assumption that the address is aligned on sizeof(uint32_t) */ - const int index = reg_addr / sizeof(uint32_t); + const uint32_t index = reg_addr / sizeof(uint32_t); /* Reserved bits shall always be 0 */ - ESP32C3MMUEntry e = { 0 }; - e.page_number = (uint8_t) (value & 0xff); + ESP32C3MMUEntry e = { .val = value }; + /* Always keep reserved as 0 */ + e.reserved = 0; if (s->mmu[index].val != e.val) { assert(s->flash_blk != NULL); /* Update the cache (MemoryRegion) */ @@ -92,7 +93,7 @@ static uint64_t esp32c3_cache_read(void *opaque, hwaddr addr, unsigned int size) if (addr & 0x3) { /* Unaligned access, should we fail? */ - error_report("[QEMU] unaligned access to the cache registers\n"); + error_report("[QEMU] unaligned access to the cache registers"); } switch(addr) { @@ -129,13 +130,13 @@ static uint64_t esp32c3_cache_read(void *opaque, hwaddr addr, unsigned int size) break; default: #if CACHE_WARNING - warn_report("[CACHE] Unsupported read to 0x%lx\n", addr); + warn_report("[CACHE] Unsupported read to 0x%lx", addr); #endif break; } #if CACHE_DEBUG - info_report("[CACHE] Reading 0x%lx (0x%lx)\n", addr, r); + info_report("[CACHE] Reading 0x%lx (0x%lx)", addr, r); #endif return r; @@ -171,7 +172,7 @@ static void esp32c3_cache_write(void *opaque, hwaddr addr, uint64_t value, } #if CACHE_DEBUG - info_report("[CACHE] Writing 0x%lx = %08lx\n", addr, value); + info_report("[CACHE] Writing 0x%lx = %08lx", addr, value); #endif } diff --git a/include/hw/misc/esp32c3_cache.h b/include/hw/misc/esp32c3_cache.h index 72acfc09e5f1..ccc05fd1b941 100644 --- a/include/hw/misc/esp32c3_cache.h +++ b/include/hw/misc/esp32c3_cache.h @@ -29,9 +29,9 @@ typedef union ESP32C3MMUEntry { struct { - uint32_t reserved : 23; /* Must always be 0 */ - uint32_t invalid : 1; uint32_t page_number : 8; + uint32_t invalid : 1; + uint32_t reserved : 23; /* Must always be 0 */ }; uint32_t val; } ESP32C3MMUEntry; From 47ff9135c3f8890c9d93a2775eb4e5f6d8e65c04 Mon Sep 17 00:00:00 2001 From: redfast00 Date: Tue, 4 Jul 2023 16:51:46 +0200 Subject: [PATCH 56/56] Implement undocument wifi registers, get AP mode working ESP32 as client, QEMU as AP works with the following command: build/qemu-system-xtensa -nic user,model=misc.esp32_wifi,id=u1 -no-reboot -S -s -nographic -machine esp32 -drive file=../http_request/meshtest_http_10.0.0.8.bin,if=mtd,format=raw -object filter-dump,id=f1,file=dump.pcap,netdev=u1 -drive file=../efuse.bin,if=none,format=raw,id=efuse -global driver=nvram.esp32.efuse,property=drive,value=efuse The efuse file was dumped from a real ESP32 with espefuse.py dump The meshtest_http_... file was built from esp-idf/examples/protocols/http_request, configured to connect to one of the APs hardcoded in hw/misc/esp32_wifi_ap.c Co-authored-by: Martin Johnson --- hw/misc/esp32_ana.c | 72 ++++++ hw/misc/esp32_fe.c | 56 +++++ hw/misc/esp32_phya.c | 54 +++++ hw/misc/esp32_unknown.c | 75 ++++++ hw/misc/esp32_wifi.c | 173 ++++++++++++++ hw/misc/esp32_wifi_ap.c | 410 ++++++++++++++++++++++++++++++++ hw/misc/esp32_wlan.h | 226 ++++++++++++++++++ hw/misc/esp32_wlan_packet.c | 283 ++++++++++++++++++++++ hw/misc/esp32_wlan_packet.h | 56 +++++ hw/misc/meson.build | 9 +- hw/misc/unimp-default.c | 101 ++++++++ hw/xtensa/esp32.c | 117 +++++++-- hw/xtensa/esp32_intc.c | 14 +- include/hw/misc/esp32_ana.h | 17 ++ include/hw/misc/esp32_fe.h | 17 ++ include/hw/misc/esp32_phya.h | 17 ++ include/hw/misc/esp32_reg.h | 6 +- include/hw/misc/esp32_unknown.h | 15 ++ include/hw/misc/esp32_wifi.h | 65 +++++ include/hw/misc/unimp-default.h | 58 +++++ include/hw/xtensa/esp32.h | 13 + include/hw/xtensa/esp32_intc.h | 1 + 22 files changed, 1827 insertions(+), 28 deletions(-) create mode 100644 hw/misc/esp32_ana.c create mode 100644 hw/misc/esp32_fe.c create mode 100644 hw/misc/esp32_phya.c create mode 100644 hw/misc/esp32_unknown.c create mode 100644 hw/misc/esp32_wifi.c create mode 100644 hw/misc/esp32_wifi_ap.c create mode 100644 hw/misc/esp32_wlan.h create mode 100644 hw/misc/esp32_wlan_packet.c create mode 100644 hw/misc/esp32_wlan_packet.h create mode 100644 hw/misc/unimp-default.c create mode 100644 include/hw/misc/esp32_ana.h create mode 100644 include/hw/misc/esp32_fe.h create mode 100644 include/hw/misc/esp32_phya.h create mode 100644 include/hw/misc/esp32_unknown.h create mode 100644 include/hw/misc/esp32_wifi.h create mode 100644 include/hw/misc/unimp-default.h diff --git a/hw/misc/esp32_ana.c b/hw/misc/esp32_ana.c new file mode 100644 index 000000000000..dc8da7064304 --- /dev/null +++ b/hw/misc/esp32_ana.c @@ -0,0 +1,72 @@ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_ana.h" + +int esp32_wifi_channel=0; + +static uint64_t esp32_ana_read(void *opaque, hwaddr addr, unsigned int size) +{ + Esp32AnaState *s = ESP32_ANA(opaque); + // printf("analog read for %016lX\n", addr); + uint32_t r = s->mem[addr/4]; + switch(addr) { + case 4: r= 0xFDFFFFFF; + break; + case 68: + case 76: + case 196: r=0xFFFFFFFF; + break; + } + return r; +} + +static void esp32_ana_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) { + Esp32AnaState *s = ESP32_ANA(opaque); + if (addr == 196) { + int v = value&255; + if ((v % 10)==4) { + esp32_wifi_channel=(v/10)-1; + printf("esp32 wifi channel register = %d\n", esp32_wifi_channel); + } + } + s->mem[addr/4]=value; + // printf("analog write to %016lx, value=%016lx\n", addr, value); +} + +static const MemoryRegionOps esp32_ana_ops = { + .read = esp32_ana_read, + .write = esp32_ana_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_ana_init(Object *obj) +{ + Esp32AnaState *s = ESP32_ANA(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_ana_ops, s, + TYPE_ESP32_ANA, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + memset(s->mem,0,sizeof(s->mem)); +} + + +static const TypeInfo esp32_ana_info = { + .name = TYPE_ESP32_ANA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32AnaState), + .instance_init = esp32_ana_init, +}; + +static void esp32_ana_register_types(void) +{ + type_register_static(&esp32_ana_info); +} + +type_init(esp32_ana_register_types) diff --git a/hw/misc/esp32_fe.c b/hw/misc/esp32_fe.c new file mode 100644 index 000000000000..1de52d4cce9b --- /dev/null +++ b/hw/misc/esp32_fe.c @@ -0,0 +1,56 @@ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_fe.h" + +static uint64_t esp32_fe_read(void *opaque, hwaddr addr, unsigned int size) +{ + uint32_t r = 0; + Esp32FeState *s = ESP32_FE(opaque); + r = s->mem[addr/4]; + if (addr == 0x7c) { + r = 0xffffffff; + } + return r; +} + +static void esp32_fe_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) { + Esp32FeState *s = ESP32_FE(opaque); + s->mem[addr/4] = (uint32_t)value; +} + +static const MemoryRegionOps esp32_fe_ops = { + .read = esp32_fe_read, + .write = esp32_fe_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_fe_init(Object *obj) +{ + Esp32FeState *s = ESP32_FE(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_fe_ops, s, TYPE_ESP32_FE, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + memset(s->mem, 0, sizeof(s->mem)); +} + + +static const TypeInfo esp32_fe_info = { + .name = TYPE_ESP32_FE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32FeState), + .instance_init = esp32_fe_init, +}; + +static void esp32_fe_register_types(void) +{ + type_register_static(&esp32_fe_info); +} + +type_init(esp32_fe_register_types) diff --git a/hw/misc/esp32_phya.c b/hw/misc/esp32_phya.c new file mode 100644 index 000000000000..38956e597524 --- /dev/null +++ b/hw/misc/esp32_phya.c @@ -0,0 +1,54 @@ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_phya.h" + +static uint64_t esp32_phya_read(void *opaque, hwaddr addr, unsigned int size) +{ + uint32_t r = 0; + Esp32PhyaState *s = ESP32_PHYA(opaque); + r=s->mem[addr/4]; + return r; +} + +static void esp32_phya_write(void *opaque, hwaddr addr, uint64_t value, + unsigned int size) { + Esp32PhyaState *s = ESP32_PHYA(opaque); + s->mem[addr/4]=(uint32_t)value; +} + +static const MemoryRegionOps esp32_phya_ops = { + .read = esp32_phya_read, + .write = esp32_phya_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_phya_init(Object *obj) +{ + Esp32PhyaState *s = ESP32_PHYA(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_phya_ops, s, + TYPE_ESP32_PHYA, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + memset(s->mem,0,sizeof(s->mem)); +} + + +static const TypeInfo esp32_phya_info = { + .name = TYPE_ESP32_PHYA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32PhyaState), + .instance_init = esp32_phya_init, +}; + +static void esp32_phya_register_types(void) +{ + type_register_static(&esp32_phya_info); +} + +type_init(esp32_phya_register_types) diff --git a/hw/misc/esp32_unknown.c b/hw/misc/esp32_unknown.c new file mode 100644 index 000000000000..4ff39932a74d --- /dev/null +++ b/hw/misc/esp32_unknown.c @@ -0,0 +1,75 @@ +/* ESP32 unknown peripheral handler +*/ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/boards.h" +#include "hw/misc/esp32_unknown.h" +#include "hw/misc/esp32_reg.h" + +static uint64_t esp32_unknown_read(void *opaque, hwaddr addr, unsigned int size) +{ + addr += 0x3ff00000; + uint64_t r = 0; + switch (addr) { + case (DR_REG_ANA_BASE + 0x04c): { // used in ram_txdc_cal_v70, esp32.analog region + r = 0x1000000; + break; + } + case 0x3ff4607c: { // used in ram_iq_est_enable, reserved region + r = 0xffffffff; + break; + } + + default: { + printf("unknown read for %016lX\n", addr); + break; + } + } + // Esp32UnknownState *s = ESP32_UNKNOWN(opaque); + return r; +} + +static void esp32_unknown_write(void *opaque, hwaddr addr, + uint64_t value, unsigned int size) +{ + addr += 0x3ff00000; + // Esp32UnknownState *s = ESP32_UNKNOWN(opaque); + printf("unknown write for %016lX, setting to %ld (size=%d)\n", addr, value, size); + +} + +static const MemoryRegionOps esp32_unknown_ops = { + .read = esp32_unknown_read, + .write = esp32_unknown_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_unknown_init(Object *obj) +{ + Esp32UnknownState *s = ESP32_UNKNOWN(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + memory_region_init_io(&s->iomem, obj, &esp32_unknown_ops, s, + TYPE_ESP32_UNKNOWN, 0x80000); + sysbus_init_mmio(sbd, &s->iomem); +} + +static const TypeInfo esp32_unknown_info = { + .name = TYPE_ESP32_UNKNOWN, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32UnknownState), + .instance_init = esp32_unknown_init, +}; + +static void esp32_unknown_register_types(void) +{ + type_register_static(&esp32_unknown_info); +} + +type_init(esp32_unknown_register_types) diff --git a/hw/misc/esp32_wifi.c b/hw/misc/esp32_wifi.c new file mode 100644 index 000000000000..d723c7ee2ebe --- /dev/null +++ b/hw/misc/esp32_wifi.c @@ -0,0 +1,173 @@ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" +#include "sysemu/sysemu.h" +#include "hw/hw.h" +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_wifi.h" +#include "exec/address-spaces.h" +#include "esp32_wlan_packet.h" +#include "hw/qdev-properties.h" + +#define DEBUG 0 + +static uint64_t esp32_wifi_read(void *opaque, hwaddr addr, unsigned int size) +{ + + Esp32WifiState *s = ESP32_WIFI(opaque); + uint32_t r = s->mem[addr/4]; + + switch(addr) { + case A_WIFI_DMA_IN_STATUS: + r=0; + break; + case A_WIFI_DMA_INT_STATUS: + case A_WIFI_DMA_INT_CLR: + r=s->raw_interrupt; + break; + case A_WIFI_STATUS: + case A_WIFI_DMA_OUT_STATUS: + r=1; + break; + } + + if(DEBUG) printf("esp32_wifi_read %lx=%x\n",addr,r); + + return r; +} +static void set_interrupt(Esp32WifiState *s, int e) { + s->raw_interrupt |= e; + qemu_set_irq(s->irq, 1); +} + +static void esp32_wifi_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size) { + Esp32WifiState *s = ESP32_WIFI(opaque); + if(DEBUG) printf("esp32_wifi_write %lx=%lx\n",addr, value); + + switch (addr) { + case A_WIFI_DMA_INLINK: + s->dma_inlink_address = value; + break; + case A_WIFI_DMA_INT_CLR: + s->raw_interrupt &= ~value; + if (s->raw_interrupt == 0) + qemu_set_irq(s->irq, 0); + break; + case A_WIFI_DMA_OUTLINK: + if (value & 0xc0000000) { + // do a DMA transfer to the hardware from esp32 memory + mac80211_frame frame; + dma_list_item item; + unsigned memaddr = (0x3ff00000 | (value & 0xfffff)); + address_space_read(&address_space_memory, memaddr, MEMTXATTRS_UNSPECIFIED, &item, 12); + address_space_read(&address_space_memory, item.address, MEMTXATTRS_UNSPECIFIED, &frame, item.length); + // frame from esp32 to ap + frame.frame_length=item.length; + frame.next_frame=0; + Esp32_WLAN_handle_frame(s, &frame); + set_interrupt(s, 0x80); + } + } + s->mem[addr/4]=value; +} + +static int match_mac_address(uint8_t *a1,uint8_t *a2) { + if(!memcmp(a1,a2,6)) return 1; + if(!memcmp(a1,BROADCAST,6)) return 1; + return 0; +} + +// frame from QEMU to ESP32 +void Esp32_sendFrame(Esp32WifiState *s, mac80211_frame *frame, int length, int signal_strength) { + + if(s->dma_inlink_address == 0) { + return; + } + uint8_t header[28+length]; + wifi_pkt_rx_ctrl_t *pkt=(wifi_pkt_rx_ctrl_t *)header; + *pkt=(wifi_pkt_rx_ctrl_t){ + .rssi=(signal_strength+(rand()%10)+96), + .rate=11, + .sig_len=length, + .sig_len_copy=length, + .legacy_length=length, + .noise_floor=-97, + .channel=esp32_wifi_channel, + .timestamp=qemu_clock_get_ns(QEMU_CLOCK_REALTIME)/1000, + }; + // These 4 bits are set if the mac addresses previously stored at 0x40 and 0x48 + // match the destination or bssid addresses in the frame + if(match_mac_address(frame->receiver_address,(uint8_t *)s->mem+0x40)) + pkt->damatch0=1; + if(match_mac_address(frame->receiver_address,(uint8_t *)s->mem+0x48)) + pkt->damatch1=1; + if(match_mac_address(frame->address_3,(uint8_t *)s->mem+0x40)) + pkt->bssidmatch0=1; + if(match_mac_address(frame->address_3,(uint8_t *)s->mem+0x48)) + pkt->bssidmatch1=1; + //printf("...%x %x\n",header[3],frame->receiver_address[0]); + + memcpy(header+28, frame, length); + length += 28; + // do a DMA transfer from the hardware to esp32 memory + dma_list_item item; + address_space_read(&address_space_memory, s->dma_inlink_address, MEMTXATTRS_UNSPECIFIED, &item, 12); + address_space_write(&address_space_memory, item.address, MEMTXATTRS_UNSPECIFIED, header, length); + item.length=length; + item.eof=1; + address_space_write(&address_space_memory, s->dma_inlink_address, MEMTXATTRS_UNSPECIFIED,&item,4); + s->dma_inlink_address=item.next; + set_interrupt(s, 0x1000024); +} + +static const MemoryRegionOps esp32_wifi_ops = { + .read = esp32_wifi_read, + .write = esp32_wifi_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void esp32_wifi_realize(DeviceState *dev, Error **errp) +{ + Esp32WifiState *s = ESP32_WIFI(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + s->dma_inlink_address = 0; + + memory_region_init_io(&s->iomem, OBJECT(dev), &esp32_wifi_ops, s, + TYPE_ESP32_WIFI, 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->irq); + memset(s->mem,0,sizeof(s->mem)); + Esp32_WLAN_setup_ap(dev, s); + +} +static Property esp32_wifi_properties[] = { + DEFINE_NIC_PROPERTIES(Esp32WifiState, conf), + DEFINE_PROP_END_OF_LIST(), +}; +static void esp32_wifi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = esp32_wifi_realize; + set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->desc = "Esp32 WiFi"; + device_class_set_props(dc, esp32_wifi_properties); +} + + +static const TypeInfo esp32_wifi_info = { + .name = TYPE_ESP32_WIFI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Esp32WifiState), + .class_init = esp32_wifi_class_init, +}; + +static void esp32_wifi_register_types(void) +{ + type_register_static(&esp32_wifi_info); +} + +type_init(esp32_wifi_register_types) diff --git a/hw/misc/esp32_wifi_ap.c b/hw/misc/esp32_wifi_ap.c new file mode 100644 index 000000000000..5892d82bd29c --- /dev/null +++ b/hw/misc/esp32_wifi_ap.c @@ -0,0 +1,410 @@ +/** + * QEMU WLAN access point emulation + * + * Copyright (c) 2008 Clemens Kolbitsch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Modifications: + * 2008-February-24 Clemens Kolbitsch : + * New implementation based on ne2000.c + * 18/1/22 Martin Johnson : Modified for esp32 wifi emulation + */ + +#include "qemu/osdep.h" +#include "net/net.h" +#include "qemu/timer.h" + +#include "hw/misc/esp32_wifi.h" +#include "esp32_wlan.h" +#include "esp32_wlan_packet.h" + +// 50ms between beacons +#define BEACON_TIME 50000000 +#define INTER_FRAME_TIME 5000000 +#define DEBUG 1 +#define DEBUG_DUMPFRAMES 1 + +// channel 12, 13 and 14 aren't scanned with probe requests, but by listening to beacons +// likely because those channels aren't freely licensed in all countries +access_point_info access_points[]={ + {"Open Wifi",4,-40,{0x10,0x01,0x00,0xc4,0x0a,0x51}}, + {"meshtest",1,-25,{0x10,0x01,0x00,0xc4,0x0a,0x50}}, + {"Zeus WPI",12,-25,{0x10,0x01,0x00,0xc4,0x0a,0x56}} +}; + +int nb_aps=sizeof(access_points)/sizeof(access_point_info); + +static void Esp32_WLAN_beacon_timer(void *opaque) +{ + struct mac80211_frame *frame; + Esp32WifiState *s = (Esp32WifiState *)opaque; + + // only send a beacon if we are an access point + if(s->ap_state!=Esp32_WLAN__STATE_STA_ASSOCIATED) { + if (access_points[s->beacon_ap].channel==esp32_wifi_channel) { + printf("QEMU: sending beacon for AP %s\n", access_points[s->beacon_ap].ssid); + memcpy(s->ap_macaddr,access_points[s->beacon_ap].mac_address,6); + frame = Esp32_WLAN_create_beacon_frame(&access_points[s->beacon_ap]); + memcpy(frame->receiver_address, BROADCAST, 6); + memcpy(frame->transmitter_address, s->ap_macaddr, 6); + memcpy(frame->address_3, s->ap_macaddr, 6); + Esp32_WLAN_init_ap_frame(s, frame); + Esp32_WLAN_insert_frame(s, frame); + } + s->beacon_ap=(s->beacon_ap+1)%nb_aps; + } + timer_mod(s->beacon_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + BEACON_TIME); +} + +static void Esp32_WLAN_inject_timer(void *opaque) +{ + Esp32WifiState *s = (Esp32WifiState *)opaque; + struct mac80211_frame *frame; + + frame = s->inject_queue; + if (frame) { + // remove from queue + s->inject_queue_size--; + s->inject_queue = frame->next_frame; + Esp32_sendFrame(s, (void *)frame, frame->frame_length,frame->signal_strength); + free(frame); + } + if (s->inject_queue_size > 0) { + // there are more packets... schedule + // the timer for sending them as well + timer_mod(s->inject_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + INTER_FRAME_TIME); + } else { + // we wait until a new packet schedules + // us again + s->inject_timer_running = 0; + } + +} + +static void macprint(uint8_t *p, const char * name) { + printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n",name, p[0],p[1],p[2],p[3],p[4],p[5]); +} + +static void infoprint(struct mac80211_frame *frame) { + if(DEBUG_DUMPFRAMES) { + printf("Frame Info type=%d subtype=%d to_ds=%d from_ds=%d duration=%d frame_length=%d\n",frame->frame_control.type,frame->frame_control.sub_type, frame->frame_control.to_ds,frame->frame_control.from_ds, frame->duration_id, frame->frame_length); + macprint(frame->receiver_address, "receiver "); + macprint(frame->transmitter_address,"transmitter"); + macprint(frame->address_3, "3rd address"); + uint8_t *b=(uint8_t *)frame; + for(int i=0;iframe_length;i++) { + if((i%16)==0) printf("\n%04x: ",i); + printf("%02x ",b[i]); + } + printf("\n"); + } +} + +void Esp32_WLAN_insert_frame(Esp32WifiState *s, struct mac80211_frame *frame) +{ + struct mac80211_frame *i_frame; + + insertCRC(frame); + if(DEBUG) printf("QEMU: sent frame (qemu AP -> ESP32) type=%d subtype=%d\n",frame->frame_control.type,frame->frame_control.sub_type); + infoprint(frame); + s->inject_queue_size++; + i_frame = s->inject_queue; + if (!i_frame) { + s->inject_queue = frame; + } else { + while (i_frame->next_frame) { + i_frame = i_frame->next_frame; + } + i_frame->next_frame = frame; + } + + if (!s->inject_timer_running) { + // if the injection timer is not + // running currently, let's schedule + // one run... + s->inject_timer_running = 1; + timer_mod(s->inject_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + INTER_FRAME_TIME); + } + +} + +static _Bool Esp32_WLAN_can_receive(NetClientState *ncs) +{ + Esp32WifiState *s = qemu_get_nic_opaque(ncs); + + if (s->ap_state != Esp32_WLAN__STATE_ASSOCIATED && s->ap_state != Esp32_WLAN__STATE_STA_ASSOCIATED) { + // we are currently not connected + // to the access point + return 0; + } + if (s->inject_queue_size > Esp32_WLAN__MAX_INJECT_QUEUE_SIZE) { + // overload, please give me some time... + return 0; + } + + return 1; +} + +static ssize_t Esp32_WLAN_receive(NetClientState *ncs, + const uint8_t *buf, size_t size) +{ + Esp32WifiState *s = qemu_get_nic_opaque(ncs); + struct mac80211_frame *frame; + if (!Esp32_WLAN_can_receive(ncs)) { + // this should not happen, but in + // case it does, let's simply drop + // the packet + return -1; + } + + if (!s) { + return -1; + } + /* + * A 802.3 packet comes from the qemu network. The + * access points turns it into a 802.11 frame and + * forwards it to the wireless device + */ + frame = Esp32_WLAN_create_data_packet(s, buf, size); + if (frame) { + /* send message to ESP32 AP */ + if(s->ap_state == Esp32_WLAN__STATE_STA_ASSOCIATED) { + printf("QEMU: Esp32_WLAN_create_data_packet not yet implemented for STA!"); + frame->frame_control.to_ds = 1; + frame->frame_control.from_ds = 0; + memcpy(frame->receiver_address, s->ap_macaddr, 6); // ? + // TODO implement setting all 3 802.11 MAC addresses + } + else { // send message to ESP32 station + frame->frame_control.to_ds = 0; + frame->frame_control.from_ds = 1; + memcpy(frame->receiver_address, &buf[0], 6); + memcpy(frame->transmitter_address, s->associated_ap_macaddr, 6); + memcpy(frame->address_3, &buf[6], 6); // source address + } + Esp32_WLAN_init_ap_frame(s, frame); + Esp32_WLAN_insert_frame(s, frame); + } + return size; +} +static void Esp32_WLAN_cleanup(NetClientState *ncs) { } + +static NetClientInfo net_info = { + .type = NET_CLIENT_DRIVER_NIC, + .size = sizeof(NICState), + .can_receive = Esp32_WLAN_can_receive, + .receive = Esp32_WLAN_receive, + .cleanup = Esp32_WLAN_cleanup, +}; + +void Esp32_WLAN_setup_ap(DeviceState *dev,Esp32WifiState *s) { + + s->ap_state = Esp32_WLAN__STATE_NOT_AUTHENTICATED; + s->beacon_ap=0; + memcpy(s->ap_macaddr,(uint8_t[]){0x01,0x13,0x46,0xbf,0x31,0x50},sizeof(s->ap_macaddr)); + memcpy(s->macaddr,(uint8_t[]){0x10,0x01,0x00,0xc4,0x0a,0x24},sizeof(s->macaddr)); + + s->inject_timer_running = 0; + s->inject_sequence_number = 0; + + s->inject_queue = NULL; + s->inject_queue_size = 0; + + s->beacon_timer = timer_new_ns(QEMU_CLOCK_REALTIME, Esp32_WLAN_beacon_timer, s); + timer_mod(s->beacon_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME)+100000000); + + // setup the timer but only schedule + // it when necessary... + s->inject_timer = timer_new_ns(QEMU_CLOCK_REALTIME, Esp32_WLAN_inject_timer, s); + + s->nic = qemu_new_nic(&net_info, &s->conf, object_get_typename(OBJECT(s)), dev->id, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->macaddr); +} + +static void send_single_frame(Esp32WifiState *s, struct mac80211_frame *frame, struct mac80211_frame *reply) { + reply->sequence_control.sequence_number = s->inject_sequence_number++ +0x730; + reply->signal_strength=-10; + + if(frame) { + memcpy(reply->receiver_address, frame->transmitter_address, 6); + memcpy(reply->transmitter_address, s->macaddr, 6); + memcpy(reply->address_3, frame->transmitter_address, 6); + } + + Esp32_WLAN_insert_frame(s, reply); +} +void Esp32_WLAN_handle_frame(Esp32WifiState *s, struct mac80211_frame *frame) +{ + struct mac80211_frame *reply = NULL; + static access_point_info dummy_ap={0}; + char ssid[64]; + unsigned long ethernet_frame_size; + unsigned char ethernet_frame[1518] = {0}; + if(DEBUG) + printf("QEMU: received frame (esp32 -> qemu) type=%d subtype=%d chan=%d to_ds=%d from_ds=%d state=%d\n",frame->frame_control.type, frame->frame_control.sub_type, esp32_wifi_channel, frame->frame_control.to_ds, frame->frame_control.from_ds, s->ap_state); + infoprint(frame); + access_point_info *ap_info=0; + for (int i=0;iframe_control.type == IEEE80211_TYPE_MGT) { + switch(frame->frame_control.sub_type) { + case IEEE80211_TYPE_MGT_SUBTYPE_BEACON: + if(s->ap_state==Esp32_WLAN__STATE_NOT_AUTHENTICATED || s->ap_state==Esp32_WLAN__STATE_AUTHENTICATED) { + strncpy(ssid,(char *)frame->data_and_fcs+14,frame->data_and_fcs[13]); + if(DEBUG) printf("QEMU: beacon from %s\n",ssid); + dummy_ap.ssid=ssid; + s->ap_state=Esp32_WLAN__STATE_STA_NOT_AUTHENTICATED; + send_single_frame(s,frame,Esp32_WLAN_create_probe_request(&dummy_ap)); + } + break; + case IEEE80211_TYPE_MGT_SUBTYPE_PROBE_RESP: + ap_info=&dummy_ap; + strncpy(ssid,(char *)frame->data_and_fcs+14,frame->data_and_fcs[13]); + if(DEBUG) printf("QEMU: probe resp from %s\n",ssid); + dummy_ap.ssid=ssid; + s->ap_state=Esp32_WLAN__STATE_STA_NOT_AUTHENTICATED; + send_single_frame(s,frame,Esp32_WLAN_create_deauthentication()); + send_single_frame(s,frame,Esp32_WLAN_create_authentication_request()); + break; + case IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_RESP: + if(DEBUG) printf("QEMU: assoc resp\n"); + mac80211_frame *frame1=Esp32_WLAN_create_dhcp_discover(); + memcpy(frame1->address_3,BROADCAST,6); + memcpy(frame1->transmitter_address,frame->receiver_address,6); + memcpy(frame1->receiver_address,frame->transmitter_address,6); + send_single_frame(s,0,frame1); + s->ap_state=Esp32_WLAN__STATE_STA_DHCP; + break; + case IEEE80211_TYPE_MGT_SUBTYPE_DISASSOCIATION: + DEBUG_PRINT_AP(("QEMU: Received disassociation!\n")); + send_single_frame(s,frame,Esp32_WLAN_create_disassociation()); + if (s->ap_state == Esp32_WLAN__STATE_ASSOCIATED || s->ap_state == Esp32_WLAN__STATE_STA_ASSOCIATED) { + s->ap_state = Esp32_WLAN__STATE_AUTHENTICATED; + } + break; + case IEEE80211_TYPE_MGT_SUBTYPE_DEAUTHENTICATION: + DEBUG_PRINT_AP(("QEMU: Received deauthentication!\n")); + //reply = Esp32_WLAN_create_authentication_response(ap_info); + if (s->ap_state == Esp32_WLAN__STATE_AUTHENTICATED) { + s->ap_state = Esp32_WLAN__STATE_NOT_AUTHENTICATED; + } + break; + case IEEE80211_TYPE_MGT_SUBTYPE_AUTHENTICATION: + if(frame->data_and_fcs[2]==2) { // response + DEBUG_PRINT_AP(("QEMU: Received authentication response!\n")); + send_single_frame(s,frame,Esp32_WLAN_create_association_request(&dummy_ap)); + } + break; + } + if(ap_info) { + memcpy(s->ap_macaddr, ap_info->mac_address, 6); + switch(frame->frame_control.sub_type) { + case IEEE80211_TYPE_MGT_SUBTYPE_PROBE_REQ: + DEBUG_PRINT_AP(("QEMU: Received probe request!\n")); + reply = Esp32_WLAN_create_probe_response(ap_info); + break; + case IEEE80211_TYPE_MGT_SUBTYPE_AUTHENTICATION: + if(frame->data_and_fcs[2]==1) { // request + DEBUG_PRINT_AP(("QEMU: Received authentication request!\n")); + reply = Esp32_WLAN_create_authentication_response(ap_info); + if (s->ap_state == Esp32_WLAN__STATE_NOT_AUTHENTICATED) { + s->ap_state = Esp32_WLAN__STATE_AUTHENTICATED; + } + } + break; + case IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_REQ: + DEBUG_PRINT_AP(("QEMU: Received association request!\n")); + reply = Esp32_WLAN_create_association_response(ap_info); + if (s->ap_state == Esp32_WLAN__STATE_AUTHENTICATED) { + s->ap_state = Esp32_WLAN__STATE_ASSOCIATED; + memcpy(s->associated_ap_macaddr,s->ap_macaddr,6); + } + break; + } + if (reply) { + reply->signal_strength=ap_info->sigstrength; + memcpy(reply->receiver_address, frame->transmitter_address, 6); + memcpy(reply->transmitter_address, s->ap_macaddr, 6); + memcpy(reply->address_3, s->ap_macaddr, 6); + Esp32_WLAN_init_ap_frame(s, reply); + Esp32_WLAN_insert_frame(s, reply); + } + } + } + if ((frame->frame_control.type == IEEE80211_TYPE_DATA) && + (frame->frame_control.sub_type == IEEE80211_TYPE_DATA_SUBTYPE_DATA)) { + if(s->ap_state == Esp32_WLAN__STATE_STA_DHCP) { + printf("QEMU: STA DHCP not implemented yet\n"); + dhcp_request_t *req=(dhcp_request_t *)&frame->data_and_fcs[8]; + // check for a dhcp offer + if(req->dhcp.bp_options[0]==0x35 && req->dhcp.bp_options[2]==0x2) { + mac80211_frame *frame1=Esp32_WLAN_create_dhcp_request(req->dhcp.yiaddr); + memcpy(frame1->address_3,BROADCAST,6); + memcpy(frame1->transmitter_address,s->macaddr,6); + memcpy(frame1->receiver_address,frame->transmitter_address,6); + send_single_frame(s,0,frame1); + memcpy(s->ap_macaddr,(uint8_t[]){0x10,0x01,0x00,0xc4,0x0a,0x25},sizeof(s->ap_macaddr)); + memcpy(s->macaddr,(uint8_t[]){0x10,0x01,0x00,0xc4,0x0a,0x24},sizeof(s->macaddr)); + memcpy(s->associated_ap_macaddr,s->ap_macaddr,sizeof(s->ap_macaddr)); + s->ap_state=Esp32_WLAN__STATE_STA_ASSOCIATED; + } + } else if (s->ap_state == Esp32_WLAN__STATE_ASSOCIATED) { + // ESP32 to QEMU + /* + * The access point uses the 802.11 frame + * and sends a 802.3 frame into the network... + * This packet is then understandable by + * qemu-slirp + * + * If we ever want the access point to offer + * some services, it can be added here!! + */ + // ethernet header type + ethernet_frame[12] = frame->data_and_fcs[6]; + ethernet_frame[13] = frame->data_and_fcs[7]; + + // the originator the packet is the station who sent the frame + memcpy(ðernet_frame[6], frame->transmitter_address, 6); + + // in case of to_ds = 1 and from_ds = 0, the third address is the destination address + memcpy(ðernet_frame[0], frame->address_3, 6); + + ethernet_frame_size = frame->frame_length - 22; + + // limit data to max length of ethernet frame + if (ethernet_frame_size > (sizeof(ethernet_frame) - 14)) { + ethernet_frame_size = (sizeof(ethernet_frame) - 14); + } + + // set ethernet data + memcpy(ðernet_frame[14], &frame->data_and_fcs[8], ethernet_frame_size); + + // send frame + qemu_send_packet(qemu_get_queue(s->nic), ethernet_frame, ethernet_frame_size); + } else if (s->ap_state == Esp32_WLAN__STATE_STA_ASSOCIATED) { + printf("QEMU: STA DATA, NOT IMPLEMENTED YET\n"); + } + } +} diff --git a/hw/misc/esp32_wlan.h b/hw/misc/esp32_wlan.h new file mode 100644 index 000000000000..ce55120912b0 --- /dev/null +++ b/hw/misc/esp32_wlan.h @@ -0,0 +1,226 @@ +/** + * QEMU WLAN device emulation + * + * Copyright (c) 2008 Clemens Kolbitsch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Modifications: + * 2008-February-24 Clemens Kolbitsch : + * New implementation based on ne2000.c + * 18/1/22 Martin Johnson : Modified for esp32 wifi emulation + * + */ + +#ifndef esp32_wlan_h +#define esp32_wlan_h 1 + + +#define DEBUG_Esp32_WLAN + +#ifdef DEBUG_Esp32_WLAN +#define DEBUG_PRINT_AP(x) \ + do { \ + struct timeval __tt; \ + gettimeofday(&__tt, NULL); \ + printf("%u:%u ", (unsigned)__tt.tv_sec, (unsigned)__tt.tv_usec); \ + printf x ;\ + } while (0) +#else +#define DEBUG_PRINT_AP(x) +#endif + + +#define IEEE80211_IDLE 0xff + +#define IEEE80211_TYPE_MGT 0x00 +#define IEEE80211_TYPE_CTL 0x01 +#define IEEE80211_TYPE_DATA 0x02 + +#define IEEE80211_TYPE_MGT_SUBTYPE_BEACON 0x08 +#define IEEE80211_TYPE_MGT_SUBTYPE_ACTION 0x0d +#define IEEE80211_TYPE_MGT_SUBTYPE_PROBE_REQ 0x04 +#define IEEE80211_TYPE_MGT_SUBTYPE_PROBE_RESP 0x05 +#define IEEE80211_TYPE_MGT_SUBTYPE_AUTHENTICATION 0x0b +#define IEEE80211_TYPE_MGT_SUBTYPE_DEAUTHENTICATION 0x0c +#define IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_REQ 0x00 +#define IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_RESP 0x01 +#define IEEE80211_TYPE_MGT_SUBTYPE_DISASSOCIATION 0x0a + +#define IEEE80211_TYPE_CTL_SUBTYPE_ACK 0x0d + +#define IEEE80211_TYPE_DATA_SUBTYPE_DATA 0x00 + +#define IEEE80211_BEACON_PARAM_SSID 0x00 +#define IEEE80211_BEACON_PARAM_RATES 0x01 +#define IEEE80211_BEACON_PARAM_CHANNEL 0x03 +#define IEEE80211_BEACON_PARAM_EXTENDED_RATES 0x32 +#define IEEE80211_BEACON_PARAM_TIM 0x05 + + +#define IEEE80211_HEADER_SIZE 24 + +typedef struct beacon_info_t { + uint64_t timestamp; + uint16_t interval; + uint16_t capability; +} QEMU_PACKED beacon_info_t; + +typedef uint8_t macaddr_t[6]; + +#define BROADCAST (uint8_t[]){0xff,0xff,0xff,0xff,0xff,0xff} + +typedef struct mac80211_frame { + struct mac80211_frame_control { + unsigned protocol_version : 2; + unsigned type : 2; + unsigned sub_type : 4; + unsigned to_ds : 1; + unsigned from_ds : 1; + unsigned _flags:6; + } QEMU_PACKED frame_control; + uint16_t duration_id; + macaddr_t receiver_address; + macaddr_t transmitter_address; + macaddr_t address_3; + struct mac80211_sequence_control { + unsigned fragment_number : 4; + unsigned sequence_number : 12; + } QEMU_PACKED sequence_control; + // variable length, 2312 byte plus 4 byte frame-checksum + union { + uint8_t data_and_fcs[2316]; + beacon_info_t beacon_info; + }; + unsigned int frame_length; + int signal_strength; + int pos; + struct mac80211_frame *next_frame; +} QEMU_PACKED mac80211_frame; + +typedef struct access_point_info { + const char *ssid; + int channel; + int sigstrength; + macaddr_t mac_address; +} access_point_info; + +enum esp32_ap_state { + Esp32_WLAN__STATE_NOT_AUTHENTICATED, + Esp32_WLAN__STATE_AUTHENTICATED, + Esp32_WLAN__STATE_ASSOCIATED, + Esp32_WLAN__STATE_STA_NOT_AUTHENTICATED, + Esp32_WLAN__STATE_STA_AUTHENTICATED, + Esp32_WLAN__STATE_STA_ASSOCIATED, + Esp32_WLAN__STATE_STA_DHCP, +}; + +#define Esp32_WLAN__MAX_INJECT_QUEUE_SIZE 20 + +typedef struct { + signed rssi:8; /**< Received Signal Strength Indicator(RSSI) of packet. unit: dBm */ + unsigned rate:5; /**< PHY rate encoding of the packet. Only valid for non HT(11bg) packet */ + unsigned :1; /**< reserved */ + unsigned sig_mode:2; /**< 0: non HT(11bg) packet; 1: HT(11n) packet; 3: VHT(11ac) packet */ + unsigned legacy_length:12; /**< copy of the length */ + unsigned damatch0:1; /* destination matches address0 */ + unsigned damatch1:1; /* destination matches address1 */ + unsigned bssidmatch0:1; /* bssid matches address0 */ + unsigned bssidmatch1:1; /* bssid matches address1 */ + unsigned mcs:7; /**< Modulation Coding Scheme. If is HT(11n) packet, shows the modulation, range from 0 to 76(MSC0 ~ MCS76) */ + unsigned cwb:1; /**< Channel Bandwidth of the packet. 0: 20MHz; 1: 40MHz */ + unsigned :16; /**< reserved */ + unsigned smoothing:1; /**< reserved */ + unsigned not_sounding:1; /**< reserved */ + unsigned :1; /**< reserved */ + unsigned aggregation:1; /**< Aggregation. 0: MPDU packet; 1: AMPDU packet */ + unsigned stbc:2; /**< Space Time Block Code(STBC). 0: non STBC packet; 1: STBC packet */ + unsigned fec_coding:1; /**< Flag is set for 11n packets which are LDPC */ + unsigned sgi:1; /**< Short Guide Interval(SGI). 0: Long GI; 1: Short GI */ + signed noise_floor:8; /**< noise floor of Radio Frequency Module(RF). unit: 0.25dBm*/ + unsigned ampdu_cnt:8; /**< ampdu cnt */ + unsigned channel:4; /**< primary channel on which this packet is received */ + unsigned secondary_channel:4; /**< secondary channel on which this packet is received. 0: none; 1: above; 2: below */ + unsigned :8; /**< reserved */ + unsigned timestamp:32; /**< timestamp. The local time when this packet is received. It is precise only if modem sleep or light sleep is not enabled. unit: microsecond */ + unsigned :32; /**< reserved */ + unsigned :31; /**< reserved */ + unsigned ant:1; /**< antenna number from which this packet is received. 0: WiFi antenna 0; 1: WiFi antenna 1 */ + unsigned sig_len:12; /**< length of packet including Frame Check Sequence(FCS) */ + unsigned sig_len_copy:12; /**< another copy of the length */ + unsigned rx_state:8; /**< state of the packet. 0: no error; others: error numbers which are not public */ +} QEMU_PACKED wifi_pkt_rx_ctrl_t; + +extern int esp32_wifi_channel; + +typedef uint8_t ip4_t[4]; + +#define DHCP_CHADDR_LEN 16 +#define DHCP_SNAME_LEN 64 +#define DHCP_FILE_LEN 128 + +typedef struct ip_header_t { + uint8_t version_size; + uint8_t dscp_ecn; + uint8_t len_h; + uint8_t len_l; + uint32_t z; + uint8_t ttl; + uint8_t protocol; + uint16_t checksum; + ip4_t source_ip; + ip4_t dest_ip; +}ip_header_t ; + +typedef struct udp_header_t { + uint8_t src_port_h; + uint8_t src_port_l; + uint8_t dest_port_h; + uint8_t dest_port_l; + uint8_t len_h; + uint8_t len_l; + uint16_t checksum; +} udp_header_t; + +typedef struct dhcp_t { + uint8_t opcode; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + ip4_t ciaddr; + ip4_t yiaddr; + ip4_t siaddr; + ip4_t giaddr; + uint8_t chaddr[DHCP_CHADDR_LEN]; + char bp_sname[DHCP_SNAME_LEN]; + char bp_file[DHCP_FILE_LEN]; + uint32_t magic_cookie; + uint8_t bp_options[0]; +} dhcp_t; + +typedef struct dhcp_request_t { + ip_header_t ipheader; + udp_header_t udpheader; + dhcp_t dhcp; +} dhcp_request_t; + +#endif // esp32_wlan_h diff --git a/hw/misc/esp32_wlan_packet.c b/hw/misc/esp32_wlan_packet.c new file mode 100644 index 000000000000..ca842dd21504 --- /dev/null +++ b/hw/misc/esp32_wlan_packet.c @@ -0,0 +1,283 @@ +/** + * QEMU WLAN access point emulation + * + * Copyright (c) 2008 Clemens Kolbitsch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Modifications: + * 2008-February-24 Clemens Kolbitsch : + * New implementation based on ne2000.c + * 18/1/22 Martin Johnson : Modified for esp32 wifi emulation + */ + +#include "qemu/osdep.h" + +#include "net/net.h" + +#include "esp32_wlan.h" +#include "esp32_wlan_packet.h" + +// the frame checksum isn't used so just put zero in there. +void insertCRC(mac80211_frame *frame) { + unsigned long crc; + unsigned char *fcs = (unsigned char *)frame; + crc = 0; + memcpy(fcs+frame->frame_length, &crc, 4); + frame->frame_length += 4; +} + +static void add_byte(mac80211_frame *frame, uint8_t data) { + frame->data_and_fcs[frame->pos++]=data; + frame->frame_length=IEEE80211_HEADER_SIZE+frame->pos; +} + +static void add_data(mac80211_frame *frame, int len,uint8_t *data) { + for(int i=0;isequence_control.sequence_number = s->inject_sequence_number++; +} + +static mac80211_frame *new_frame(unsigned type, unsigned subtype) { + mac80211_frame *frame = (mac80211_frame *)malloc(sizeof(mac80211_frame)); + frame->next_frame = NULL; + frame->frame_control.protocol_version = 0; + frame->frame_control.type = type; + frame->frame_control.sub_type = subtype; + frame->frame_control._flags = 0; + frame->frame_control.from_ds = 0; + frame->frame_control.to_ds = 0; + frame->duration_id = 314; + frame->sequence_control.fragment_number = 0; + frame->pos=0; + return frame; +} + +static void add_rates(mac80211_frame *frame) { + add_tag(frame,IEEE80211_BEACON_PARAM_RATES,8,(uint8_t[]){0x8b,0x96,0x82,0x84,0x0c,0x18,0x30,0x60}); + add_tag(frame,IEEE80211_BEACON_PARAM_EXTENDED_RATES,4,(uint8_t[]){0x6c,0x12,0x24,0x48}); +} + +static void add_ssid(mac80211_frame *frame, const char *ssid) { + add_tag(frame,IEEE80211_BEACON_PARAM_SSID,strlen(ssid),(uint8_t *)ssid); +} + +mac80211_frame *Esp32_WLAN_create_beacon_frame(access_point_info *ap) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_BEACON); + frame->signal_strength=ap->sigstrength; + frame->beacon_info.timestamp=qemu_clock_get_ns(QEMU_CLOCK_REALTIME)/1000; + frame->beacon_info.interval=1000; + frame->beacon_info.capability=1; + frame->pos=12; + add_ssid(frame,ap->ssid); + add_rates(frame); + add_tag(frame,IEEE80211_BEACON_PARAM_CHANNEL,1,(uint8_t[]){ap->channel}); + add_tag(frame,IEEE80211_BEACON_PARAM_TIM,4,(uint8_t[]){4,1,3,0,0}); + return frame; +} + +static uint16_t in_cksum(uint16_t *addr, int len) { + int sum = 0; + uint16_t answer = 0; + uint16_t *w = addr; + int nleft = len; + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + /* mop up an odd byte, if necessary */ + if (nleft == 1) { + *(uint8_t *)(&answer) = *(uint8_t *) w; + sum += answer; + } + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return (answer); +} + +static mac80211_frame *Esp32_WLAN_create_dhcp_frame(int cmd_size, uint8_t dhcp_commands[]) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_DATA,IEEE80211_TYPE_DATA_SUBTYPE_DATA); + frame->frame_control.to_ds=1; + add_data(frame,8,(uint8_t[]){ 0xaa, 0xaa ,0x03 ,00 ,00 ,00 ,8 ,00}); + dhcp_request_t req={ + {.version_size=0x45,.ttl=0xff,.protocol=0x11,.dest_ip={0xff,0xff,0xff,0xff}}, + {.src_port_l=0x44,.dest_port_l=0x43}, + {.htype=1,.hlen=6,.xid=0x1d3d00,.chaddr={0x10,0x01,0x00,0xc4,0x0a,0x24}, + .magic_cookie=0x63538263} + }; + int len=sizeof(req)+cmd_size; + req.ipheader.len_h=len>>8; + req.ipheader.len_l=len&0xff; + len=len-sizeof(ip_header_t); + req.udpheader.len_h=len>>8; + req.udpheader.len_l=len&0xff; + req.ipheader.checksum=in_cksum((void *)&req.ipheader,sizeof(ip_header_t)); + add_data(frame,sizeof(req),(uint8_t *)&req); + add_data(frame,cmd_size,dhcp_commands); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_dhcp_request(uint8_t *ip) { + uint8_t dhcp_commands[]={ + 0x35, 1, 3, + 0x39, 2 ,5 ,0xdc , + 0x32, 4, ip[0],ip[1],ip[2],ip[3], + 0x3d, 0x07, 0x01, 0x3c, 0x61, 0x05, 0x0d, 0x99, 0x24, + 0x37, 0x04, 0x01, 0x03, 0x1c, 0x06, + 0xff, 0, 0 + }; + return Esp32_WLAN_create_dhcp_frame(sizeof(dhcp_commands),dhcp_commands); +} + +mac80211_frame *Esp32_WLAN_create_dhcp_discover(void) { + uint8_t dhcp_commands[]={ + 0x35, 1, 1, + 0x39, 2 ,5 ,0xdc , + 0x0c ,0x09 ,0x65 ,0x73 ,0x70 ,0x72 ,0x65 ,0x73 ,0x73 ,0x69 ,0x66 , + 0x3d ,0x07, 0x01 ,0x3c ,0x61 ,0x05 ,0x0d ,0x99 ,0x24 , + 0x37 ,0x04 ,0x01 ,0x03 ,0x1c ,0x06 , + 0xff, 0,0 + }; + return Esp32_WLAN_create_dhcp_frame(sizeof(dhcp_commands),dhcp_commands); +} + +mac80211_frame *Esp32_WLAN_create_association_request(access_point_info *ap) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_REQ); + add_data(frame,4,(uint8_t []){0x21,4,3,0}); + add_ssid(frame,ap->ssid); + add_rates(frame); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_ack(void) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_CTL,IEEE80211_TYPE_CTL_SUBTYPE_ACK); + frame->frame_length=10; + return frame; +} + +mac80211_frame *Esp32_WLAN_create_probe_response(access_point_info *ap) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_PROBE_RESP); + frame->beacon_info.timestamp=qemu_clock_get_ns(QEMU_CLOCK_REALTIME)/1000; + frame->beacon_info.interval=1000; + frame->beacon_info.capability=1; + frame->pos=12; + add_ssid(frame,ap->ssid); + add_rates(frame); + add_tag(frame,IEEE80211_BEACON_PARAM_CHANNEL,1,(uint8_t[]){ap->channel}); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_probe_request(access_point_info *ap) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_PROBE_REQ); + memcpy(frame->receiver_address,BROADCAST,6); + memcpy(frame->address_3,BROADCAST,6); + add_ssid(frame,ap->ssid); + add_tag(frame,IEEE80211_BEACON_PARAM_CHANNEL,1,(uint8_t[]){ap->channel}); + add_rates(frame); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_authentication_response(access_point_info *ap) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_AUTHENTICATION); + /* + * Fixed params... typical AP params (6 byte) + * + * They include + * - Authentication Algorithm (here: Open System) + * - Authentication SEQ + * - Status code (successful 0x0) + */ + add_data(frame,6,(uint8_t []){0,0,2,0,0,0}); + add_ssid(frame,ap->ssid); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_authentication_request(void) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_AUTHENTICATION); + /* + * Fixed params... typical AP params (6 byte) + * + * They include + * - Authentication Algorithm (here: Open System) + * - Authentication SEQ + * - Status code (successful 0x0) + */ + //frame->duration_id=0x13a; + add_data(frame,6,(uint8_t []){0,0,1,0,0,0}); + //add_data(frame,11,(uint8_t []){0,0,0,0,0,0,0,0,0,0,0}); + //add_ssid(frame,ap->ssid); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_deauthentication(void) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_DEAUTHENTICATION); + /* + * Insert reason code: + * "Deauthentication because sending STA is leaving" + */ + add_data(frame,2,(uint8_t []){3,0}); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_association_response(access_point_info *ap) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_RESP); + /* + * Fixed params... typical AP params (6 byte) + * + * They include + * - Capability Information + * - Status code (successful 0x0) + * - Association ID + */ + add_data(frame,6,(uint8_t []){33,4,0,0,1,0xc0}); + add_ssid(frame,ap->ssid); + add_rates(frame); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_disassociation(void) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_MGT,IEEE80211_TYPE_MGT_SUBTYPE_DISASSOCIATION); + /* + * Insert reason code: + * "Disassociation because sending STA is leaving" + */ + add_data(frame,2,(uint8_t []){3,0}); + return frame; +} + +mac80211_frame *Esp32_WLAN_create_data_packet(Esp32WifiState *s, const uint8_t *buf, int size) { + mac80211_frame *frame=new_frame(IEEE80211_TYPE_DATA,IEEE80211_TYPE_DATA_SUBTYPE_DATA); + + frame->duration_id = 44; + /* LLC */ + add_data(frame,6,(uint8_t[]){ 0xaa, 0xaa ,0x03 ,0 ,0 ,0}); + memcpy(frame->data_and_fcs+6, buf+12, size-12); + frame->frame_length = IEEE80211_HEADER_SIZE + size-6; + return frame; +} diff --git a/hw/misc/esp32_wlan_packet.h b/hw/misc/esp32_wlan_packet.h new file mode 100644 index 000000000000..241aa7f41199 --- /dev/null +++ b/hw/misc/esp32_wlan_packet.h @@ -0,0 +1,56 @@ +/** + * QEMU WLAN access point emulation + * + * Copyright (c) 2008 Clemens Kolbitsch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Modifications: + * 2008-February-24 Clemens Kolbitsch : + * New implementation based on ne2000.c + * 18/1/22 Martin Johnson : Modified for esp32 wifi emulation + * + */ + +#ifndef esp32_wlan_packet_h +#define esp32_wlan_packet_h 1 + +#include "esp32_wlan.h" +#include "hw/misc/esp32_wifi.h" + +void Esp32_WLAN_init_ap_frame(Esp32WifiState *s, struct mac80211_frame *frame); +int Esp32_WLAN_dumpFrame(struct mac80211_frame *frame, int frame_len, char *filename); +void Esp32_WLAN_insert_frame(Esp32WifiState *s, struct mac80211_frame *frame); +struct mac80211_frame *Esp32_WLAN_create_beacon_frame(access_point_info *ap); +struct mac80211_frame *Esp32_WLAN_create_probe_response(access_point_info *ap); +struct mac80211_frame *Esp32_WLAN_create_probe_request(access_point_info *ap); +struct mac80211_frame *Esp32_WLAN_create_authentication_request(void); +struct mac80211_frame *Esp32_WLAN_create_authentication_response(access_point_info *ap); +struct mac80211_frame *Esp32_WLAN_create_deauthentication(void); +struct mac80211_frame *Esp32_WLAN_create_association_request(access_point_info *ap); +struct mac80211_frame *Esp32_WLAN_create_association_response(access_point_info *ap); +struct mac80211_frame *Esp32_WLAN_create_disassociation(void); +struct mac80211_frame *Esp32_WLAN_create_data_reply(Esp32WifiState *s, struct mac80211_frame *incoming); +struct mac80211_frame *Esp32_WLAN_create_data_packet(Esp32WifiState *s, const uint8_t *buf, int size); +struct mac80211_frame *Esp32_WLAN_create_ack(void); +struct mac80211_frame *Esp32_WLAN_create_dhcp_discover(void); +struct mac80211_frame *Esp32_WLAN_create_dhcp_request(uint8_t *ip); +void insertCRC(mac80211_frame *frame); + +#endif // esp32_wlan_packet_h diff --git a/hw/misc/meson.build b/hw/misc/meson.build index a062aa255368..2f197051f025 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -5,7 +5,7 @@ softmmu_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugexit.c')) softmmu_ss.add(when: 'CONFIG_ISA_TESTDEV', if_true: files('pc-testdev.c')) softmmu_ss.add(when: 'CONFIG_PCA9552', if_true: files('pca9552.c')) softmmu_ss.add(when: 'CONFIG_PCI_TESTDEV', if_true: files('pci-testdev.c')) -softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c')) +softmmu_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c', 'unimp-default.c')) softmmu_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c')) softmmu_ss.add(when: 'CONFIG_LED', if_true: files('led.c')) softmmu_ss.add(when: 'CONFIG_PVPANIC_COMMON', if_true: files('pvpanic.c')) @@ -134,6 +134,13 @@ softmmu_ss.add(when: 'CONFIG_XTENSA_ESP32', if_true: files( 'esp32_aes.c', 'esp32_ledc.c', 'esp32_flash_enc.c', + 'esp32_unknown.c', + 'esp32_ana.c', + 'esp32_wifi.c', + 'esp32_wifi_ap.c', + 'esp32_wlan_packet.c', + 'esp32_phya.c', + 'esp32_fe.c', 'ssi_psram.c' )) softmmu_ss.add(when: 'CONFIG_RISCV_ESP32C3', if_true: files( diff --git a/hw/misc/unimp-default.c b/hw/misc/unimp-default.c new file mode 100644 index 000000000000..8ca733d8e93f --- /dev/null +++ b/hw/misc/unimp-default.c @@ -0,0 +1,101 @@ +/* "Unimplemented" default device + * + * This is a dummy device which accepts and logs all accesses. + * It's useful for stubbing out regions of an SoC or board + * map which correspond to devices that have not yet been + * implemented. This is often sufficient to placate initial + * guest device driver probing such that the system will + * come up. + * + * Copyright Linaro Limited, 2017 + * Written by Peter Maydell + * Modified by redfast00 2023 + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/misc/unimp-default.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qapi/error.h" + +static uint64_t unimp_default_read(void *opaque, hwaddr offset, unsigned size) +{ + UnimplementedDefaultDeviceState *s = UNIMPLEMENTED_DEFAULT_DEVICE(opaque); + + qemu_log_mask(LOG_UNIMP, "%s: unimplemented default device read " + "(size %d, offset 0x%0*" HWADDR_PRIx ")\n", + s->name, size, s->offset_fmt_width, offset); + return s->default_value; +} + +static void unimp_default_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + UnimplementedDefaultDeviceState *s = UNIMPLEMENTED_DEFAULT_DEVICE(opaque); + + qemu_log_mask(LOG_UNIMP, "%s: unimplemented default device write " + "(size %d, offset 0x%0*" HWADDR_PRIx + ", value 0x%0*" PRIx64 ")\n", + s->name, size, s->offset_fmt_width, offset, size << 1, value); +} + +static const MemoryRegionOps unimp_default_ops = { + .read = unimp_default_read, + .write = unimp_default_write, + .impl.min_access_size = 1, + .impl.max_access_size = 8, + .valid.min_access_size = 1, + .valid.max_access_size = 8, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void unimp_default_realize(DeviceState *dev, Error **errp) +{ + UnimplementedDefaultDeviceState *s = UNIMPLEMENTED_DEFAULT_DEVICE(dev); + + if (s->size == 0) { + error_setg(errp, "property 'size' not specified or zero"); + return; + } + + if (s->name == NULL) { + error_setg(errp, "property 'name' not specified"); + return; + } + + s->offset_fmt_width = DIV_ROUND_UP(64 - clz64(s->size - 1), 4); + + memory_region_init_io(&s->iomem, OBJECT(s), &unimp_default_ops, s, + s->name, s->size); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); +} + +static Property unimp_default_properties[] = { + DEFINE_PROP_UINT64("size", UnimplementedDefaultDeviceState, size, 0), + DEFINE_PROP_STRING("name", UnimplementedDefaultDeviceState, name), + DEFINE_PROP_UINT64("default_value", UnimplementedDefaultDeviceState, default_value, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void unimp_default_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = unimp_default_realize; + device_class_set_props(dc, unimp_default_properties); +} + +static const TypeInfo unimp_default_info = { + .name = TYPE_UNIMPLEMENTED_DEFAULT_DEVICE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(UnimplementedDefaultDeviceState), + .class_init = unimp_default_class_init, +}; + +static void unimp_default_register_types(void) +{ + type_register_static(&unimp_default_info); +} + +type_init(unimp_default_register_types) diff --git a/hw/xtensa/esp32.c b/hw/xtensa/esp32.c index 2df6c2e93840..8bd4a41b33c9 100644 --- a/hw/xtensa/esp32.c +++ b/hw/xtensa/esp32.c @@ -20,6 +20,7 @@ #include "hw/i2c/esp32_i2c.h" #include "hw/xtensa/xtensa_memory.h" #include "hw/misc/unimp.h" +#include "hw/misc/unimp-default.h" #include "hw/irq.h" #include "hw/i2c/i2c.h" #include "hw/qdev-properties.h" @@ -185,6 +186,9 @@ static void esp32_soc_reset(DeviceState *dev) if (s->eth) { device_cold_reset(s->eth); } + if (s->wifi_dev) { + device_cold_reset(s->wifi_dev); + } } if (s->requested_reset & ESP32_SOC_RESET_PROCPU) { xtensa_select_static_vectors(&s->cpu[0].env, s->rtc_cntl.stat_vector_sel[0]); @@ -250,11 +254,22 @@ static void esp32_soc_add_periph_device(MemoryRegion *dest, void* dev, hwaddr dp g_free(name); } -static void esp32_soc_add_unimp_device(MemoryRegion *dest, const char* name, hwaddr dport_base_addr, size_t size) +static void esp32_soc_add_periph_device_prio(MemoryRegion *dest, void* dev, hwaddr dport_base_addr, int priority) { - create_unimplemented_device(name, dport_base_addr, size); + MemoryRegion *mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_add_subregion_overlap(dest, dport_base_addr, mr, priority); + MemoryRegion *mr_apb = g_new(MemoryRegion, 1); + char *name = g_strdup_printf("mr-apb-0x%08x", (uint32_t) dport_base_addr); + memory_region_init_alias(mr_apb, OBJECT(dev), name, mr, 0, memory_region_size(mr)); + memory_region_add_subregion_overlap(dest, dport_base_addr - DR_REG_DPORT_APB_BASE + APB_REG_BASE, mr_apb, priority); + g_free(name); +} + +static void esp32_soc_add_unimp_default_device(MemoryRegion *dest, const char* name, hwaddr dport_base_addr, size_t size, uint64_t default_value) +{ + create_unimplemented_default_device(name, dport_base_addr, size, default_value); char * name_apb = g_strdup_printf("%s-apb", name); - create_unimplemented_device(name_apb, dport_base_addr - DR_REG_DPORT_APB_BASE + APB_REG_BASE, size); + create_unimplemented_default_device(name_apb, dport_base_addr - DR_REG_DPORT_APB_BASE + APB_REG_BASE, size, default_value); g_free(name_apb); } @@ -385,6 +400,9 @@ static void esp32_soc_realize(DeviceState *dev, Error **errp) qdev_realize(DEVICE(&s->sha), &s->periph_bus, &error_fatal); esp32_soc_add_periph_device(sys_mem, &s->sha, DR_REG_SHA_BASE); + qdev_realize(DEVICE(&s->unknown), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device_prio(sys_mem, &s->unknown, 0x3ff00000, -1001); + qdev_realize(DEVICE(&s->aes), &s->periph_bus, &error_fatal); esp32_soc_add_periph_device(sys_mem, &s->aes, DR_REG_AES_BASE); @@ -474,6 +492,15 @@ static void esp32_soc_realize(DeviceState *dev, Error **errp) qdev_realize(DEVICE(&s->rng), &s->periph_bus, &error_fatal); esp32_soc_add_periph_device(sys_mem, &s->rng, ESP32_RNG_BASE); + qdev_realize(DEVICE(&s->ana), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->ana, DR_REG_ANA_BASE); + + qdev_realize(DEVICE(&s->phya), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->phya, DR_REG_PHYA_BASE); + + qdev_realize(DEVICE(&s->fe), &s->periph_bus, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &s->fe, DR_REG_FE_BASE); + qdev_realize(DEVICE(&s->efuse), &s->periph_bus, &error_fatal); esp32_soc_add_periph_device(sys_mem, &s->efuse, DR_REG_EFUSE_BASE); sysbus_connect_irq(SYS_BUS_DEVICE(&s->efuse), 0, @@ -494,18 +521,29 @@ static void esp32_soc_realize(DeviceState *dev, Error **errp) sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdmmc), 0, qdev_get_gpio_in(intmatrix_dev, ETS_SDIO_HOST_INTR_SOURCE)); - esp32_soc_add_unimp_device(sys_mem, "esp32.analog", DR_REG_ANA_BASE, 0x1000); - esp32_soc_add_unimp_device(sys_mem, "esp32.rtcio", DR_REG_RTCIO_BASE, 0x400); - esp32_soc_add_unimp_device(sys_mem, "esp32.rtcio", DR_REG_SENS_BASE, 0x400); - esp32_soc_add_unimp_device(sys_mem, "esp32.iomux", DR_REG_IO_MUX_BASE, 0x2000); - esp32_soc_add_unimp_device(sys_mem, "esp32.hinf", DR_REG_HINF_BASE, 0x1000); - esp32_soc_add_unimp_device(sys_mem, "esp32.slc", DR_REG_SLC_BASE, 0x1000); - esp32_soc_add_unimp_device(sys_mem, "esp32.slchost", DR_REG_SLCHOST_BASE, 0x1000); - esp32_soc_add_unimp_device(sys_mem, "esp32.apbctrl", DR_REG_APB_CTRL_BASE, 0x1000); - esp32_soc_add_unimp_device(sys_mem, "esp32.i2s0", DR_REG_I2S_BASE, 0x1000); - esp32_soc_add_unimp_device(sys_mem, "esp32.i2s1", DR_REG_I2S1_BASE, 0x1000); - esp32_soc_add_unimp_device(sys_mem, "esp32.rmt", DR_REG_RMT_BASE, 0x1000); - esp32_soc_add_unimp_device(sys_mem, "esp32.pcnt", DR_REG_PCNT_BASE, 0x1000); + // not mentioned in fork + esp32_soc_add_unimp_default_device(sys_mem, "esp32.pcnt", DR_REG_PCNT_BASE, 0x1000, 0); + + // implemented in fork, still unimplemented here + esp32_soc_add_unimp_default_device(sys_mem, "esp32.rtcio", DR_REG_SENS_BASE, 0x400, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.rmt", DR_REG_RMT_BASE, 0x1000, 0); + + // common + esp32_soc_add_unimp_default_device(sys_mem, "esp32.rtcio", DR_REG_RTCIO_BASE, 0x400, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.iomux", DR_REG_IO_MUX_BASE, 0x2000, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.hinf", DR_REG_HINF_BASE, 0x100, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.slc", DR_REG_SLC_BASE, 0x1000, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.slchost", DR_REG_SLCHOST_BASE, 0x1000, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.apbctrl", DR_REG_APB_CTRL_BASE, 0x1000, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.i2s0", DR_REG_I2S_BASE, 0x1000, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.i2s1", DR_REG_I2S1_BASE, 0x1000, 0); + + // only implemented in fork + esp32_soc_add_unimp_default_device(sys_mem, "esp32.fe2", DR_REG_FE2_BASE, 0x1000, -1); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.chipv7_phy", DR_REG_PHY_BASE, 0x1000, -1); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.chipv7_phyb", DR_REG_WDEV_BASE, 0x1000, 0); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.unknown_wifi", DR_REG_NRX_BASE , 0x1000, -1); + esp32_soc_add_unimp_default_device(sys_mem, "esp32.unknown_wifi1", DR_REG_BB_BASE , 0x1000, -1); /* Emulation of APB_CTRL_DATE_REG, needed for ECO3 revision detection. * This is a small hack to avoid creating a whole new device just to emulate one @@ -598,6 +636,24 @@ static void esp32_soc_init(Object *obj) object_initialize_child(obj, "sha", &s->sha, TYPE_ESP32_SHA); + object_initialize_child(obj, "unknown", &s->unknown, TYPE_ESP32_UNKNOWN); + + object_initialize_child(obj, "ana", &s->ana, TYPE_ESP32_ANA); + + printf("nb_nics=%d\n", nb_nics); + for(int i=0;iwifi, TYPE_ESP32_WIFI); + } + } + object_initialize_child(obj, "fe", &s->fe, TYPE_ESP32_FE); + + object_initialize_child(obj, "phya", &s->phya, TYPE_ESP32_PHYA); + object_initialize_child(obj, "aes", &s->aes, TYPE_ESP32_AES); object_initialize_child(obj, "ledc", &s->ledc, TYPE_ESP32_LEDC); @@ -719,22 +775,33 @@ static void esp32_machine_init_i2c(Esp32SocState *s) static void esp32_machine_init_openeth(Esp32SocState *ss) { SysBusDevice *sbd; - NICInfo *nd = &nd_table[0]; MemoryRegion* sys_mem = get_system_memory(); hwaddr reg_base = DR_REG_EMAC_BASE; hwaddr desc_base = reg_base + 0x400; qemu_irq irq = qdev_get_gpio_in(DEVICE(&ss->intmatrix), ETS_ETH_MAC_INTR_SOURCE); const char* type_openeth = "open_eth"; - if (nd->used && nd->model && strcmp(nd->model, type_openeth) == 0) { - DeviceState* open_eth_dev = qdev_new(type_openeth); - ss->eth = open_eth_dev; - qdev_set_nic_properties(open_eth_dev, nd); - sbd = SYS_BUS_DEVICE(open_eth_dev); - sysbus_realize_and_unref(sbd, &error_fatal); - sysbus_connect_irq(sbd, 0, irq); - memory_region_add_subregion(sys_mem, reg_base, sysbus_mmio_get_region(sbd, 0)); - memory_region_add_subregion(sys_mem, desc_base, sysbus_mmio_get_region(sbd, 1)); + for(int i=0;i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + + if (nd->used && nd->model && strcmp(nd->model, type_openeth) == 0) { + DeviceState* open_eth_dev = qdev_new(type_openeth); + ss->eth = open_eth_dev; + qdev_set_nic_properties(open_eth_dev, nd); + sbd = SYS_BUS_DEVICE(open_eth_dev); + sysbus_realize_and_unref(sbd, &error_fatal); + sysbus_connect_irq(sbd, 0, irq); + memory_region_add_subregion(sys_mem, reg_base, sysbus_mmio_get_region(sbd, 0)); + memory_region_add_subregion(sys_mem, desc_base, sysbus_mmio_get_region(sbd, 1)); + } + else if (nd->used && nd->model && strcmp(nd->model, TYPE_ESP32_WIFI) == 0) { + qdev_set_nic_properties(DEVICE(&ss->wifi), nd); + sbd = SYS_BUS_DEVICE(DEVICE(&ss->wifi)); + sysbus_realize_and_unref(sbd, &error_fatal); + esp32_soc_add_periph_device(sys_mem, &ss->wifi, DR_REG_WIFI_BASE); + sysbus_connect_irq(SYS_BUS_DEVICE(&ss->wifi), 0, + qdev_get_gpio_in(DEVICE(&ss->intmatrix), ETS_WIFI_MAC_INTR_SOURCE)); + } } } diff --git a/hw/xtensa/esp32_intc.c b/hw/xtensa/esp32_intc.c index 68e985a19605..50fb8f661d77 100644 --- a/hw/xtensa/esp32_intc.c +++ b/hw/xtensa/esp32_intc.c @@ -25,6 +25,7 @@ static void esp32_intmatrix_irq_handler(void *opaque, int n, int level) { Esp32IntMatrixState *s = ESP32_INTMATRIX(opaque); + s->irq_raw[n] = level; for (int i = 0; i < ESP32_CPU_COUNT; ++i) { if (s->outputs[i] == NULL) { continue; @@ -61,10 +62,20 @@ static uint64_t esp32_intmatrix_read(void* opaque, hwaddr addr, unsigned int siz static void esp32_intmatrix_write(void* opaque, hwaddr addr, uint64_t value, unsigned int size) { Esp32IntMatrixState *s = ESP32_INTMATRIX(opaque); - uint8_t* map_entry = get_map_entry(s, addr); + int source_index = (addr / sizeof(uint32_t)) % ESP32_INT_MATRIX_INPUTS; + uint8_t *map_entry = get_map_entry(s, addr); + if (value == INTMATRIX_UNINT_VALUE) { + int si = s->irq_raw[source_index]; + esp32_intmatrix_irq_handler(s, source_index, 0); + s->irq_raw[source_index] = si; + } if (map_entry != NULL) { *map_entry = value & 0x1f; } + if (value != INTMATRIX_UNINT_VALUE && s->irq_raw[source_index]) { + esp32_intmatrix_irq_handler(s, source_index, 1); + } + } static const MemoryRegionOps esp_intmatrix_ops = { @@ -76,6 +87,7 @@ static const MemoryRegionOps esp_intmatrix_ops = { static void esp32_intmatrix_reset(DeviceState *dev) { Esp32IntMatrixState *s = ESP32_INTMATRIX(dev); + memset(s->irq_raw, 0, sizeof(s->irq_raw)); memset(s->irq_map, INTMATRIX_UNINT_VALUE, sizeof(s->irq_map)); for (int i = 0; i < ESP32_CPU_COUNT; ++i) { if (s->outputs[i] == NULL) { diff --git a/include/hw/misc/esp32_ana.h b/include/hw/misc/esp32_ana.h new file mode 100644 index 000000000000..8c4bc32c858f --- /dev/null +++ b/include/hw/misc/esp32_ana.h @@ -0,0 +1,17 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32_reg.h" + + +#define TYPE_ESP32_ANA "misc.esp32.ana" +#define ESP32_ANA(obj) OBJECT_CHECK(Esp32AnaState, (obj), TYPE_ESP32_ANA) + +typedef struct Esp32AnaState { + SysBusDevice parent_obj; + MemoryRegion iomem; + uint32_t mem[1024]; +} Esp32AnaState; + diff --git a/include/hw/misc/esp32_fe.h b/include/hw/misc/esp32_fe.h new file mode 100644 index 000000000000..fa6c9faf29cc --- /dev/null +++ b/include/hw/misc/esp32_fe.h @@ -0,0 +1,17 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_reg.h" + + +#define TYPE_ESP32_FE "misc.esp32.fe" +#define ESP32_FE(obj) OBJECT_CHECK(Esp32FeState, (obj), TYPE_ESP32_FE) + +typedef struct Esp32FeState { + SysBusDevice parent_obj; + MemoryRegion iomem; + uint32_t mem[1024]; +} Esp32FeState; + + diff --git a/include/hw/misc/esp32_phya.h b/include/hw/misc/esp32_phya.h new file mode 100644 index 000000000000..8a4c66b6d8b9 --- /dev/null +++ b/include/hw/misc/esp32_phya.h @@ -0,0 +1,17 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_reg.h" + + +#define TYPE_ESP32_PHYA "misc.esp32.phya" +#define ESP32_PHYA(obj) OBJECT_CHECK(Esp32PhyaState, (obj), TYPE_ESP32_PHYA) + +typedef struct Esp32PhyaState { + SysBusDevice parent_obj; + MemoryRegion iomem; + uint32_t mem[1024]; +} Esp32PhyaState; + + diff --git a/include/hw/misc/esp32_reg.h b/include/hw/misc/esp32_reg.h index 657f4679e74b..669a0c0419b0 100644 --- a/include/hw/misc/esp32_reg.h +++ b/include/hw/misc/esp32_reg.h @@ -37,7 +37,8 @@ #define DR_REG_LEDC_BASE 0x3ff59000 #define DR_REG_EFUSE_BASE 0x3ff5A000 #define DR_REG_SPI_ENCRYPT_BASE 0x3ff5B000 -#define DR_REG_NRX_BASE 0x3ff5CC00 +#define DR_REG_NRX_BASE 0x3ff5C000 +// ^ modified from official value of 0x3ff5CC00 #define DR_REG_BB_BASE 0x3ff5D000 #define DR_REG_PWM_BASE 0x3ff5E000 #define DR_REG_TIMERGROUP0_BASE 0x3ff5F000 @@ -58,6 +59,9 @@ #define DR_REG_UART2_BASE 0x3ff6E000 #define DR_REG_PWM2_BASE 0x3ff6F000 #define DR_REG_PWM3_BASE 0x3ff70000 +#define DR_REG_PHY_BASE 0x3ff71000 +#define DR_REG_WIFI_BASE 0x3ff73000 +#define DR_REG_PHYA_BASE 0x3ff74000 #define DR_REG_WDEV_BASE 0x3ff75000 #define APB_REG_BASE 0x60000000 diff --git a/include/hw/misc/esp32_unknown.h b/include/hw/misc/esp32_unknown.h new file mode 100644 index 000000000000..8fef1140d8a5 --- /dev/null +++ b/include/hw/misc/esp32_unknown.h @@ -0,0 +1,15 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/esp32_reg.h" + +#define TYPE_ESP32_UNKNOWN "misc.esp32.unknown" +#define ESP32_UNKNOWN(obj) OBJECT_CHECK(Esp32UnknownState, (obj), TYPE_ESP32_UNKNOWN) + +typedef struct Esp32UnknownState { + SysBusDevice parent_obj; + MemoryRegion iomem; +} Esp32UnknownState; + diff --git a/include/hw/misc/esp32_wifi.h b/include/hw/misc/esp32_wifi.h new file mode 100644 index 000000000000..a8c86d4dd08f --- /dev/null +++ b/include/hw/misc/esp32_wifi.h @@ -0,0 +1,65 @@ +#pragma once + +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/sysbus.h" +#include "hw/misc/esp32_reg.h" +#include "sysemu/sysemu.h" +#include "net/net.h" + +#define TYPE_ESP32_WIFI "misc.esp32_wifi" +#define ESP32_WIFI(obj) OBJECT_CHECK(Esp32WifiState, (obj), TYPE_ESP32_WIFI) + +typedef struct dma_list_item { + unsigned size:12; + unsigned length:12; + unsigned :6; + unsigned eof:1; + unsigned owner:1; + uint32_t address; + uint32_t next; +} QEMU_PACKED dma_list_item; + +typedef struct Esp32WifiState { + SysBusDevice parent_obj; + MemoryRegion iomem; + int raw_interrupt; + qemu_irq irq; + uint32_t mem[1024]; + int dma_inlink_address; + uint32_t ap_state; + int inject_queue_size; + struct mac80211_frame *inject_queue; + int inject_timer_running; + unsigned int inject_sequence_number; + int beacon_ap; + + hwaddr receive_queue_address; + uint32_t receive_queue_count; + NICConf conf; + NICState *nic; + // various timers + QEMUTimer *beacon_timer; + QEMUTimer *inject_timer; + uint8_t ipaddr[4]; + uint8_t macaddr[6]; + + uint8_t ap_ipaddr[4]; + uint8_t ap_macaddr[6]; + + uint8_t associated_ap_macaddr[6]; + +} Esp32WifiState; + + +void Esp32_WLAN_handle_frame(Esp32WifiState *s, struct mac80211_frame *frame); +void Esp32_WLAN_setup_ap(DeviceState *dev,Esp32WifiState *s); +void Esp32_sendFrame(Esp32WifiState *s, struct mac80211_frame *frame,int length, int signal_strength); + +REG32(WIFI_DMA_IN_STATUS, 0x84); +REG32(WIFI_DMA_INLINK, 0x88); +REG32(WIFI_DMA_INT_STATUS, 0xc48); +REG32(WIFI_DMA_INT_CLR, 0xc4c); +REG32(WIFI_STATUS, 0xcc8); +REG32(WIFI_DMA_OUTLINK, 0xd20); +REG32(WIFI_DMA_OUT_STATUS, 0xd24); diff --git a/include/hw/misc/unimp-default.h b/include/hw/misc/unimp-default.h new file mode 100644 index 000000000000..2ee8c5ad6a8e --- /dev/null +++ b/include/hw/misc/unimp-default.h @@ -0,0 +1,58 @@ +/* + * "Unimplemented" device with default value + * + * Copyright Linaro Limited, 2017 + * Written by Peter Maydell + * Modified by redfast00 2023 + */ + +#ifndef HW_MISC_UNIMP_DEFAULT_H +#define HW_MISC_UNIMP_DEFAULT_H + +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "qapi/error.h" +#include "qom/object.h" + +#define TYPE_UNIMPLEMENTED_DEFAULT_DEVICE "unimplemented-default-device" + +OBJECT_DECLARE_SIMPLE_TYPE(UnimplementedDefaultDeviceState, UNIMPLEMENTED_DEFAULT_DEVICE) + +struct UnimplementedDefaultDeviceState { + SysBusDevice parent_obj; + MemoryRegion iomem; + unsigned offset_fmt_width; + char *name; + uint64_t size; + uint64_t default_value; +}; + +/** + * create_unimplemented_default_device: create and map a dummy device with default value + * @name: name of the device for debug logging + * @base: base address of the device's MMIO region + * @size: size of the device's MMIO region + * @default_value: value returned for read operations + * + * This utility function creates and maps an instance of unimplemented-device, + * which is a dummy device which simply logs all guest accesses to + * it via the qemu_log LOG_UNIMP debug log. + * The device is mapped at priority -1000, which means that you can + * use it to cover a large region and then map other devices on top of it + * if necessary. + */ +static inline void create_unimplemented_default_device(const char *name, + hwaddr base, + hwaddr size, uint64_t default_value) +{ + DeviceState *dev = qdev_new(TYPE_UNIMPLEMENTED_DEFAULT_DEVICE); + + qdev_prop_set_string(dev, "name", name); + qdev_prop_set_uint64(dev, "size", size); + qdev_prop_set_uint64(dev, "default_value", default_value); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, base, -1000); +} + +#endif diff --git a/include/hw/xtensa/esp32.h b/include/hw/xtensa/esp32.h index 6097a362538f..261a21669e2c 100644 --- a/include/hw/xtensa/esp32.h +++ b/include/hw/xtensa/esp32.h @@ -13,6 +13,11 @@ #include "hw/misc/esp32_aes.h" #include "hw/misc/esp32_ledc.h" #include "hw/misc/esp32_rsa.h" +#include "hw/misc/esp32_unknown.h" +#include "hw/misc/esp32_ana.h" +#include "hw/misc/esp32_wifi.h" +#include "hw/misc/esp32_phya.h" +#include "hw/misc/esp32_fe.h" #include "hw/timer/esp32_frc_timer.h" #include "hw/timer/esp32_timg.h" #include "hw/misc/esp32_crosscore_int.h" @@ -46,8 +51,16 @@ typedef struct Esp32SocState { Esp32LEDCState ledc; Esp32EfuseState efuse; Esp32FlashEncryptionState flash_enc; + Esp32UnknownState unknown; + Esp32AnaState ana; + Esp32WifiState wifi; + Esp32PhyaState phya; + Esp32FeState fe; + DWCSDMMCState sdmmc; DeviceState *eth; + DeviceState *wifi_dev; + BusState rtc_bus; BusState periph_bus; diff --git a/include/hw/xtensa/esp32_intc.h b/include/hw/xtensa/esp32_intc.h index 262dbd13844f..bd0bb8008c14 100644 --- a/include/hw/xtensa/esp32_intc.h +++ b/include/hw/xtensa/esp32_intc.h @@ -34,6 +34,7 @@ typedef struct Esp32IntMatrixState { MemoryRegion iomem; qemu_irq *outputs[ESP32_CPU_COUNT]; uint8_t irq_map[ESP32_CPU_COUNT][ESP32_INT_MATRIX_INPUTS]; + uint8_t irq_raw[ESP32_INT_MATRIX_INPUTS]; /* properties */ XtensaCPU *cpu[ESP32_CPU_COUNT];