From db735964ee29c1377a4d2d54e8ce960b98a4607c Mon Sep 17 00:00:00 2001 From: Axel Tillequin Date: Mon, 24 Jun 2024 14:18:14 +0200 Subject: [PATCH] Squashed commit of the following: * change default ui term engine from pygments to rich * add EmuData orm object to save the emulator state * add save/restore commands in emul ui * implement callstack logic * add callstack frame in emul ui * add debug command in emul ui * add StructView class for structs pretty printing * fix x86 mmu_cache logic (flush & misses) * change default action from codeql to ruff * refactor code based on ruff checks --- .github/workflows/codeql.yml | 41 - .github/workflows/ruff.yml | 10 + .readthedocs.yaml | 8 +- README.rst | 92 +- amoco/__init__.py | 2 +- amoco/arch/arm/cpu_armv7.py | 30 +- amoco/arch/arm/cpu_armv8.py | 26 +- amoco/arch/arm/v7/asm.py | 49 +- amoco/arch/arm/v7/env.py | 10 +- amoco/arch/arm/v7/formats.py | 8 +- amoco/arch/arm/v7/spec_armv7.py | 123 +- amoco/arch/arm/v7/spec_thumb.py | 13 +- amoco/arch/arm/v7/spec_thumb2.py | 27 +- amoco/arch/arm/v7/utils.py | 2 + amoco/arch/arm/v8/asm64.py | 25 +- amoco/arch/arm/v8/env64.py | 43 +- amoco/arch/arm/v8/formats.py | 89 +- amoco/arch/arm/v8/spec_armv8.py | 55 +- amoco/arch/arm/v8/spec_simd.py | 192 ++ amoco/arch/arm/v8/utils.py | 4 +- amoco/arch/avr/asm.py | 19 +- amoco/arch/avr/cpu.py | 24 +- amoco/arch/avr/env.py | 117 +- amoco/arch/avr/formats.py | 17 +- amoco/arch/avr/spec.py | 10 +- amoco/arch/core.py | 100 +- amoco/arch/dwarf/asm.py | 6 +- amoco/arch/dwarf/cpu.py | 24 +- amoco/arch/dwarf/env.py | 6 +- amoco/arch/dwarf/formats.py | 3 +- amoco/arch/dwarf/spec.py | 22 +- amoco/arch/eBPF/asm.py | 3 +- amoco/arch/eBPF/cpu.py | 27 +- amoco/arch/eBPF/cpu_bpf.py | 27 +- amoco/arch/eBPF/env.py | 7 +- amoco/arch/eBPF/formats.py | 5 +- amoco/arch/eBPF/spec.py | 58 +- amoco/arch/eBPF/spec_bpf.py | 9 +- amoco/arch/gas.py | 70 +- amoco/arch/io.py | 37 +- amoco/arch/mips/cpu_r3000.py | 20 +- amoco/arch/mips/cpu_r3000LE.py | 18 +- amoco/arch/mips/r3000/asm.py | 298 +-- amoco/arch/mips/r3000/env.py | 199 +- amoco/arch/mips/r3000/formats.py | 18 +- amoco/arch/mips/r3000/spec.py | 42 +- amoco/arch/msp430/asm.py | 7 +- amoco/arch/msp430/cpu.py | 18 +- amoco/arch/msp430/env.py | 6 +- amoco/arch/msp430/formats.py | 7 +- amoco/arch/msp430/parsers.py | 16 +- amoco/arch/msp430/spec_msp430.py | 7 +- amoco/arch/pic/F46K22/asm.py | 20 +- amoco/arch/pic/F46K22/env.py | 3 +- amoco/arch/pic/F46K22/formats.py | 3 +- amoco/arch/pic/F46K22/spec_pic18.py | 5 +- amoco/arch/pic/cpu_pic18f46k22.py | 17 +- amoco/arch/ppc32/asm.py | 6 +- amoco/arch/ppc32/cpu.py | 19 +- amoco/arch/ppc32/cpu_e200.py | 19 +- amoco/arch/ppc32/e200/asm.py | 298 +-- amoco/arch/ppc32/e200/env.py | 55 +- amoco/arch/ppc32/e200/formats.py | 18 +- amoco/arch/ppc32/e200/spec_e200.py | 5 +- amoco/arch/ppc32/env.py | 148 +- amoco/arch/ppc32/formats.py | 20 +- amoco/arch/ppc32/spec_booke.py | 430 ++-- amoco/arch/ppc32/spec_vle.py | 11 +- amoco/arch/riscv/cpu_rv32i.py | 18 +- amoco/arch/riscv/cpu_rv64i.py | 18 +- amoco/arch/riscv/formats.py | 6 +- amoco/arch/riscv/rv32i/asm.py | 43 +- amoco/arch/riscv/rv32i/env.py | 7 +- amoco/arch/riscv/rv32i/formats.py | 6 +- amoco/arch/riscv/rv32i/spec_rv32i.py | 12 +- amoco/arch/riscv/rv64i/asm.py | 43 +- amoco/arch/riscv/rv64i/env.py | 6 +- amoco/arch/riscv/rv64i/formats.py | 6 +- amoco/arch/riscv/rv64i/spec_rv64i.py | 11 +- amoco/arch/riscv/utils.py | 1 + amoco/arch/sparc/asm.py | 30 +- amoco/arch/sparc/cpu_v8.py | 19 +- amoco/arch/sparc/env.py | 10 +- amoco/arch/sparc/formats.py | 187 +- amoco/arch/sparc/parsers.py | 138 +- amoco/arch/sparc/spec_v8.py | 140 +- amoco/arch/superh/cpu_sh2.py | 18 +- amoco/arch/superh/cpu_sh4.py | 19 +- amoco/arch/superh/sh2/asm.py | 32 +- amoco/arch/superh/sh2/env.py | 8 +- amoco/arch/superh/sh2/formats.py | 6 +- amoco/arch/superh/sh2/spec_sh2.py | 12 +- amoco/arch/superh/sh4/env.py | 7 +- amoco/arch/superh/sh4/spec_sh4.py | 6 +- amoco/arch/tricore/asm.py | 840 ++++---- amoco/arch/tricore/cpu.py | 17 +- amoco/arch/tricore/env.py | 196 +- amoco/arch/tricore/formats.py | 15 +- amoco/arch/tricore/spec.py | 1770 +++++++++++++---- amoco/arch/tricore/utils.py | 41 +- amoco/arch/v850/asm.py | 20 +- amoco/arch/v850/cpu_v850e2s.py | 17 +- amoco/arch/v850/env.py | 6 +- amoco/arch/v850/formats.py | 4 +- amoco/arch/v850/spec_v850e2s.py | 17 +- amoco/arch/w65c02/asm.py | 513 +++-- amoco/arch/w65c02/cpu.py | 17 +- amoco/arch/w65c02/env.py | 34 +- amoco/arch/w65c02/formats.py | 6 +- amoco/arch/w65c02/spec.py | 88 +- amoco/arch/wasm/asm.py | 10 +- amoco/arch/wasm/cpu.py | 16 +- amoco/arch/wasm/env.py | 31 +- amoco/arch/wasm/formats.py | 3 +- amoco/arch/wasm/spec.py | 140 +- amoco/arch/x64/asm.py | 39 +- amoco/arch/x64/cpu_x64.py | 23 +- amoco/arch/x64/env.py | 36 +- amoco/arch/x64/formats.py | 10 +- amoco/arch/x64/spec_fpu.py | 6 +- amoco/arch/x64/spec_ia32e.py | 188 +- amoco/arch/x64/spec_sse.py | 20 +- amoco/arch/x64/utils.py | 5 +- amoco/arch/x86/asm.py | 668 ++++--- amoco/arch/x86/cpu_x86.py | 173 +- amoco/arch/x86/env.py | 306 ++- amoco/arch/x86/formats.py | 33 +- amoco/arch/x86/hw.py | 35 +- amoco/arch/x86/parsers.py | 115 +- amoco/arch/x86/spec_fpu.py | 4 +- amoco/arch/x86/spec_ia32.py | 179 +- amoco/arch/x86/spec_sse.py | 20 +- amoco/arch/x86/structs.py | 222 ++- amoco/arch/x86/utils.py | 5 +- amoco/arch/z80/asm.py | 16 +- amoco/arch/z80/cpu_gb.py | 17 +- amoco/arch/z80/cpu_z80.py | 17 +- amoco/arch/z80/env.py | 6 +- amoco/arch/z80/spec_gb.py | 13 +- amoco/arch/z80/spec_mostek.py | 15 +- amoco/cas/__init__.py | 1 + amoco/cas/blobs.py | 172 +- amoco/cas/expressions.py | 156 +- amoco/cas/mapper.py | 139 +- amoco/cas/parser.py | 2 +- amoco/cas/smt.py | 69 +- amoco/cas/tracker.py | 9 +- amoco/cas/utils.py | 2 +- amoco/cfg.py | 12 +- amoco/code.py | 88 +- amoco/config.py | 39 +- amoco/db.py | 20 +- amoco/emu.py | 301 +-- amoco/logger.py | 78 +- amoco/main.py | 2 + amoco/sa/__init__.py | 2 +- amoco/sa/backward.py | 23 +- amoco/sa/forward.py | 16 +- amoco/sa/ghidra.py | 152 +- amoco/sa/lsweep.py | 35 +- amoco/sa/utils.py | 3 +- amoco/signals.py | 4 +- amoco/system/baremetal/__init__.py | 13 +- amoco/system/baremetal/apple2.py | 231 +-- amoco/system/baremetal/atmega328p.py | 44 +- amoco/system/baremetal/gameboy.py | 7 +- amoco/system/baremetal/imx6.py | 15 +- amoco/system/baremetal/leon2.py | 6 +- amoco/system/baremetal/msp430.py | 3 +- amoco/system/baremetal/pic18.py | 8 +- amoco/system/baremetal/psx.py | 634 +++--- amoco/system/baremetal/riscv.py | 92 - amoco/system/baremetal/sh726b.py | 2 +- amoco/system/baremetal/tricore.py | 59 +- amoco/system/baremetal/w65c02.py | 39 +- amoco/system/baremetal/x86.py | 147 +- amoco/system/coff.py | 273 ++- amoco/system/core.py | 94 +- amoco/system/elf.py | 88 +- amoco/system/fs/ufs.py | 13 +- amoco/system/fs/yaffs.py | 56 +- amoco/system/gdb_tfile.py | 206 +- amoco/system/linux32/__init__.py | 13 +- amoco/system/linux32/abi.py | 39 +- amoco/system/linux32/arm.py | 55 +- amoco/system/linux32/mips.py | 32 +- amoco/system/linux32/mips_le.py | 32 +- amoco/system/linux32/riscv.py | 32 +- amoco/system/linux32/sh2.py | 15 +- amoco/system/linux32/sparc.py | 41 +- amoco/system/linux32/x86.py | 64 +- amoco/system/linux64/__init__.py | 4 +- amoco/system/linux64/aarch64.py | 14 +- amoco/system/linux64/abi.py | 42 + amoco/system/linux64/ld.py | 1 - amoco/system/linux64/x64.py | 67 +- amoco/system/macho.py | 119 +- amoco/system/memory.py | 21 +- amoco/system/osx/x64.py | 81 +- amoco/system/pe.py | 162 +- amoco/system/raw.py | 22 +- amoco/system/structs/HEX.py | 11 +- amoco/system/structs/SREC.py | 45 +- amoco/system/structs/__init__.py | 93 +- amoco/system/structs/core.py | 49 +- amoco/system/structs/fields.py | 190 +- amoco/system/structs/formatters.py | 114 +- amoco/system/structs/utils.py | 34 +- amoco/system/utils.py | 2 +- amoco/system/vm/__init__.py | 3 +- amoco/system/vm/bpf.py | 5 +- amoco/system/vm/dwarf.py | 6 +- amoco/system/vm/ebpf.py | 5 +- amoco/system/vm/wasm.py | 471 +++-- amoco/system/win32/__init__.py | 3 +- amoco/system/win32/ole2.py | 139 +- amoco/system/win32/vb6.py | 2 +- amoco/system/win32/x86.py | 40 +- amoco/system/win64/__init__.py | 3 +- amoco/system/win64/x64.py | 9 +- amoco/ui/app.py | 98 +- amoco/ui/cli.py | 15 +- amoco/ui/graphics/__init__.py | 28 +- amoco/ui/graphics/gtk_/canvas.py | 67 - amoco/ui/graphics/gtk_/engine.py | 42 - amoco/ui/graphics/gtk_/graphwin.py | 103 - amoco/ui/graphics/gtk_/items.py | 455 ----- amoco/ui/graphics/gtk_/mainwin.py | 59 - amoco/ui/graphics/kivy_/__init__.py | 0 amoco/ui/graphics/kivy_/engine.py | 28 - amoco/ui/graphics/qt_/binfmtview.py | 74 +- amoco/ui/graphics/qt_/brushes.py | 14 +- amoco/ui/graphics/qt_/colors.py | 42 +- amoco/ui/graphics/qt_/engine.py | 73 +- amoco/ui/graphics/qt_/graphwin.py | 155 +- amoco/ui/graphics/qt_/hexview.py | 263 +-- amoco/ui/graphics/qt_/infoview.py | 4 - amoco/ui/graphics/qt_/models.py | 29 +- amoco/ui/graphics/qt_/rc_icons.py | 11 +- amoco/ui/graphics/qt_/structview.py | 43 +- amoco/ui/graphics/qt_/taskwin.py | 67 +- amoco/ui/graphics/rich_.py | 276 +++ amoco/ui/graphics/term.py | 47 - .../graphics/{gtk_ => textual_}/__init__.py | 0 amoco/ui/graphics/textual_/amoco.tcss | 21 + amoco/ui/graphics/textual_/configscreen.py | 7 + amoco/ui/graphics/textual_/dbscreen.py | 7 + amoco/ui/graphics/textual_/emulscreen.py | 16 + amoco/ui/graphics/textual_/engine.py | 83 + amoco/ui/graphics/textual_/helpscreen.py | 12 + amoco/ui/render.py | 385 +--- amoco/ui/srv.py | 515 +++-- amoco/ui/views.py | 481 +++-- doc/amo_emu_inherit.png | Bin 0 -> 123132 bytes doc/arch.rst | 58 +- doc/conf.py | 171 +- doc/examples.rst | 1 - doc/installation.rst | 19 +- doc/overview.rst | 6 +- doc/quickstart.rst | 327 +-- doc/requirements.txt | 1 + pyproject.toml | 18 + requirements.txt | 9 +- setup.py | 86 +- tests/conftest.py | 103 +- tests/samples/arm/hw | Bin tests/samples/arm/sc | Bin tests/samples/inherit.cpp | 58 + tests/samples/x64/inherit_dbg.elf64 | Bin 0 -> 37144 bytes .../x64/toc.osx/lib/libtoc.dylib.mach-o | Bin tests/samples/x64/toc.osx/toc.mach-o | Bin tests/samples/x86/hello.c | 6 + tests/samples/x86/libhello_pic.so | Bin 0 -> 14616 bytes tests/test_arch_armv7.py | 99 +- tests/test_arch_armv8.py | 78 +- tests/test_arch_ppc.py | 44 +- tests/test_arch_sparc.py | 212 +- tests/test_arch_tricore.py | 55 +- tests/test_arch_wasm.py | 59 +- tests/test_arch_x64.py | 328 +-- tests/test_arch_x64_mapper.py | 32 +- tests/test_arch_x86.py | 735 ++++--- tests/test_cas_blob.py | 138 +- tests/test_cas_exp.py | 252 +-- tests/test_cas_mapper.py | 283 +-- tests/test_cas_smt.py | 38 +- tests/test_code.py | 58 +- tests/test_main_target.py | 35 +- tests/test_signals.py | 119 +- tests/test_system_core.py | 97 +- tests/test_system_elf.py | 19 +- tests/test_system_imx6.py | 8 +- tests/test_system_loader.py | 9 +- tests/test_system_macho.py | 16 +- tests/test_system_pe.py | 9 +- tests/test_system_raw.py | 11 +- tests/test_system_structs.py | 336 ++-- tests/test_system_utils.py | 17 +- tests/test_ui_qt.py | 22 +- tests/test_ui_render.py | 45 +- 300 files changed, 13168 insertions(+), 9758 deletions(-) delete mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/ruff.yml create mode 100644 amoco/arch/arm/v8/spec_simd.py delete mode 100644 amoco/system/baremetal/riscv.py create mode 100644 amoco/system/linux64/abi.py delete mode 100644 amoco/system/linux64/ld.py delete mode 100644 amoco/ui/graphics/gtk_/canvas.py delete mode 100644 amoco/ui/graphics/gtk_/engine.py delete mode 100644 amoco/ui/graphics/gtk_/graphwin.py delete mode 100644 amoco/ui/graphics/gtk_/items.py delete mode 100644 amoco/ui/graphics/gtk_/mainwin.py delete mode 100644 amoco/ui/graphics/kivy_/__init__.py delete mode 100644 amoco/ui/graphics/kivy_/engine.py create mode 100644 amoco/ui/graphics/rich_.py delete mode 100644 amoco/ui/graphics/term.py rename amoco/ui/graphics/{gtk_ => textual_}/__init__.py (100%) create mode 100644 amoco/ui/graphics/textual_/amoco.tcss create mode 100644 amoco/ui/graphics/textual_/configscreen.py create mode 100644 amoco/ui/graphics/textual_/dbscreen.py create mode 100644 amoco/ui/graphics/textual_/emulscreen.py create mode 100644 amoco/ui/graphics/textual_/engine.py create mode 100644 amoco/ui/graphics/textual_/helpscreen.py create mode 100644 doc/amo_emu_inherit.png create mode 100644 doc/requirements.txt create mode 100644 pyproject.toml mode change 100755 => 100644 tests/samples/arm/hw mode change 100755 => 100644 tests/samples/arm/sc create mode 100644 tests/samples/inherit.cpp create mode 100644 tests/samples/x64/inherit_dbg.elf64 mode change 100755 => 100644 tests/samples/x64/toc.osx/lib/libtoc.dylib.mach-o mode change 100755 => 100644 tests/samples/x64/toc.osx/toc.mach-o create mode 100644 tests/samples/x86/hello.c create mode 100644 tests/samples/x86/libhello_pic.so diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 30e61cb..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [ "release" ] - pull_request: - branches: [ "release" ] - schedule: - - cron: "1 2 * * 1" - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ python ] - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - queries: +security-and-quality - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 0000000..857d73a --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,10 @@ +name: Ruff +on: [push, pull_request] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 + with: + args: 'check --config pyproject.toml' diff --git a/.readthedocs.yaml b/.readthedocs.yaml index fd5be7b..084787e 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -9,14 +9,20 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.10" + python: "3.12" # Build documentation in the docs/ directory with Sphinx sphinx: configuration: doc/conf.py +formats: + - pdf + - epub + # We recommend specifying your dependencies to enable reproducible builds: # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html python: install: + - method: pip - requirements: requirements.txt + - requirements: doc/requirements.txt diff --git a/README.rst b/README.rst index 006d520..23f0ca1 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ ===== -Amoco +amoco ===== .. image:: http://readthedocs.org/projects/amoco/badge/?version=latest @@ -9,17 +9,15 @@ Amoco +-----------+--------------------------------------------------+ | Status: | Under Development | +-----------+--------------------------------------------------+ -| Location: | https://github.com/bdcht/amoco | -+-----------+--------------------------------------------------+ | Version: | 2.9 (pre-3.0) | +-----------+--------------------------------------------------+ -| Doc: | http://amoco.readthedocs.io/en/latest/index.html | +| Doc: | http://amoco.readthedocs.io/en/latest/index.html | +-----------+--------------------------------------------------+ Description =========== -Amoco is a python (>=3.8) package dedicated to symbolic analysis of binaries. +Amoco is a python package dedicated to symbolic analysis of binaries. It features: @@ -51,8 +49,8 @@ merged from develop branch or to be more thoroughly implemented. User documentation and API can be found at `http://amoco.readthedocs.io/en/latest/index.html` -.. image:: https://github.com/bdcht/amoco/blob/release/doc/gui_load.png - :width: 800 +.. image:: doc/amo_emu_inherit.png + :width: 100% Todo ==== @@ -87,6 +85,19 @@ Please see `LICENSE`_. Changelog ========= +- `v2.9.11`_ + + * change default ui term engine from pygments to rich + * add EmuData orm object to save the emulator state + * add save/restore commands in emul ui + * implement callstack logic + * add callstack frame in emul ui + * add debug command in emul ui + * add StructView class for structs pretty printing + * fix x86 mmu_cache logic (flush & misses) + * change default action from codeql to ruff + * refactor code based on ruff checks + - `v2.9.10`_ * x86: add support for real mode execution @@ -98,7 +109,7 @@ Changelog * add tracepoint method in emul class * add support for PE resources * improve amoco app load/emul commands - * add set,display,nexti,until in emul ui. + * add set,display,nexti,until in emul ui - `v2.9.9`_ @@ -408,35 +419,36 @@ Changelog .. _ply: http://www.dabeaz.com/ply/ .. _sqlalchemy: http://www.sqlalchemy.org .. _QDarkStyleSheet: https://github.com/ColinDuquesnoy/QDarkStyleSheet -.. _LICENSE: https://github.com/bdcht/amoco/blob/release/LICENSE -.. _v2.9.10: https://github.com/bdcht/amoco/releases/tag/v2.9.10 -.. _v2.9.9: https://github.com/bdcht/amoco/releases/tag/v2.9.9 -.. _v2.9.8: https://github.com/bdcht/amoco/releases/tag/v2.9.8 -.. _v2.9.7: https://github.com/bdcht/amoco/releases/tag/v2.9.7 -.. _v2.9.6: https://github.com/bdcht/amoco/releases/tag/v2.9.6 -.. _v2.9.5: https://github.com/bdcht/amoco/releases/tag/v2.9.5 -.. _v2.9.4: https://github.com/bdcht/amoco/releases/tag/v2.9.4 -.. _v2.9.3: https://github.com/bdcht/amoco/releases/tag/v2.9.3 -.. _v2.9.2: https://github.com/bdcht/amoco/releases/tag/v2.9.2 -.. _v2.9.1: https://github.com/bdcht/amoco/releases/tag/v2.9.1 -.. _v2.9.0: https://github.com/bdcht/amoco/releases/tag/v2.9.0 -.. _v2.6.3: https://github.com/bdcht/amoco/releases/tag/v2.6.3 -.. _v2.6.2: https://github.com/bdcht/amoco/releases/tag/v2.6.2 -.. _v2.6.1: https://github.com/bdcht/amoco/releases/tag/v2.6.1 -.. _v2.6.0: https://github.com/bdcht/amoco/releases/tag/v2.6.0 -.. _v2.5.3: https://github.com/bdcht/amoco/releases/tag/v2.5.3 -.. _v2.5.2: https://github.com/bdcht/amoco/releases/tag/v2.5.2 -.. _v2.5.1: https://github.com/bdcht/amoco/releases/tag/v2.5.1 -.. _v2.5.0: https://github.com/bdcht/amoco/releases/tag/v2.5.0 -.. _v2.4.6: https://github.com/bdcht/amoco/releases/tag/v2.4.6 -.. _v2.4.5: https://github.com/bdcht/amoco/releases/tag/v2.4.5 -.. _v2.4.4: https://github.com/bdcht/amoco/releases/tag/v2.4.4 -.. _v2.4.3: https://github.com/bdcht/amoco/releases/tag/v2.4.3 -.. _v2.4.2: https://github.com/bdcht/amoco/releases/tag/v2.4.2 -.. _v2.4.1: https://github.com/bdcht/amoco/releases/tag/v2.4.1 -.. _v2.4.0: https://github.com/bdcht/amoco/releases/tag/v2.4.0 -.. _v2.3.5: https://github.com/bdcht/amoco/releases/tag/v2.3.5 -.. _v2.3.4: https://github.com/bdcht/amoco/releases/tag/v2.3.4 -.. _v2.3.3: https://github.com/bdcht/amoco/releases/tag/v2.3.3 -.. _v2.3.2: https://github.com/bdcht/amoco/releases/tag/v2.3.2 -.. _v2.3.1: https://github.com/bdcht/amoco/releases/tag/v2.3.1 +.. _LICENSE: /../../release/LICENSE +.. _v2.9.11: /../../releases/tag/v2.9.11 +.. _v2.9.10: /../../releases/tag/v2.9.10 +.. _v2.9.9: /../../releases/tag/v2.9.9 +.. _v2.9.8: /../../releases/tag/v2.9.8 +.. _v2.9.7: /../../releases/tag/v2.9.7 +.. _v2.9.6: /../../releases/tag/v2.9.6 +.. _v2.9.5: /../../releases/tag/v2.9.5 +.. _v2.9.4: /../../releases/tag/v2.9.4 +.. _v2.9.3: /../../releases/tag/v2.9.3 +.. _v2.9.2: /../../releases/tag/v2.9.2 +.. _v2.9.1: /../../releases/tag/v2.9.1 +.. _v2.9.0: /../../releases/tag/v2.9.0 +.. _v2.6.3: /../../releases/tag/v2.6.3 +.. _v2.6.2: /../../releases/tag/v2.6.2 +.. _v2.6.1: /../../releases/tag/v2.6.1 +.. _v2.6.0: /../../releases/tag/v2.6.0 +.. _v2.5.3: /../../releases/tag/v2.5.3 +.. _v2.5.2: /../../releases/tag/v2.5.2 +.. _v2.5.1: /../../releases/tag/v2.5.1 +.. _v2.5.0: /../../releases/tag/v2.5.0 +.. _v2.4.6: /../../releases/tag/v2.4.6 +.. _v2.4.5: /../../releases/tag/v2.4.5 +.. _v2.4.4: /../../releases/tag/v2.4.4 +.. _v2.4.3: /../../releases/tag/v2.4.3 +.. _v2.4.2: /../../releases/tag/v2.4.2 +.. _v2.4.1: /../../releases/tag/v2.4.1 +.. _v2.4.0: /../../releases/tag/v2.4.0 +.. _v2.3.5: /../../releases/tag/v2.3.5 +.. _v2.3.4: /../../releases/tag/v2.3.4 +.. _v2.3.3: /../../releases/tag/v2.3.3 +.. _v2.3.2: /../../releases/tag/v2.3.2 +.. _v2.3.1: /../../releases/tag/v2.3.1 diff --git a/amoco/__init__.py b/amoco/__init__.py index 15b6a64..216bacc 100644 --- a/amoco/__init__.py +++ b/amoco/__init__.py @@ -1 +1 @@ -from .main import * +from .main import * # noqa: F403 diff --git a/amoco/arch/arm/cpu_armv7.py b/amoco/arch/arm/cpu_armv7.py index f928d33..fdd6cd0 100644 --- a/amoco/arch/arm/cpu_armv7.py +++ b/amoco/arch/arm/cpu_armv7.py @@ -4,15 +4,9 @@ # Copyright (C) 2006-2014 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from amoco.arch.arm.v7.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) - -from amoco.arch.core import instruction, disassembler - -instruction_armv7 = type("instruction_armv7", (instruction,), {}) -instruction_armv7.set_uarch(uarch) +from amoco.arch.arm.v7 import env +from amoco.arch.arm.v7 import asm +from amoco.arch.core import instruction, disassembler, CPU # define disassembler: from amoco.arch.arm.v7 import spec_armv7 @@ -20,18 +14,24 @@ from amoco.arch.arm.v7.formats import ARM_V7_full +instruction_armv7 = type("instruction_armv7", (instruction,), {}) instruction_armv7.set_formatter(ARM_V7_full) -mode = lambda: internals["isetstate"] -endian = lambda: 1 if internals["ibigend"] == 0 else -1 +def mode(**kargs): + return env.internals["isetstate"] + + +def endian(**kargs): + return 1 if env.internals["ibigend"] == 0 else -1 + disassemble = disassembler([spec_armv7, spec_thumb], instruction_armv7, mode, endian) -def PC(state=None): - return pc_ +class CPU_ARMv7(CPU): + def get_data_endian(self): + return 1 if env.internals["endianstate"] == 0 else -1 -def get_data_endian(): - return 1 if internals["endianstate"] == 0 else -1 +cpu = CPU_ARMv7(env, asm, disassemble, env.pc_) diff --git a/amoco/arch/arm/cpu_armv8.py b/amoco/arch/arm/cpu_armv8.py index 3ba6429..0dee52f 100644 --- a/amoco/arch/arm/cpu_armv8.py +++ b/amoco/arch/arm/cpu_armv8.py @@ -4,30 +4,28 @@ # Copyright (C) 2006-2014 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from amoco.arch.arm.v8.asm64 import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) - -from amoco.arch.core import instruction, disassembler - -instruction_armv8 = type("instruction_armv8", (instruction,), {}) -instruction_armv8.set_uarch(uarch) +from amoco.arch.arm.v8 import env64 as env +from amoco.arch.arm.v8 import asm64 +from amoco.arch.core import instruction, disassembler, CPU # define disassembler: from amoco.arch.arm.v8 import spec_armv8 from amoco.arch.arm.v8.formats import ARM_V8_full +instruction_armv8 = type("instruction_armv8", (instruction,), {}) instruction_armv8.set_formatter(ARM_V8_full) -endian = lambda: 1 if internals["ibigend"] == 0 else -1 + +def endian(): + return 1 if env.internals["ibigend"] == 0 else -1 + disassemble = disassembler([spec_armv8], endian=endian, iclass=instruction_armv8) -def PC(state=None): - return pc +class CPU_ARMv8(CPU): + def get_data_endian(self): + return 1 if env.internals["endianstate"] == 0 else -1 -def get_data_endian(): - return 1 if internals["endianstate"] == 0 else -1 +cpu = CPU_ARMv8(env, asm64, disassemble, env.pc) diff --git a/amoco/arch/arm/v7/asm.py b/amoco/arch/arm/v7/asm.py index 060cf14..76b51d6 100644 --- a/amoco/arch/arm/v7/asm.py +++ b/amoco/arch/arm/v7/asm.py @@ -4,13 +4,22 @@ # Copyright (C) 2006-2011 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * +from .env import pc, pc_, lr, sp, C, Z, N, V, internals, CONDITION +from amoco.cas.expressions import mem, bit0, bit1, top, composer, cst, ror # utilities: # ---------- -from .utils import * -from amoco.cas.utils import * +from .utils import ( + stst, + LSL_C, + LSR_C, + ASR_C, + Shift_C, + ROR_C, + RRX_C, +) +from amoco.cas.utils import AddWithCarry from amoco.arch.core import InstructionError from amoco.logger import Log @@ -35,7 +44,12 @@ def __check_state(i, fmap): if _s != internals["isetstate"]: logger.info( "switch to %s instructions" - % ({0: "ARM", 1: "Thumb",}[internals["isetstate"]]) + % ( + { + 0: "ARM", + 1: "Thumb", + }[internals["isetstate"]] + ) ) @@ -75,6 +89,7 @@ def __setflags(fmap, cond, cout, result, overflow=None): # i_xxx is the translation of UAL (ARM/Thumb) instruction xxx. # ------------------------------------------------------------------------------ + # Branch instructions (A4.3, pA4-7) def i_B(i, fmap): cond, pcoff = __pre(i, fmap) @@ -127,6 +142,7 @@ def i_BXJ(i, fmap): # Data processing instructions (A4.4) + # standard (4.4.1): def i_ADC(i, fmap): cond, dest, op1, op2 = __pre(i, fmap) @@ -189,7 +205,7 @@ def i_BIC(i, fmap): def i_CMN(i, fmap): cond, dest, op1 = __pre(i, fmap) - if i.stype != None: + if i.stype is not None: shifted = Shift_C(fmap(op1), i.stype, i.shift, fmap(C)) else: shifted = fmap(op1) @@ -199,7 +215,7 @@ def i_CMN(i, fmap): def i_CMP(i, fmap): cond, dest, op1 = __pre(i, fmap) - if i.stype != None: + if i.stype is not None: shifted = Shift_C(fmap(op1), i.stype, i.shift, fmap(C)) else: shifted = fmap(op1) @@ -234,7 +250,6 @@ def i_MOV(i, fmap): def i_MOVT(i, fmap): cond, dest, op1 = __pre(i, fmap) result = fmap(op1) - cout = fmap(op1.bit(31)) fmap[dest[16:32]] = stst(cond, result, fmap(dest[16:32])) @@ -433,7 +448,7 @@ def i_SMLABB(i, fmap): cond, dest, Rn, Rm, Ra = __pre(i, fmap) op1 = Rn[0:16] op2 = Rm[0:16] - result = fmap((op1 ** op2) + Ra) + result = fmap((op1**op2) + Ra) fmap[dest] = stst(cond, result, fmap(dest)) overflow = top(1) fmap[V] = stst(cond, overflow, fmap(V)) @@ -443,7 +458,7 @@ def i_SMLABT(i, fmap): cond, dest, Rn, Rm, Ra = __pre(i, fmap) op1 = Rn[0:16] op2 = Rm[16:32] - result = fmap((op1 ** op2) + Ra) + result = fmap((op1**op2) + Ra) fmap[dest] = stst(cond, result, fmap(dest)) overflow = top(1) fmap[V] = stst(cond, overflow, fmap(V)) @@ -453,7 +468,7 @@ def i_SMLATT(i, fmap): cond, dest, Rn, Rm, Ra = __pre(i, fmap) op1 = Rn[16:32] op2 = Rm[16:32] - result = fmap((op1 ** op2) + Ra) + result = fmap((op1**op2) + Ra) fmap[dest] = stst(cond, result, fmap(dest)) overflow = top(1) fmap[V] = stst(cond, overflow, fmap(V)) @@ -463,7 +478,7 @@ def i_SMLATB(i, fmap): cond, dest, Rn, Rm, Ra = __pre(i, fmap) op1 = Rn[16:32] op2 = Rm[0:16] - result = fmap((op1 ** op2) + Ra) + result = fmap((op1**op2) + Ra) fmap[dest] = stst(cond, result, fmap(dest)) overflow = top(1) fmap[V] = stst(cond, overflow, fmap(V)) @@ -491,7 +506,7 @@ def i_SMLADX(i, fmap): def i_SMLAL(i, fmap): cond, RdLo, RdHi, Rn, Rm = __pre(i, fmap) - result = fmap(Rn ** Rm + composer([RdLo, RdHi])) + result = fmap(Rn**Rm + composer([RdLo, RdHi])) fmap[RdLo] = stst(cond, result[0:32], fmap(RdLo)) fmap[RdHi] = stst(cond, result[32:64], fmap(RdHi)) if i.setflags: @@ -503,7 +518,7 @@ def i_SMLALBB(i, fmap): cond, RdLo, RdHi, Rn, Rm = __pre(i, fmap) op1 = Rn[0:16] op2 = Rm[0:16] - result = fmap((op1 ** op2).signextend(64) + composer([RdLo, RdHi])) + result = fmap((op1**op2).signextend(64) + composer([RdLo, RdHi])) fmap[RdLo] = stst(cond, result[0:32], fmap(RdLo)) fmap[RdHi] = stst(cond, result[32:64], fmap(RdHi)) @@ -512,7 +527,7 @@ def i_SMLALBT(i, fmap): cond, RdLo, RdHi, Rn, Rm = __pre(i, fmap) op1 = Rn[0:16] op2 = Rm[16:32] - result = fmap((op1 ** op2).signextend(64) + composer([RdLo, RdHi])) + result = fmap((op1**op2).signextend(64) + composer([RdLo, RdHi])) fmap[RdLo] = stst(cond, result[0:32], fmap(RdLo)) fmap[RdHi] = stst(cond, result[32:64], fmap(RdHi)) @@ -521,7 +536,7 @@ def i_SMLALTT(i, fmap): cond, RdLo, RdHi, Rn, Rm = __pre(i, fmap) op1 = Rn[16:32] op2 = Rm[16:32] - result = fmap((op1 ** op2).signextend(64) + composer([RdLo, RdHi])) + result = fmap((op1**op2).signextend(64) + composer([RdLo, RdHi])) fmap[RdLo] = stst(cond, result[0:32], fmap(RdLo)) fmap[RdHi] = stst(cond, result[32:64], fmap(RdHi)) @@ -530,7 +545,7 @@ def i_SMLALTB(i, fmap): cond, RdLo, RdHi, Rn, Rm = __pre(i, fmap) op1 = Rn[16:32] op2 = Rm[0:16] - result = fmap((op1 ** op2).signextend(64) + composer([RdLo, RdHi])) + result = fmap((op1**op2).signextend(64) + composer([RdLo, RdHi])) fmap[RdLo] = stst(cond, result[0:32], fmap(RdLo)) fmap[RdHi] = stst(cond, result[32:64], fmap(RdHi)) @@ -569,6 +584,7 @@ def i_SMLALTB(i, fmap): # UXTB16 # UXTH + # miscellaneous (4.4.6) def i_BFC(i, fmap): cond, dest, lsb, size = __pre(i, fmap) @@ -627,6 +643,7 @@ def i_CLZ(i, fmap): # MRS # MSR + # load/store (A4.6) def i_LDR(i, fmap): cond, dest, src, sht = __pre(i, fmap, True) diff --git a/amoco/arch/arm/v7/env.py b/amoco/arch/arm/v7/env.py index 8248ea3..6045b67 100644 --- a/amoco/arch/arm/v7/env.py +++ b/amoco/arch/arm/v7/env.py @@ -4,8 +4,12 @@ # Copyright (C) 2006-2011 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -# import expressions: -from amoco.cas.expressions import * +# explicit import from expressions: +from amoco.cas.expressions import reg, slc, top, bit1 +from amoco.cas.expressions import is_reg_flags, is_reg_pc, is_reg_stack + +# also import all (other) expressions as interface +from amoco.cas.expressions import * # noqa: F403 # reference documentation: # "ARM Architecture Reference Manual ARMv7-A and ARMv7-R" (DDI0406B) @@ -109,4 +113,4 @@ cpregs = {} cpregs["p15"] = [reg("c%02d" % x, 32) for x in range(16)] -registers = regs+[pc_,apsr] +registers = regs + [pc_, apsr] diff --git a/amoco/arch/arm/v7/formats.py b/amoco/arch/arm/v7/formats.py index 9754fe4..9ca4ce7 100644 --- a/amoco/arch/arm/v7/formats.py +++ b/amoco/arch/arm/v7/formats.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- -from .env import * -from .utils import * +from amoco.cas.expressions import exp from amoco.arch.core import Formatter - from amoco.ui.render import Token, TokenListJoin +from .env import pc, apsr, CONDITION_AL, CONDITION, internals + def mnemo(i): m = i.mnemonic @@ -17,7 +17,7 @@ def mnemo(i): def regs(i, limit=None): - ops = list(filter(lambda x: isinstance(x,exp),i.operands)) + ops = list(filter(lambda x: isinstance(x, exp), i.operands)) if limit: ops = ops[:limit] return [(Token.Register, "{0}".format(r)) for r in ops] diff --git a/amoco/arch/arm/v7/spec_armv7.py b/amoco/arch/arm/v7/spec_armv7.py index d55d6d5..60361bb 100644 --- a/amoco/arch/arm/v7/spec_armv7.py +++ b/amoco/arch/arm/v7/spec_armv7.py @@ -6,10 +6,16 @@ # spec_xxx files are providers for instruction objects. -from amoco.arch.arm.v7 import env +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_cpu_state, + type_system, +) +from . import env +from .utils import ARMExpandImm, DecodeShift -from amoco.arch.core import * -from .utils import * # ------------------------------------------------------ # amoco ARMv7++ instruction specs: @@ -18,6 +24,9 @@ ISPECS = [] +# ruff: noqa: F811 + + @ispec("32[ .cond(4) 00 1 0000 S Rn(4) Rd(4) imm12(12) ]", mnemonic="AND") @ispec("32[ .cond(4) 00 1 0001 S Rn(4) Rd(4) imm12(12) ]", mnemonic="EOR") @ispec("32[ .cond(4) 00 1 0010 S Rn(4) Rd(4) imm12(12) ]", mnemonic="SUB") @@ -159,7 +168,7 @@ def A_default(obj, S, Rd, imm5, Rm): if imm5 == 0: shift_n = 32 if obj.mnemonic in ("LSR", "ASR") else imm5 if obj.mnemonic == "ROR": - raise InstructionError(obj) # see RRX + raise InstructionError(obj) # see RRX else: shift_n = imm5 obj.operands = [obj.d, obj.m, env.cst(shift_n, 5)] @@ -295,7 +304,7 @@ def A_sreg(obj, Rn, imm5, stype, Rm): @ispec("32[ .cond(4) 00 0 1001 1 Rn(4) 0000 Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="TEQ") @ispec("32[ .cond(4) 00 0 1000 1 Rn(4) 0000 Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="TST") def A_sreg(obj, Rn, Rs, stype, Rm): - if 15 in (Rd, Rm, Rs): + if 15 in (Rn, Rm, Rs): raise InstructionError(obj) obj.n = env.regs[Rn] obj.m = DecodeShift(stype, env.regs[Rm], env.regs[Rs]) @@ -368,14 +377,38 @@ def A_deref(obj, P, U, W, Rn, Rt, imm12): obj.type = type_control_flow -@ispec("32[ .cond(4) 011 P U 0 W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="LDR") -@ispec("32[ .cond(4) 011 P U 1 W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="LDRB") -@ispec("32[ .cond(4) 011 P U 0 W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="STR") -@ispec("32[ .cond(4) 011 P U 1 W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="STRB") -@ispec("32[ .cond(4) 011 0=P U 0 1=W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="LDRT") -@ispec("32[ .cond(4) 011 0=P U 1 1=W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="LDRBT") -@ispec("32[ .cond(4) 011 0=P U 0 1=W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="STRT") -@ispec("32[ .cond(4) 011 0=P U 1 1=W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="STRBT") +@ispec( + "32[ .cond(4) 011 P U 0 W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", + mnemonic="LDR", +) +@ispec( + "32[ .cond(4) 011 P U 1 W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", + mnemonic="LDRB", +) +@ispec( + "32[ .cond(4) 011 P U 0 W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", + mnemonic="STR", +) +@ispec( + "32[ .cond(4) 011 P U 1 W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", + mnemonic="STRB", +) +@ispec( + "32[ .cond(4) 011 0=P U 0 1=W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", + mnemonic="LDRT", +) +@ispec( + "32[ .cond(4) 011 0=P U 1 1=W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", + mnemonic="LDRBT", +) +@ispec( + "32[ .cond(4) 011 0=P U 0 1=W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", + mnemonic="STRT", +) +@ispec( + "32[ .cond(4) 011 0=P U 1 1=W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]", + mnemonic="STRBT", +) def A_deref(obj, P, U, W, Rn, Rt, imm5, stype, Rm): obj.n = env.regs[Rn] obj.t = env.regs[Rt] @@ -402,8 +435,12 @@ def A_deref(obj, P, U, W, Rn, Rt, imm5, stype, Rm): obj.type = type_control_flow -@ispec("32[ .cond(4) 000 P U 1 W 0 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]", mnemonic="LDRD") -@ispec("32[ .cond(4) 000 P U 1 W 0 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]", mnemonic="STRD") +@ispec( + "32[ .cond(4) 000 P U 1 W 0 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]", mnemonic="LDRD" +) +@ispec( + "32[ .cond(4) 000 P U 1 W 0 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]", mnemonic="STRD" +) def A_deref(obj, P, U, W, Rn, Rt, imm4H, imm4L): obj.n = env.regs[Rn] obj.t = env.regs[Rt] @@ -486,14 +523,38 @@ def A_default(obj, Rn, Rd, Rt): obj.type = type_data_processing -@ispec("32[ .cond(4) 000 P U 1 W 1 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]", mnemonic="LDRH") -@ispec("32[ .cond(4) 000 P U 1 W 1 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]", mnemonic="LDRSB") -@ispec("32[ .cond(4) 000 P U 1 W 1 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]", mnemonic="LDRSH") -@ispec("32[ .cond(4) 000 P U 1 W 0 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]", mnemonic="STRH") -@ispec("32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]", mnemonic="LDRHT") -@ispec("32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]", mnemonic="LDRSBT") -@ispec("32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]", mnemonic="LDRSHT") -@ispec("32[ .cond(4) 000 0=P U 1 1=W 0 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]", mnemonic="STRHT") +@ispec( + "32[ .cond(4) 000 P U 1 W 1 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]", + mnemonic="LDRH", +) +@ispec( + "32[ .cond(4) 000 P U 1 W 1 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]", + mnemonic="LDRSB", +) +@ispec( + "32[ .cond(4) 000 P U 1 W 1 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]", + mnemonic="LDRSH", +) +@ispec( + "32[ .cond(4) 000 P U 1 W 0 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]", + mnemonic="STRH", +) +@ispec( + "32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]", + mnemonic="LDRHT", +) +@ispec( + "32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]", + mnemonic="LDRSBT", +) +@ispec( + "32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]", + mnemonic="LDRSHT", +) +@ispec( + "32[ .cond(4) 000 0=P U 1 1=W 0 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]", + mnemonic="STRHT", +) def A_deref(obj, P, U, W, Rn, Rt, imm4H, imm4L): obj.n = env.regs[Rn] obj.t = env.regs[Rt] @@ -518,8 +579,12 @@ def A_deref(obj, P, U, W, Rn, Rt, imm4H, imm4L): @ispec("32[ .cond(4) 000 P U 0 W 1 Rn(4) Rt(4) 0000 1111 Rm(4) ]", mnemonic="LDRSH") @ispec("32[ .cond(4) 000 P U 0 W 0 Rn(4) Rt(4) 0000 1011 Rm(4) ]", mnemonic="STRH") @ispec("32[ .cond(4) 000 0=P U 0 1=W 1 Rn(4) Rt(4) 0000 1011 Rm(4) ]", mnemonic="LDRHT") -@ispec("32[ .cond(4) 000 0=P U 0 1=W 1 Rn(4) Rt(4) 0000 1101 Rm(4) ]", mnemonic="LDRSBT") -@ispec("32[ .cond(4) 000 0=P U 0 1=W 1 Rn(4) Rt(4) 0000 1111 Rm(4) ]", mnemonic="LDRSHT") +@ispec( + "32[ .cond(4) 000 0=P U 0 1=W 1 Rn(4) Rt(4) 0000 1101 Rm(4) ]", mnemonic="LDRSBT" +) +@ispec( + "32[ .cond(4) 000 0=P U 0 1=W 1 Rn(4) Rt(4) 0000 1111 Rm(4) ]", mnemonic="LDRSHT" +) @ispec("32[ .cond(4) 000 0=P U 0 1=W 0 Rn(4) Rt(4) 0000 1011 Rm(4) ]", mnemonic="STRHT") def A_deref(obj, P, U, W, Rn, Rt, Rm): obj.n = env.regs[Rn] @@ -651,7 +716,7 @@ def A_sreg(obj, Rn, Rd, imm5, tb, Rm): @ispec("32[ 1111 01 0 1 U 0=R 01 Rn(4) 1111 imm12(12) ]", mnemonic="PLDW") def instr_PLx(obj, U, R, Rn, imm12): obj.n = env.regs[Rn] - obj.imm32 = cst(imm12, 32) + obj.imm32 = env.cst(imm12, 32) obj.add = U == 1 obj.is_pldw = R == 0 obj.operands = [obj.n, obj.imm32] @@ -659,7 +724,9 @@ def instr_PLx(obj, U, R, Rn, imm12): @ispec("32[ 1111 01 1 1 U 1=R 01 Rn(4) 1111 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="PLD") -@ispec("32[ 1111 01 1 1 U 0=R 01 Rn(4) 1111 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="PLDW") +@ispec( + "32[ 1111 01 1 1 U 0=R 01 Rn(4) 1111 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="PLDW" +) def instr_PLx(obj, U, R, Rn, imm5, stype, Rm): obj.n = env.regs[Rn] obj.m = DecodeShift(stype, env.regs[Rm], env.cst(imm5, 5)) @@ -674,7 +741,7 @@ def instr_PLx(obj, U, R, Rn, imm5, stype, Rm): @ispec("32[ 1111 0100 U 101 Rn(4) 1111 imm12(12) ]", mnemonic="PLI") def instr_PLx(obj, U, Rn, imm12): obj.n = env.regs[Rn] - obj.imm32 = cst(imm12, 32) + obj.imm32 = env.cst(imm12, 32) obj.add = U == 1 obj.operands = [obj.n, obj.imm32] obj.type = type_cpu_state diff --git a/amoco/arch/arm/v7/spec_thumb.py b/amoco/arch/arm/v7/spec_thumb.py index f360397..a87facf 100644 --- a/amoco/arch/arm/v7/spec_thumb.py +++ b/amoco/arch/arm/v7/spec_thumb.py @@ -7,13 +7,20 @@ # spec_xxx files are providers for instruction objects. # These objects are wrapped and created by disasm.py. -from amoco.arch.core import * +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_cpu_state, +) +from amoco.arch.core import ispec, InstructionError -from amoco.arch.arm.v7 import env -from .utils import * +from . import env +from .utils import InITBlock ISPECS = [] +# ruff: noqa: F811 + # ------------------------------------------------------ # amoco THUMB-1 instruction specs: # ------------------------------------------------------ diff --git a/amoco/arch/arm/v7/spec_thumb2.py b/amoco/arch/arm/v7/spec_thumb2.py index 1402125..3751a68 100644 --- a/amoco/arch/arm/v7/spec_thumb2.py +++ b/amoco/arch/arm/v7/spec_thumb2.py @@ -7,16 +7,25 @@ # spec_xxx files are providers for instruction objects. # These objects are wrapped and created by disasm.py. -from amoco.arch.core import * -from amoco.arch.arm.v7 import env -from .utils import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_cpu_state, + type_unpredictable, +) + +from . import env +from .utils import ThumbExpandImm, DecodeShift, BadReg + +ISPECS = [] + +# ruff: noqa: F811 # ------------------------------------------------------ # amoco THUMB2 instruction specs: # ------------------------------------------------------ -ISPECS = [] - @ispec("32[ 0 #imm3(3) Rd(4) #imm8(8) 11110 #i 0 0000 S Rn(4) ]", mnemonic="AND") @ispec("32[ 0 #imm3(3) Rd(4) #imm8(8) 11110 #i 0 0001 S Rn(4) ]", mnemonic="BIC") @@ -65,7 +74,7 @@ def A_default(obj, i, Rn, imm3, Rd, imm8): obj.d = env.regs[Rd] # TODO: manual says its a ZeroExtend here, but need to double check with gdb # cause its looks weird... - obj.imm32 = cst(int(i + imm3 + imm8, 2), 32) + obj.imm32 = env.cst(int(i + imm3 + imm8, 2), 32) obj.operands = [obj.d, obj.n, obj.imm32] if BadReg(Rd): obj.type = type_unpredictable @@ -245,7 +254,7 @@ def A_default(obj): @ispec("32[ 1111 Rd(4) 1 011 Rm(4) 11111 010 1 001 rm(4) ]", mnemonic="REVSH") def A_default(obj, rm, Rd, Rm): assert rm == Rm - obj.d = env.regs[Rn] + obj.d = env.regs[Rd] obj.m = env.regs[Rm] if BadReg(Rd) or BadReg(Rm): raise InstructionError(obj) @@ -532,7 +541,9 @@ def A_deref(obj, Rn, Rt, Rt2, Rd): obj.cond = env.CONDITION_AL -@ispec("32[ Ra(4) Rd(4) 0000 Rm(4) 11111 0110 000 Rn(4) ]", mnemonic="MLA", setflags=False) +@ispec( + "32[ Ra(4) Rd(4) 0000 Rm(4) 11111 0110 000 Rn(4) ]", mnemonic="MLA", setflags=False +) @ispec("32[ Ra(4) Rd(4) 0001 Rm(4) 11111 0110 000 Rn(4) ]", mnemonic="MLS") def A_default(obj, Rn, Ra, Rd, Rm): obj.n = env.regs[Rn] diff --git a/amoco/arch/arm/v7/utils.py b/amoco/arch/arm/v7/utils.py index 7e74a4d..7b19a52 100644 --- a/amoco/arch/arm/v7/utils.py +++ b/amoco/arch/arm/v7/utils.py @@ -140,6 +140,8 @@ def ThumbExpandImm(imm12): tmp = x & 0xFF tmp2 = (tmp << 8) | tmp imm32 = (tmp2 << 16) | tmp2 + else: + raise ValueError(s) return cst(imm32, 32) else: v = cst((1 << 7) | (x & 0x7F), 32) diff --git a/amoco/arch/arm/v8/asm64.py b/amoco/arch/arm/v8/asm64.py index 3f7679a..3a5cec3 100644 --- a/amoco/arch/arm/v8/asm64.py +++ b/amoco/arch/arm/v8/asm64.py @@ -8,9 +8,12 @@ logger = Log(__name__) logger.debug("loading module") -from .env64 import * -from .utils import * -from amoco.cas.utils import * +from amoco.arch.core import InstructionError +from .env64 import pc, r30, C, N, Z, V +from .env64 import CONDITION, bit0, internals +from amoco.cas.expressions import mem, ext, cst, tst, comp, composer, top +from .utils import ROR +from amoco.cas.utils import AddWithCarry, SubWithBorrow def __mem(a, sz, disp=0): @@ -604,42 +607,42 @@ def i_UDIV(i, fmap): def i_SMADDL(i, fmap): fmap[pc] = fmap[pc] + i.length - _x = fmap(i.a + (i.n ** i.m)) + _x = fmap(i.a + (i.n**i.m)) _x.sf = True fmap[i.d] = _x def i_SMSUBL(i, fmap): fmap[pc] = fmap[pc] + i.length - _x = fmap(i.a - (i.n ** i.m)) + _x = fmap(i.a - (i.n**i.m)) _x.sf = True fmap[i.d] = _x def i_UMADDL(i, fmap): fmap[pc] = fmap[pc] + i.length - _x = fmap(i.a + (i.n ** i.m)) + _x = fmap(i.a + (i.n**i.m)) _x.sf = False fmap[i.d] = _x def i_UMSUBL(i, fmap): fmap[pc] = fmap[pc] + i.length - _x = fmap(i.a - (i.n ** i.m)) + _x = fmap(i.a - (i.n**i.m)) _x.sf = False fmap[i.d] = _x def i_SMULH(i, fmap): fmap[pc] = fmap[pc] + i.length - result = fmap(i.n ** i.m) + result = fmap(i.n**i.m) result.sf = True fmap[i.d] = result[64:128] def i_UMULH(i, fmap): fmap[pc] = fmap[pc] + i.length - result = fmap(i.n ** i.m) + result = fmap(i.n**i.m) result.sf = False fmap[i.d] = result[64:128] @@ -703,3 +706,7 @@ def i_TBZ(i, fmap): fmap[pc] = tst( op[i.bitpos : i.bitpos + 1] == 0, fmap[pc] + i.offset, fmap[pc] + i.length ) + + +# expose "microarchitecture" (instructions semantics) +uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) diff --git a/amoco/arch/arm/v8/env64.py b/amoco/arch/arm/v8/env64.py index 2d071e8..8cf42b2 100644 --- a/amoco/arch/arm/v8/env64.py +++ b/amoco/arch/arm/v8/env64.py @@ -5,7 +5,11 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc, cst, top, bit1 +from amoco.cas.expressions import is_reg_flags, is_reg_stack, is_reg_pc + +# import all (other) expressions as interface +from amoco.cas.expressions import * # noqa: F403 # reference documentation: # "ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile, Errata markup (DDI0487A.a_errata_2013_Q3) @@ -89,15 +93,37 @@ pstate = reg("pstate", 64) # in current program status register -N = slc(pstate, 0, 1, ref="N") # negative result from ALU -Z = slc(pstate, 1, 1, ref="Z") # zero flag -C = slc(pstate, 2, 1, ref="C") # carry flag -V = slc(pstate, 3, 1, ref="V") # overflow flag +N = slc(pstate, 31, 1, ref="N") # negative result from ALU +Z = slc(pstate, 30, 1, ref="Z") # zero flag +C = slc(pstate, 29, 1, ref="C") # carry flag +V = slc(pstate, 28, 1, ref="V") # overflow flag + +SS = slc(pstate, 21, 1, ref="SS") # software step +IL = slc(pstate, 20, 1, ref="IL") # illegal execution state +SPSel = slc(pstate, 12, 1, ref="SPSel") + +D = slc(pstate, 9, 1, ref="D") # debug mask +A = slc(pstate, 8, 1, ref="A") # SError mask +I = slc(pstate, 7, 1, ref="I") # IRQ mask +F = slc(pstate, 6, 1, ref="F") # FIQ mask +M = slc(pstate, 0, 5, ref="M") # execution mode is_reg_flags(pstate) is_reg_stack(sp) is_reg_pc(pc) +#exception-specific special regs: +sp_el0 = reg("SP_EL0", 64) +sp_el1 = reg("SP_EL1", 64) +sp_el2 = reg("SP_EL2", 64) +sp_el3 = reg("SP_EL3", 64) +elr_el1 = reg("ELR_EL1", 64) +elr_el2 = reg("ELR_EL2", 64) +elr_el3 = reg("ELR_EL3", 64) +spsr_el1 = reg("SPSR_EL1", 64) +spsr_el2 = reg("SPSR_EL2", 64) +spsr_el3 = reg("SPSR_EL3", 64) + Xregs = [ r0, r1, @@ -167,10 +193,6 @@ wsp, ] -SPSel = slc(pstate, 12, 1, ref="SPSel") -DAIFSet = slc(pstate, 4, 4, ref="DAIFSet") -DAIFClr = slc(pstate, 4, 4, ref="DAIFClr") - CONDITION_EQ = 0x0 # == CONDITION_NE = 0x1 # != CONDITION_CS = 0x2 # >= (unsigned) @@ -216,7 +238,8 @@ } # SIMD and VFP (floating point) extensions: -# NOT IMPLEMENTED + +Vregs = [reg("V%d"%i,128) for i in range(32)] # Coprocessor (CPxx) support: # NOT IMPLEMENTED diff --git a/amoco/arch/arm/v8/formats.py b/amoco/arch/arm/v8/formats.py index 54353c1..3567262 100644 --- a/amoco/arch/arm/v8/formats.py +++ b/amoco/arch/arm/v8/formats.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- -from .env64 import * -from .utils import * +from .env64 import pc, CONDITION from amoco.arch.core import Formatter from amoco.ui.render import Token from amoco.ui.render import TokenListJoin, LambdaTokenListJoin def tok_mnemo(x): - return [(Token.Mnemonic, "{:<12}".format(m.lower()))] + return [(Token.Mnemonic, "{:<12}".format(x.lower()))] def mnemo(i): @@ -24,7 +23,15 @@ def regs(i, limit=None): ops = i.operands if limit: ops = ops[:limit] - return [r.toks() for r in ops] + res = [r.toks() for r in ops] + if 'simd' in i.spec.hook.__module__: + x = {4: '.Q', 3: '.D', 2: '.S', 1: '.H', 0: '.B'}.get(i.scale,'') + for r in res: + for i in range(len(r)): + t = r[i] + if t[1][0]=='V': + r[i] = (t[0],t[1]+x) + return res def deref(i, pos=-2): @@ -74,8 +81,8 @@ def alias_ADD(i): r.pop(0) elif i.setflags and i.d == 0: m = tok_mnemo("cmn") - r = r.pop(0) - return m + TokenListJoin(", ",r) + r = r.pop(0) + return m + TokenListJoin(", ", r) def alias_SUB(i): @@ -92,7 +99,7 @@ def alias_SUB(i): elif i.n == 0: m = tok_mnemo("negs") r.pop(1) - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_AND(i): @@ -101,7 +108,7 @@ def alias_AND(i): if i.setflags and i.d == 0: m = tok_mnemo("tst") r = r[1:] - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_BFM(i): @@ -113,7 +120,7 @@ def alias_BFM(i): else: r[3] = (Token.Constant, str(i.imms - i.immr + 1)) m = tok_mnemo("bfxil") - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_SBFM(i): @@ -134,7 +141,7 @@ def alias_SBFM(i): if i.immr == 31: m = tok_mnemo("sxtw") r.pop(1) - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_UBFM(i): @@ -159,7 +166,7 @@ def alias_UBFM(i): if i.immr == 31: m = tok_mnemo("uxtw") r = r[:2] - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_CSINC(i): @@ -173,8 +180,8 @@ def alias_CSINC(i): else: m = tok_mnemo("cset") r = r[:1] - r.append((Token.Literal,"%s"%CONDITION[i.cond ^ 1][0])) - return m + TokenListJoin(", ",r) + r.append((Token.Literal, "%s" % CONDITION[i.cond ^ 1][0])) + return m + TokenListJoin(", ", r) def alias_CSINV(i): @@ -188,8 +195,8 @@ def alias_CSINV(i): else: m = tok_mnemo("csetm") r = r[:1] - r.append((Token.Literal,"%s"%CONDITION[i.cond ^ 1][0])) - return m + TokenListJoin(", ",r) + r.append((Token.Literal, "%s" % CONDITION[i.cond ^ 1][0])) + return m + TokenListJoin(", ", r) def alias_CSNEG(i): @@ -199,8 +206,8 @@ def alias_CSNEG(i): if i.cond >> 1 != 0b111: m = tok_mnemo("cneg") r = r[:2] - r.append((Token.Literal,"%s"%CONDITION[i.cond ^ 1][0])) - return m + TokenListJoin(", ",r) + r.append((Token.Literal, "%s" % CONDITION[i.cond ^ 1][0])) + return m + TokenListJoin(", ", r) def alias_EXTR(i): @@ -209,7 +216,7 @@ def alias_EXTR(i): if i.n is i.m: m = tok_mnemo("ror") r.pop(1) - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_HINT(i): @@ -223,7 +230,7 @@ def alias_MADD(i): if i.a == 0: m = tok_mnemo("mul") r.pop() - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_SMADDL(i): @@ -232,7 +239,7 @@ def alias_SMADDL(i): if i.a == 0: m = tok_mnemo("smull") r.pop() - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_UMADDL(i): @@ -241,7 +248,7 @@ def alias_UMADDL(i): if i.a == 0: m = tok_mnemo("umull") r.pop() - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_MSUB(i): @@ -250,7 +257,7 @@ def alias_MSUB(i): if i.a == 0: m = tok_mnemo("mneg") r.pop() - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_SMSUBL(i): @@ -259,7 +266,7 @@ def alias_SMSUBL(i): if i.a == 0: m = tok_mnemo("smnegl") r.pop() - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_UMSUBL(i): @@ -268,7 +275,7 @@ def alias_UMSUBL(i): if i.a == 0: m = tok_mnemo("umnegl") r.pop() - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_ORR(i): @@ -277,7 +284,7 @@ def alias_ORR(i): if i.n == 0: m = tok_mnemo("mov") r.pop(1) - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_ORN(i): @@ -286,33 +293,36 @@ def alias_ORN(i): if i.n == 0: m = tok_mnemo("mvn") r.pop(1) - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) def alias_SBC(i): m = mnemo(i) r = regs(i) if i.n == 0: - m = m[0][1].replace("sbc","ngc") + m = m[0][1].replace("sbc", "ngc") m = tok_mnemo(m) r.pop(1) - return m + TokenListJoin(", ",r) + return m + TokenListJoin(", ", r) condreg = lambda i: [(Token.Literal, "'%s'" % CONDITION[i.cond][0])] -allregs = LambdaTokenListJoin(", ",regs) -format_default = [mnemo, LambdaTokenListJoin(", ",regs)] -format_ld_st = [mnemo, lambda i: TokenListJoin(", ",regs(i, -2) + - deref(i, -2))] +allregs = LambdaTokenListJoin(", ", regs) +format_default = [mnemo, LambdaTokenListJoin(", ", regs)] +format_ld_st = [mnemo, lambda i: TokenListJoin(", ", regs(i, -2) + deref(i, -2))] format_B = [mnemo, label] -format_ADR = [mnemo, lambda i: TokenListJoin(", ", i.operands[0].toks() + - label_adr(i))] -format_CBx = [mnemo, lambda i: TokenListJoin(", ", i.t.toks() + label(i, 1))] -format_CCMx = [mnemo, lambda i: TokenListJoin(", ", regs(i, 2)), - lambda i: i.flags.toks(), - condreg] +format_ADR = [mnemo, lambda i: TokenListJoin(", ", i.operands[0].toks() + label_adr(i))] +format_CBx = [mnemo, lambda i: TokenListJoin(", ", i.t.toks() + label(i, 1))] +format_CCMx = [ + mnemo, + lambda i: TokenListJoin(", ", regs(i, 2)), + lambda i: i.flags.toks(), + condreg, +] ARM_V8_full_formats = { + "A64_data_processing_reg": format_default, + "A64_data_processing_imm": format_default, "A64_generic": format_default, "A64_load_store": format_ld_st, "A64_adr": format_ADR, @@ -341,6 +351,9 @@ def alias_SBC(i): "ORR": [alias_ORR], "ORN": [alias_ORN], "SBC": [alias_SBC], + "A64_SIMD_scalar": format_default, + "A64_SIMD_vector": format_default, + "A64_SIMD_ldr": format_ld_st, } ARM_V8_full = Formatter(ARM_V8_full_formats) diff --git a/amoco/arch/arm/v8/spec_armv8.py b/amoco/arch/arm/v8/spec_armv8.py index 7bab071..bbabc93 100644 --- a/amoco/arch/arm/v8/spec_armv8.py +++ b/amoco/arch/arm/v8/spec_armv8.py @@ -9,8 +9,20 @@ from amoco.arch.arm.v8 import env64 as env -from amoco.arch.core import * -from .utils import * +from amoco.cas.expressions import ( + cst, + composer, + reg, +) +from amoco.arch.core import Bits, ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_cpu_state, + type_control_flow, +) +from .utils import ROR + +# ruff: noqa: F811 def DecodeBitMasks(M, targs): @@ -70,7 +82,7 @@ def sp2z(x): @ispec("32[ sf 0 S 11010000 Rm(5) 000000 Rn(5) Rd(5) ]", mnemonic="ADC") @ispec("32[ sf 1 S 11010000 Rm(5) 000000 Rn(5) Rd(5) ]", mnemonic="SBC") -def A64_generic(obj, sf, S, Rm, Rn, Rd): +def A64_data_processing_reg(obj, sf, S, Rm, Rn, Rd): obj.datasize = 64 if (sf == 1) else 32 obj.setflags = S == 1 regs = env.Xregs if sf == 1 else env.Wregs @@ -83,7 +95,7 @@ def A64_generic(obj, sf, S, Rm, Rn, Rd): @ispec("32[ sf 0 S 01011001 Rm(5) option(3) imm3(3) Rn(5) Rd(5) ]", mnemonic="ADD") @ispec("32[ sf 1 S 01011001 Rm(5) option(3) imm3(3) Rn(5) Rd(5) ]", mnemonic="SUB") -def A64_generic(obj, sf, S, Rm, option, imm3, Rn, Rd): +def A64_data_processing_reg(obj, sf, S, Rm, option, imm3, Rn, Rd): obj.datasize = 64 if (sf == 1) else 32 obj.setflags = S == 1 regs = env.Xregs if sf == 1 else env.Wregs @@ -98,7 +110,7 @@ def A64_generic(obj, sf, S, Rm, option, imm3, Rn, Rd): @ispec("32[ sf 0 S 10001 shift(2) imm12(12) Rn(5) Rd(5) ]", mnemonic="ADD") @ispec("32[ sf 1 S 10001 shift(2) imm12(12) Rn(5) Rd(5) ]", mnemonic="SUB") -def A64_generic(obj, sf, S, shift, imm12, Rn, Rd): +def A64_data_processing_imm(obj, sf, S, shift, imm12, Rn, Rd): obj.datasize = 64 if (sf == 1) else 32 obj.setflags = S == 1 regs = env.Xregs if sf == 1 else env.Wregs @@ -117,7 +129,7 @@ def A64_generic(obj, sf, S, shift, imm12, Rn, Rd): @ispec("32[ sf 0 S 01011 shift(2) 0 Rm(5) imm6(6) Rn(5) Rd(5) ]", mnemonic="ADD") @ispec("32[ sf 1 S 01011 shift(2) 0 Rm(5) imm6(6) Rn(5) Rd(5) ]", mnemonic="SUB") -def A64_generic(obj, sf, S, shift, Rm, imm6, Rn, Rd): +def A64_data_processing_reg(obj, sf, S, shift, Rm, imm6, Rn, Rd): obj.datasize = 64 if (sf == 1) else 32 obj.setflags = S == 1 regs = env.Xregs if sf == 1 else env.Wregs @@ -158,7 +170,7 @@ def A64_adr(obj, p, immlo, immhi, Rd): @ispec( "32[ sf 11 100100 N immr(6) imms(6) Rn(5) Rd(5) ]", mnemonic="AND", setflags=True ) -def A64_generic(obj, sf, N, immr, imms, Rn, Rd): +def A64_data_processing_reg(obj, sf, N, immr, imms, Rn, Rd): obj.datasize = 64 if (sf == 1) else 32 regs = env.Xregs if sf == 1 else env.Wregs if sf == 0 and N != 0: @@ -252,7 +264,7 @@ def A64_xBFM(obj, sf, N, immr, imms, Rn, Rd): setflags=True, invert=True, ) -def A64_generic(obj, sf, shift, Rm, imm6, Rn, Rd): +def A64_data_processing_reg(obj, sf, shift, Rm, imm6, Rn, Rd): obj.datasize = 64 if (sf == 1) else 32 regs = env.Xregs if sf == 1 else env.Wregs obj.d = sp2z(regs[Rd]) @@ -271,7 +283,7 @@ def A64_generic(obj, sf, shift, Rm, imm6, Rn, Rd): @ispec("32[ sf 0 0 11010110 Rm(5) 0010 11 Rn(5) Rd(5) ]", mnemonic="RORV") @ispec("32[ sf 0 0 11010110 Rm(5) 0000 11 Rn(5) Rd(5) ]", mnemonic="SDIV") @ispec("32[ sf 0 0 11010110 Rm(5) 0000 10 Rn(5) Rd(5) ]", mnemonic="UDIV") -def A64_generic(obj, sf, Rm, Rn, Rd): +def A64_data_processing_reg(obj, sf, Rm, Rn, Rd): obj.datasize = 64 if (sf == 1) else 32 regs = env.Xregs if sf == 1 else env.Wregs obj.d = sp2z(regs[Rd]) @@ -313,8 +325,8 @@ def A64_msr(obj, op1, CRm, op2): try: obj.pstatefield = { 0b000101: env.SPSel, - 0b011110: env.DAIFSet, - 0b011111: env.DAIFClr, + 0b011110: env.pstate[6:10], + 0b011111: env.pstate[6:10], }[op1 << 3 + op2] except KeyError: raise InstructionError(obj) @@ -322,6 +334,12 @@ def A64_msr(obj, op1, CRm, op2): obj.operands = [obj.pstatefield, obj.imm] obj.type = type_cpu_state +@ispec("32[ 1101010100 0 00 011 0010 0100 op2(2) 0 11111 ]", mnemonic="BTI") +def A64_msr(obj, op2): + obj.targets = {0b00: '', 0b01: 'c', 0b10: 'j', 0b11: 'jc'}[op2] + obj.operands = [obj.targets] + obj.type = type_cpu_state + @ispec("32[ 1101010100 0 1 o0 op1(3) CRn(4) CRm(4) op2(3) Rt(5) ]", mnemonic="MSR") def A64_msr(obj, o0, op1, CRn, CRm, op2, Rt): @@ -362,6 +380,18 @@ def A64_generic(obj, Rn): obj.operands = [obj.n] obj.type = type_control_flow +@ispec("32[ 1101011 Z 0 00 11111 0000 1=A M Rn(5) Rm(5) ]", mnemonic="BRA") +def A64_generic(obj, Z, A, M, Rn, Rm): + obj.Z = Z + obj.use_key_a = M==0 + obj.src_is_sp = (Z==1 and Rm==31) + if Z==0 and Rm!=31: + raise InstructionError + obj.n = sp2z(env.Xregs[Rn]) + obj.m = sp2z(env.Xregs[Rm]) + obj.operands = [obj.n, obj.m] + obj.type = type_control_flow + @ispec("32[ 11010100 001 imm16(16) 000 00 ]", mnemonic="BRK") @ispec("32[ 11010100 101 imm16(16) 000 01 ]", mnemonic="DCPS1") @@ -1166,3 +1196,6 @@ def A64_generic(obj, b5, b40, imm14, Rt): obj.t = sp2z(env.Xregs[Rt]) if b5 == 1 else sp2z(env.Wregs[Rt]) obj.operands = [obj.t, obj.bitpos, obj.offset] obj.type = type_data_processing + +from . import spec_simd +ISPECS += spec_simd.ISPECS diff --git a/amoco/arch/arm/v8/spec_simd.py b/amoco/arch/arm/v8/spec_simd.py new file mode 100644 index 0000000..6c01c30 --- /dev/null +++ b/amoco/arch/arm/v8/spec_simd.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- + +# This code is part of Amoco +# Copyright (C) 2013 Axel Tillequin (bdcht3@gmail.com) +# published under GPLv2 license + +# spec_xxx files are providers for instruction objects. +# These objects are wrapped and created by disasm.py. + +from amoco.arch.arm.v8 import env64 as env + +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, +) + +# ruff: noqa: F811 + +def ExtendReg(r, etype, shift=0): + assert shift >= 0 and shift <= 4 + N = r.size + signed = True if etype & 4 == 0 else False + l = 8 << (etype & 3) + l = min(l, N - shift) + return r[0:l].extend(signed, N) << shift + +def sp2z(x): + if x is env.sp: + return env.xzr + if x is env.wsp: + return env.wzr + return x + +# ------------------------------------------------------ +# amoco ARMv8-A SIMD instruction specs: +# ------------------------------------------------------ + +ISPECS = [] + +@ispec("32[ 0 1 0=U 11110 11 10000 01011 10 Rn(5) Rd(5) ]", mnemonic="ABS") +@ispec("32[ 0 1 0=U 11110 11 11000 11011 10 Rn(5) Rd(5) ]", mnemonic="ADDP") +@ispec("32[ 0 0 0=U 11110 01 10001 10100 00 Rn(5) Rd(5) ]", mnemonic="BFCVT") +def A64_SIMD_scalar(obj, U, Rn, Rd): + obj.datasize = 64 + regs = env.Vregs + obj.n = regs[Rn] + obj.d = regs[Rd] + obj.operands = [obj.d, obj.n] + obj.U = U + obj.type = type_data_processing + +@ispec("32[ 0 Q 0 01110 size(2) 10000 01011 10 Rn(5) Rd(5) ]", mnemonic="ABS") +def A64_SIMD_vector(obj, Q, size, Rn, Rd): + if size==3 and Q==0: + InstructionError + obj.esize = 8<>1)*4) + obj.datasize = 8<128: + raise InstructionError + obj.t = env.Vregs[Rt] + obj.operands = [obj.t, obj.n, obj.offset] + obj.type = type_data_processing + +@ispec( + "32[ size(2) 111 1 01 -1=opc(2) imm12(12) Rn(5) Rt(5) ]", + mnemonic="LDR", + wback=False, + postindex=False, +) +def A64_SIMD_ldr(obj, size, opc, imm12, Rn, Rt): + obj.n = sp2z(env.Xregs[Rn]) + obj.scale = (size + (opc>>1)*4) + obj.datasize = 8<128: + raise InstructionError + obj.t = env.Vregs[Rt] + obj.operands = [obj.t, obj.n, obj.offset] + obj.type = type_data_processing + +@ispec("32[ opc(2) 011 1 00 imm19(19) Rt(5) ]", mnemonic="LDR") +def A64_SIMD_ldr(obj, opc, imm19, Rt): + obj.size = 4<16: + raise InstructionError + obj.offset = env.cst(imm19 << 2, 21).signextend(64) + obj.t = env.Vregs[Rt] + obj.operands = [obj.t, obj.offset] + obj.type = type_data_processing + +@ispec( + "32[ size(2) 111 1 00 -1=opc(2) 1 Rm(5) option(3) S 10 Rn(5) Rt(5) ]", + mnemonic="LDR", +) +def A64_SIMD_ldr(obj, size, opc, Rm, option, S, Rn, Rt): + obj.wback = False + obj.postindex = False + obj.extend_type = option + obj.n = sp2z(env.Xregs[Rn]) + obj.scale = (size + (opc>>1)*4) + obj.shift = obj.scale if S == 1 else 0 + obj.datasize = 8<128 or (option&2 ==0): + raise InstructionError + obj.t = env.Vregs[Rt] + m = sp2z(env.Wregs[Rm]) if option & 1 == 0 else sp2z(env.Xregs[Rm]) + obj.m = ExtendReg(m, option, obj.shift) + obj.operands = [obj.t, obj.n, obj.m] + obj.type = type_data_processing diff --git a/amoco/arch/arm/v8/utils.py b/amoco/arch/arm/v8/utils.py index aff9789..33bede6 100644 --- a/amoco/arch/arm/v8/utils.py +++ b/amoco/arch/arm/v8/utils.py @@ -4,7 +4,7 @@ # Copyright (C) 2006-2011 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from amoco.cas.expressions import * +from amoco.cas.expressions import comp, cst def LSL_C(x, shift): @@ -47,7 +47,7 @@ def ROR_C(x, shift): assert shift >= 0 n = x.size m = shift % n - res = LSR(x, m) | LSL(x, N - m) + res = LSR(x, m) | LSL(x, n - m) return (res, res.bit(n - 1)) diff --git a/amoco/arch/avr/asm.py b/amoco/arch/avr/asm.py index 69dbedd..9f4a83b 100644 --- a/amoco/arch/avr/asm.py +++ b/amoco/arch/avr/asm.py @@ -4,9 +4,12 @@ # Copyright (C) 2014 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from amoco.arch.avr.env import * +from amoco.arch.avr.env import sp, pc, mmregs, R, Z +from amoco.arch.avr.env import cf, zf, nf, vf, sf, hf, tf +from amoco.cas.expressions import ext, composer, tst, cst, ptr, mem, bit0, bit1, top from amoco.cas.mapper import mapper + # ------------------------------------------------------------------------------ # low level functions : def _push_(fmap, x): @@ -21,7 +24,7 @@ def _pop_(fmap, _l): def __pc(f): def pcnpc(i, fmap): - fmap[pc] = fmap[pc] + i.length//2 + fmap[pc] = fmap[pc] + i.length // 2 if len(fmap.conds) > 0: cond = fmap.conds.pop() m = mapper() @@ -41,6 +44,7 @@ def __nopc(f): def __nopc(f): return f.__closure__[0].cell_contents + # flags for arithmetic operations: def __setflags__A(i, fmap, a, b, x, neg=False): fmap[zf] = x == 0 @@ -101,7 +105,8 @@ def i_BREAK(i, fmap): def i_IN(i, fmap): r, port = i.operands port = port.value - fmap[r] = fmap(mmregs.get(port,top(r.size))) + fmap[r] = fmap(mmregs.get(port, top(r.size))) + @__pc def i_OUT(i, fmap): @@ -325,7 +330,7 @@ def i_MUL(i, fmap): dst, src = i.operands a = fmap(dst) b = fmap(src) - x = a ** b + x = a**b fmap[cf] = x[15:16] fmap[zf] = x == 0 fmap[R[0]] = x[0:8] @@ -501,9 +506,9 @@ def i_SPM(i, fmap): @__pc def i_LPM(i, fmap): try: - dst, src = i.operands + dst, _ = i.operands except ValueError: - dst, src = R[0], Z + dst, _ = R[0], Z fmap[dst] = fmap(Z) if i.misc["flg"] == 1: fmap[Z] = fmap(Z + 1) @@ -546,7 +551,7 @@ def i_RET(i, fmap): @__pc def i_RETI(i, fmap): _pop_(fmap, pc) - fmap[i_] = bit1 + fmap[i] = bit1 @__pc diff --git a/amoco/arch/avr/cpu.py b/amoco/arch/avr/cpu.py index 55ed75d..c2e7c91 100644 --- a/amoco/arch/avr/cpu.py +++ b/amoco/arch/avr/cpu.py @@ -1,29 +1,19 @@ # -*- coding: utf-8 -*- -from amoco.arch.avr.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.avr import env +from amoco.arch.avr import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU -instruction_avr = type("instruction_avr", (instruction,), {}) -instruction_avr.set_uarch(uarch) +# define disassembler: +from amoco.arch.avr import spec from amoco.arch.avr.formats import AVR_full +instruction_avr = type("instruction_avr", (instruction,), {}) instruction_avr.set_formatter(AVR_full) -# define disassembler: -from amoco.arch.avr import spec - disassemble = disassembler([spec], iclass=instruction_avr) - -def PC(state=None): - return pc - - -def get_data_endian(): - return 1 # LE +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/avr/env.py b/amoco/arch/avr/env.py index 46ef45a..5ad7f98 100644 --- a/amoco/arch/avr/env.py +++ b/amoco/arch/avr/env.py @@ -5,7 +5,10 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc, ext +from amoco.cas.expressions import is_reg_flags, is_reg_pc, is_reg_stack + +from amoco.cas.expressions import * # noqa: F403 # registers : # ----------- @@ -39,8 +42,8 @@ with is_reg_stack: sp = reg("SP", 16) - spl = slc(sp,0,8,"SPL") - sph = slc(sp,8,8,"SPH") + spl = slc(sp, 0, 8, "SPL") + sph = slc(sp, 8, 8, "SPH") RAMPX = reg("RAMPX", 8) RAMPY = reg("RAMPY", 8) @@ -51,60 +54,64 @@ registers = R + [sp, pc, SREG] mmregs = { - 0x1e: reg("GPIOR0",8), # General Purpose I/O Register 0 - 0x1f: reg("EECR",8), # EEPROM control register:[EERE, EEPE, EEMPE, EERIE, EEPM0, EEPM1, -, -] - 0x20: reg("EEDR",8), # data readout from the EEPROM @ EEAR - 0x21: reg("EEARL",8), # EEPROM address (Low) - 0x22: reg("EEARH",8), # EEPROM address (High) - 0x2a: reg("GPIOR1",8), # General Purpose I/O Register 1 - 0x2b: reg("GPIOR2",8), # General Purpose I/O Register 2 - 0x2c: reg("SPCR",8), - 0x2d: reg("SPSR",8), - 0x2e: reg("SPDR",8), - 0x33: reg("SMCR",8), # Spleep Mode Control Register - 0x35: reg("MCUSR",8), # MCU Control Register - 0x3d: spl, - 0x3e: sph, - 0x3f: SREG, - 0x61: reg("CLKPR",8), # Clock Prescale - 0x64: reg("PRR",8), # Power Reduction - 0x66: reg("OSCCAL",8), # Oscillator Calibration - 0xc6: reg("UDR0",8), + 0x1E: reg("GPIOR0", 8), # General Purpose I/O Register 0 + 0x1F: reg( + "EECR", 8 + ), # EEPROM control register:[EERE, EEPE, EEMPE, EERIE, EEPM0, EEPM1, -, -] + 0x20: reg("EEDR", 8), # data readout from the EEPROM @ EEAR + 0x21: reg("EEARL", 8), # EEPROM address (Low) + 0x22: reg("EEARH", 8), # EEPROM address (High) + 0x2A: reg("GPIOR1", 8), # General Purpose I/O Register 1 + 0x2B: reg("GPIOR2", 8), # General Purpose I/O Register 2 + 0x2C: reg("SPCR", 8), + 0x2D: reg("SPSR", 8), + 0x2E: reg("SPDR", 8), + 0x33: reg("SMCR", 8), # Spleep Mode Control Register + 0x35: reg("MCUSR", 8), # MCU Control Register + 0x3D: spl, + 0x3E: sph, + 0x3F: SREG, + 0x61: reg("CLKPR", 8), # Clock Prescale + 0x64: reg("PRR", 8), # Power Reduction + 0x66: reg("OSCCAL", 8), # Oscillator Calibration + 0xC6: reg("UDR0", 8), } -EECR = mmregs[0x1f] -EERE = slc(EECR,0, 1, "EERE") # EEPROM Read Enable -EEPE = slc(EECR,1, 1, "EEPE") # EEPROM Write Enable -EEMPE = slc(EECR,2, 1, "EEMPE") # EEPROM Master Write Enable -EERIE = slc(EECR,3, 1, "EERIE") # enable EEPROM ready interrupt -EEPM0 = slc(EECR,4, 1, "EEPM0") # EEPROM programming mode: 00=EraseWrite 01:EraseOnly -EEPM1 = slc(EECR,5, 1, "EEPM1") # 10=WriteOnly 11:Reserved +EECR = mmregs[0x1F] +EERE = slc(EECR, 0, 1, "EERE") # EEPROM Read Enable +EEPE = slc(EECR, 1, 1, "EEPE") # EEPROM Write Enable +EEMPE = slc(EECR, 2, 1, "EEMPE") # EEPROM Master Write Enable +EERIE = slc(EECR, 3, 1, "EERIE") # enable EEPROM ready interrupt +EEPM0 = slc(EECR, 4, 1, "EEPM0") # EEPROM programming mode: 00=EraseWrite 01:EraseOnly +EEPM1 = slc(EECR, 5, 1, "EEPM1") # 10=WriteOnly 11:Reserved vectors = [ - ext("RESET",size=8), - ext("INT0",size=8), - ext("INT1",size=8), - ext("PCINT0",size=8), - ext("PCINT1",size=8), - ext("PCINT2",size=8), - ext("WDT",size=8), - ext("TIMER2_COMPA",size=8), - ext("TIMER2_COMPB",size=8), - ext("TIMER2_OVF",size=8), - ext("TIMER1_CAPT",size=8), - ext("TIMER1_COMPA",size=8), - ext("TIMER1_COMPB",size=8), - ext("TIMER1_OVF",size=8), - ext("TIMER0_COMPA",size=8), - ext("TIMER0_COMPB",size=8), - ext("TIMER0_OVF",size=8), - ext("SPI_STC",size=8), - ext("USART_RX",size=8), - ext("USART_UDRE",size=8), - ext("USART_TX",size=8), - ext("ADC",size=8), - ext("EE_READY",size=8), - ext("ANALOG_COMP",size=8), - ext("TWI",size=8), - ext("SPM_READY",size=8), + ext("RESET", size=8), + ext("INT0", size=8), + ext("INT1", size=8), + ext("PCINT0", size=8), + ext("PCINT1", size=8), + ext("PCINT2", size=8), + ext("WDT", size=8), + ext("TIMER2_COMPA", size=8), + ext("TIMER2_COMPB", size=8), + ext("TIMER2_OVF", size=8), + ext("TIMER1_CAPT", size=8), + ext("TIMER1_COMPA", size=8), + ext("TIMER1_COMPB", size=8), + ext("TIMER1_OVF", size=8), + ext("TIMER0_COMPA", size=8), + ext("TIMER0_COMPB", size=8), + ext("TIMER0_OVF", size=8), + ext("SPI_STC", size=8), + ext("USART_RX", size=8), + ext("USART_UDRE", size=8), + ext("USART_TX", size=8), + ext("ADC", size=8), + ext("EE_READY", size=8), + ext("ANALOG_COMP", size=8), + ext("TWI", size=8), + ext("SPM_READY", size=8), ] + +internals = {} diff --git a/amoco/arch/avr/formats.py b/amoco/arch/avr/formats.py index e3a5bcf..a935880 100644 --- a/amoco/arch/avr/formats.py +++ b/amoco/arch/avr/formats.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from .env import * +from .env import mmregs, R, pc, top from amoco.arch.core import Formatter from amoco.ui.render import Token, TokenListJoin @@ -31,14 +31,17 @@ def subf(i, L=args): return subf + def opport(pos): def port(i, pos=pos): o = i.operands[pos] assert o._is_cst r = mmregs[o.value] - return [(Token.Register,"{0}".format(r))] + return [(Token.Register, "{0}".format(r))] + return port + def opreg(pos): def subr(i, pos=pos): o = i.operands[pos] @@ -59,7 +62,7 @@ def opcst(pos): def subc(i, pos=pos): o = i.operands[pos] assert o._is_cst - if o.sf == False: + if o.sf is False: return [(Token.Constant, "0x%x" % o)] return [(Token.Constant, "%+d" % o)] @@ -99,6 +102,7 @@ def subabs(i, pos=pos): return subabs + def format_io(i): L = [] for o in i.operands: @@ -107,12 +111,13 @@ def format_io(i): r = o elif o._is_cst: tt = Token.Memory - r = mmregs.get(o.value,top(8)) - L.append((tt,"{0}".format(r))) - L.append((Token.Literal,', ')) + r = mmregs.get(o.value, top(8)) + L.append((tt, "{0}".format(r))) + L.append((Token.Literal, ", ")) L.pop() return L + def format_mem(i): s = i.misc["mem"] if s == 1: diff --git a/amoco/arch/avr/spec.py b/amoco/arch/avr/spec.py index 61316ed..f772fa8 100644 --- a/amoco/arch/avr/spec.py +++ b/amoco/arch/avr/spec.py @@ -11,9 +11,17 @@ logger = Log(__name__) logger.debug("loading module") -from amoco.arch.core import * +from amoco.arch.core import ispec +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_system, + type_other, +) from amoco.arch.avr import env +# ruff: noqa: F811 + ISPECS = [] diff --git a/amoco/arch/core.py b/amoco/arch/core.py index ec168fa..0fef37a 100644 --- a/amoco/arch/core.py +++ b/amoco/arch/core.py @@ -28,14 +28,47 @@ from functools import reduce import pyparsing as pp -from crysp.bits import Bits, pack, unpack +from crysp.bits import Bits +from crysp.bits import pack, unpack # noqa: F401 from amoco.logger import Log logger = Log(__name__) logger.debug("loading module") -from amoco.ui.render import Token, highlight +from amoco.cas.expressions import reg, regtype +from amoco.ui.render import Token, TokenListJoin +from amoco.ui.views import View + + +class CPU: + def __init__(self, env, asm, disassemble, pc_expr=None, data_endian=1): + # import all environment registers and internals + pc_found = None + for k, v in env.__dict__.items(): + setattr(self, k, v) + if isinstance(v, reg) and v.etype & regtype.PC: + pc_found = v + # expose "microarchitecture" (instructions semantics) + self.uarch = dict( + filter(lambda kv: kv[0].startswith("i_"), asm.__dict__.items()) + ) + self.disassemble = disassemble + self.disassemble.iclass.set_uarch(self.uarch) + if pc_expr is not None: + self.__pc = pc_expr + elif pc_found is not None: + self.__pc = pc_found + else: + logger.error("pc not found") + self.__data_endian = data_endian + + def getPC(self, state=None): + return self.__pc if state is None else state(self.__pc) + + def get_data_endian(self): + return self.__data_endian + type_unpredictable = -1 type_undefined = 0 @@ -58,20 +91,21 @@ class icore(object): """This is the core class for the generic parent instruction class below. - It defines the mandatory API for all instructions. - - Attributes: - bytes (bytes) : instruction's bytes - type (int) : one of (type_data_processing, type_control_flow, - type_cpu_state, type_system, type_other) or - type_undefined (default) or type_unpredictable. - spec (ispec) : the specification that was decoded by the disassembler - to instanciate this instruction. - mnemonic (str) : the mnemonic string as defined by the specification. - operands (list): the list of operands' expressions. - misc (dict) : a defaultdict for passing various arch-dependent infos - (which returns None for undefined keys.) + It defines the mandatory API for all instructions. + + Attributes: + bytes (bytes) : instruction's bytes + type (int) : one of (type_data_processing, type_control_flow, + type_cpu_state, type_system, type_other) or + type_undefined (default) or type_unpredictable. + spec (ispec) : the specification that was decoded by the disassembler + to instanciate this instruction. + mnemonic (str) : the mnemonic string as defined by the specification. + operands (list): the list of operands' expressions. + misc (dict) : a defaultdict for passing various arch-dependent infos + (which returns None for undefined keys.) """ + def __init__(self, istr=b""): self.bytes = bytes(istr) self.type = type_undefined @@ -93,7 +127,7 @@ def typename(self): def __call__(self, fmap): """calls the uarch[mnemonic] semantics function for this instruction - or warns if no semantics is found. + or warns if no semantics is found. """ if self.type in (type_undefined, type_unpredictable): logger.error("%s instruction" % self.typename()) @@ -112,7 +146,6 @@ def length(self): return len(self.bytes) - # instruction class # ----------------- @@ -160,13 +193,12 @@ def set_formatter(cls, f): @staticmethod def formatter(i, toks=False): """default formatter if no formatter has been set, will return - the highlighted list from tokens for raw mnemonic, - and comma-separated operands expressions. + the highlighted list from tokens for raw mnemonic, + and comma-separated operands expressions. """ - t = [(Token.Mnemonic, i.mnemonic)] - t += [(Token.Literal, op) for op in map(str, i.operands[0:1])] - t += [(Token.Literal, ", " + op) for op in map(str, i.operands[1:])] - return t if toks else highlight(t) + t = [(Token.Mnemonic, i.mnemonic), (Token.Column, " ")] + t.extend(TokenListJoin(", ", [(Token.Literal, str(op)) for op in i.operands])) + return t if toks else View.engine.highlight(t) def __str__(self): return self.formatter(i=self) @@ -230,7 +262,9 @@ def __init__( self.iset = iset self.endian = endian # build ispecs tree for each set: - logger.debug("building specs tree for modules %s", [m.__name__ for m in specmodules]) + logger.debug( + "building specs tree for modules %s", [m.__name__ for m in specmodules] + ) # self.indent = 0 self.specs = [self.setup(m.ISPECS) for m in specmodules] # del self.indent @@ -288,11 +322,11 @@ def setup(self, ispecs): def __call__(self, bytestring, **kargs): e = self.endian(**kargs) adjust = lambda x: x.ival - bs = bytestring[0:self.maxlen] + bs = bytestring[0 : self.maxlen] if e == -1: maxsize = self.maxlen * 8 adjust = lambda x: x.ival << (maxsize - x.size) - bs = bytestring[self.maxlen-1::-1] + bs = bytestring[self.maxlen - 1 :: -1] b = adjust(Bits(bs, bitorder=1)) # get organized/optimized tree of specs: fl = self.specs[self.iset(**kargs)] @@ -312,7 +346,7 @@ def __call__(self, bytestring, **kargs): self.__i = i return self(bytestring[s.mask.size // 8 :], **kargs) elif i.spec.pfx == "xdata": - i.xdata(i,**kargs) + i.xdata(i, **kargs) self.__i = None if "address" in kargs: i.address = kargs["address"] @@ -493,7 +527,7 @@ def setup(self, kargs): self.precond = None for k, v in iter(kargs.items()): if k.startswith("_"): - if k=="__obj": + if k == "__obj": self.precond = v else: self.fargs[k] = v @@ -537,10 +571,10 @@ def buildspec(self): loc = d[2] if loc == "*": break - if d[0]!='=': + if d[0] != "=": size += loc if size % 8 != 0: - logger.error("ispec length %d not a multiple of 8 %s" % (size,self.format)) + logger.error("ispec length %d not a multiple of 8 %s" % (size, self.format)) self.fix = Bits(0, size) # values of fixed bits self.mask = Bits(0, size) # location of fixed bits i = 0 @@ -629,7 +663,7 @@ def decode(self, istr, endian=1, i=None, iclass=instruction): i = iclass(bs) else: i.bytes += bs - saved_bytes = i.bytes[:-len(bs)] + saved_bytes = i.bytes[: -len(bs)] i.spec = self # set instruction attributes from directives, and then # call hook function with instruction as first parameter @@ -718,7 +752,7 @@ def __call__(self, i, toks=False): if isinstance(t, str): t = [(Token.Literal, t)] s.extend(t) - return s if toks else highlight(s) + return s if toks else View.engine.highlight(s) # ispec format parser: @@ -772,7 +806,7 @@ def ispec_register(x, module): def test_parser(): while 1: try: - res = raw_input("ispec>") + res = input("ispec>") s = ispec(res, mnemonic="TEST") print(s.ast) return s diff --git a/amoco/arch/dwarf/asm.py b/amoco/arch/dwarf/asm.py index 9ce9bb1..8c29163 100644 --- a/amoco/arch/dwarf/asm.py +++ b/amoco/arch/dwarf/asm.py @@ -4,7 +4,9 @@ # Copyright (C) 2019 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from amoco.arch.dwarf.env import * +from amoco.arch.dwarf.env import sp, op_ptr, stack_elt, WORD +from amoco.cas.expressions import mem, tst + # ------------------------------------------------------------------------------ # low level functions : @@ -157,7 +159,7 @@ def i_DW_OP_abs(i, fmap): @__pc -def i_DW_OP_abs(i, fmap): +def i_DW_OP_neg(i, fmap): x = _pop_(fmap) _push_(fmap, -x) diff --git a/amoco/arch/dwarf/cpu.py b/amoco/arch/dwarf/cpu.py index 4d79e09..6c290ab 100644 --- a/amoco/arch/dwarf/cpu.py +++ b/amoco/arch/dwarf/cpu.py @@ -1,29 +1,19 @@ # -*- coding: utf-8 -*- -from amoco.arch.dwarf.asm import * - -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.dwarf import env +from amoco.arch.dwarf import asm # import specifications: -from amoco.arch.core import instruction, disassembler - -instruction_dwarf = type("instruction_dwarf", (instruction,), {}) -instruction_dwarf.set_uarch(uarch) - +from amoco.arch.core import instruction, disassembler, CPU from amoco.arch.dwarf.formats import DW_full -instruction_dwarf.set_formatter(DW_full) - # define disassembler: from amoco.arch.dwarf import spec +instruction_dwarf = type("instruction_dwarf", (instruction,), {}) +instruction_dwarf.set_formatter(DW_full) + disassemble = disassembler([spec], iclass=instruction_dwarf) disassemble.maxlen = 21 - -def PC(state=None): - return op_ptr - - -def get_data_endian(): - return 1 +cpu = CPU(env, asm, disassemble, env.op_ptr) diff --git a/amoco/arch/dwarf/env.py b/amoco/arch/dwarf/env.py index a6cd1d1..f8ea339 100644 --- a/amoco/arch/dwarf/env.py +++ b/amoco/arch/dwarf/env.py @@ -5,7 +5,9 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, is_reg_pc, is_reg_stack + +from amoco.cas.expressions import * # noqa: F403 # symbols from libgcc/unwind-dw2.c : # ----------------------------------- @@ -21,3 +23,5 @@ stack_elt = reg("stack_elt", 6) registers = [op_ptr, sp, stack_elt] + +internals = {} diff --git a/amoco/arch/dwarf/formats.py b/amoco/arch/dwarf/formats.py index 32395eb..f7d9ac3 100644 --- a/amoco/arch/dwarf/formats.py +++ b/amoco/arch/dwarf/formats.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- -from .env import * from amoco.arch.core import Formatter -from amoco.ui.render import Token, TokenListJoin +from amoco.ui.render import Token def mnemo(i): diff --git a/amoco/arch/dwarf/spec.py b/amoco/arch/dwarf/spec.py index c7865ff..71caf48 100644 --- a/amoco/arch/dwarf/spec.py +++ b/amoco/arch/dwarf/spec.py @@ -11,10 +11,16 @@ logger = Log(__name__) logger.debug("loading module") -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError, pack +from amoco.arch.core import ( + type_data_processing, + type_control_flow, +) from amoco.arch.dwarf import env from amoco.system.utils import read_leb128, read_sleb128 +# ruff: noqa: F811 + ISPECS = [] WORD = env.WORD @@ -76,6 +82,7 @@ def dw_op_leb128(obj, data): for i in range(0x30, 0x50): + @ispec("8>[ {%2x} ]" % i, mnemonic="DW_OP_lit", _num=i - 0x30) def dw_op_lit(obj, _num): obj.operands = [env.cst(_num, WORD)] @@ -93,17 +100,6 @@ def dw_op_addr(obj, data): obj.type = type_data_processing -@ispec("*>[ {f1} enc(8) ~data(*) ]", mnemonic="DW_OP_GNU_encoded_addr") -def dw_op_gnu(obj, enc, data): - sz = env.op_ptr.size - if data.size < sz: - raise InstructionError(obj) - result = XXX - obj.operands = [env.cst(XXX.int(), sz)] - obj.bytes += pack(result) - obj.type = type_data_processing - - @ispec("*>[ {08} ~data(*) ]", mnemonic="DW_OP_const", sz=1, sign=+1) @ispec("*>[ {09} ~data(*) ]", mnemonic="DW_OP_const", sz=1, sign=-1) @ispec("*>[ {0a} ~data(*) ]", mnemonic="DW_OP_const", sz=2, sign=+1) @@ -136,6 +132,7 @@ def dw_op_const(obj, data): for i in range(0x50, 0x70): + @ispec("8>[ {%2x} ]" % i, mnemonic="DW_OP_reg", _num=i - 0x50) def dw_op_reg(obj, _num): sz = env.op_ptr.size @@ -155,6 +152,7 @@ def dw_op_regx(obj, data): for i in range(0x70, 0x90): + @ispec("*>[ {%2x} ~data(*) ]" % i, mnemonic="DW_OP_breg", _num=i - 0x70) def dw_op_breg(obj, data, _num): data = pack(data) diff --git a/amoco/arch/eBPF/asm.py b/amoco/arch/eBPF/asm.py index 514fa59..d5c4511 100644 --- a/amoco/arch/eBPF/asm.py +++ b/amoco/arch/eBPF/asm.py @@ -4,7 +4,8 @@ # Copyright (C) 2017 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * +from .env import pc +from amoco.cas.expressions import top, tst, oper, OP_ASR, OP_LTU, OP_GEU def __npc(i_xxx): diff --git a/amoco/arch/eBPF/cpu.py b/amoco/arch/eBPF/cpu.py index f5681bb..3701bad 100644 --- a/amoco/arch/eBPF/cpu.py +++ b/amoco/arch/eBPF/cpu.py @@ -1,31 +1,20 @@ # -*- coding: utf-8 -*- -from amoco.arch.eBPF.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.eBPF import env +from amoco.arch.eBPF import asm # import specifications: -from amoco.arch.core import instruction, disassembler - -instruction_eBPF = type("instruction_eBPF", (instruction,), {}) -instruction_eBPF.set_uarch(uarch) +from amoco.arch.core import instruction, disassembler, CPU from amoco.arch.eBPF.formats import eBPF_full -instruction_eBPF.set_formatter(eBPF_full) - # define disassembler: from amoco.arch.eBPF import spec -disassemble = disassembler([spec], iclass=instruction_eBPF) - - -def PC(state=None): - return pc - +instruction_eBPF = type("instruction_eBPF", (instruction,), {}) +instruction_eBPF.set_formatter(eBPF_full) -def get_data_endian(): - return 1 +disassemble = disassembler([spec], iclass=instruction_eBPF) -registers = R+[pc] +cpu = CPU(env, asm, disassemble, env.pc) +cpu.registers = env.R + [env.pc] diff --git a/amoco/arch/eBPF/cpu_bpf.py b/amoco/arch/eBPF/cpu_bpf.py index 5a864bf..9140b05 100644 --- a/amoco/arch/eBPF/cpu_bpf.py +++ b/amoco/arch/eBPF/cpu_bpf.py @@ -1,32 +1,21 @@ # -*- coding: utf-8 -*- -from amoco.arch.eBPF.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.eBPF import env +from amoco.arch.eBPF import asm # import specifications: -from amoco.arch.core import instruction, disassembler - -instruction_BPF = type("instruction_BPF", (instruction,), {}) -instruction_BPF.set_uarch(uarch) +from amoco.arch.core import instruction, disassembler, CPU # we use the same formatter has eBPF... from amoco.arch.eBPF.formats import eBPF_full -instruction_BPF.set_formatter(eBPF_full) - # define disassembler with spec_bpf module: from amoco.arch.eBPF import spec_bpf -disassemble = disassembler([spec_bpf], iclass=instruction_BPF) - - -def PC(state=None): - return pc - +instruction_BPF = type("instruction_BPF", (instruction,), {}) +instruction_BPF.set_formatter(eBPF_full) -def get_data_endian(): - return 1 +disassemble = disassembler([spec_bpf], iclass=instruction_BPF) -registers = [A,X]+M+[pc] +cpu = CPU(env, asm, disassemble, env.pc) +cpu.registers = [env.A, env.X] + env.M + [env.pc] diff --git a/amoco/arch/eBPF/env.py b/amoco/arch/eBPF/env.py index 44f9028..5c004b6 100644 --- a/amoco/arch/eBPF/env.py +++ b/amoco/arch/eBPF/env.py @@ -5,7 +5,9 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc, is_reg_pc, is_reg_stack + +from amoco.cas.expressions import * # noqa: F403 # reference documentation: # https://www.kernel.org/doc/Documentation/networking/filter.txt @@ -15,6 +17,8 @@ A = reg("A", 32) X = reg("X", 32) M = [reg("M[%02d]" % i, 32) for i in range(16)] + + # bpf extensions: def skb(field=""): if not field: @@ -45,3 +49,4 @@ def skb(field=""): pc = reg("pc", 64) is_reg_pc(pc) +internals = {} diff --git a/amoco/arch/eBPF/formats.py b/amoco/arch/eBPF/formats.py index d7d2939..3403590 100644 --- a/amoco/arch/eBPF/formats.py +++ b/amoco/arch/eBPF/formats.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- -from .env import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from amoco.arch.core import Formatter +from amoco.ui.render import Token def mnemo(i): diff --git a/amoco/arch/eBPF/spec.py b/amoco/arch/eBPF/spec.py index 3e89b38..b2348af 100644 --- a/amoco/arch/eBPF/spec.py +++ b/amoco/arch/eBPF/spec.py @@ -9,7 +9,14 @@ from amoco.arch.eBPF import env -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_other, +) + +# ruff: noqa: F811 # ------------------------------------------------------- # instruction eBPF decoders @@ -20,6 +27,7 @@ ISPECS = [] + # ALU_32 instructions: @ispec("64>[ 001 s 0000 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="add") @ispec("64>[ 001 s 1000 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="sub") @@ -165,14 +173,46 @@ def ebpf_ld64_(obj, dreg, sreg, off, imm, unused, imm2): # ABS/IND LOAD instructions: -@ispec("64>[ 000 00=sz(2) 100 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="ldw", _abs=True) -@ispec("64>[ 000 01=sz(2) 100 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="ldb", _abs=True) -@ispec("64>[ 000 10=sz(2) 100 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="ldh", _abs=True) -@ispec("64>[ 000 11=sz(2) 100 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="lddw", _abs=True) -@ispec("64>[ 000 00=sz(2) 010 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="ldw", _abs=False) -@ispec("64>[ 000 01=sz(2) 010 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="ldb", _abs=False) -@ispec("64>[ 000 10=sz(2) 010 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="ldh", _abs=False) -@ispec("64>[ 000 11=sz(2) 010 dreg(4) sreg(4) off(16) ~imm(32) ]", mnemonic="lddw", _abs=False) +@ispec( + "64>[ 000 00=sz(2) 100 dreg(4) sreg(4) off(16) ~imm(32) ]", + mnemonic="ldw", + _abs=True, +) +@ispec( + "64>[ 000 01=sz(2) 100 dreg(4) sreg(4) off(16) ~imm(32) ]", + mnemonic="ldb", + _abs=True, +) +@ispec( + "64>[ 000 10=sz(2) 100 dreg(4) sreg(4) off(16) ~imm(32) ]", + mnemonic="ldh", + _abs=True, +) +@ispec( + "64>[ 000 11=sz(2) 100 dreg(4) sreg(4) off(16) ~imm(32) ]", + mnemonic="lddw", + _abs=True, +) +@ispec( + "64>[ 000 00=sz(2) 010 dreg(4) sreg(4) off(16) ~imm(32) ]", + mnemonic="ldw", + _abs=False, +) +@ispec( + "64>[ 000 01=sz(2) 010 dreg(4) sreg(4) off(16) ~imm(32) ]", + mnemonic="ldb", + _abs=False, +) +@ispec( + "64>[ 000 10=sz(2) 010 dreg(4) sreg(4) off(16) ~imm(32) ]", + mnemonic="ldh", + _abs=False, +) +@ispec( + "64>[ 000 11=sz(2) 010 dreg(4) sreg(4) off(16) ~imm(32) ]", + mnemonic="lddw", + _abs=False, +) def ebpf_ld_(obj, sz, dreg, sreg, off, imm, _abs): size = {0: 32, 1: 16, 2: 8, 3: 64}[sz] dst = env.R[0] diff --git a/amoco/arch/eBPF/spec_bpf.py b/amoco/arch/eBPF/spec_bpf.py index be1ed63..1d23ae2 100644 --- a/amoco/arch/eBPF/spec_bpf.py +++ b/amoco/arch/eBPF/spec_bpf.py @@ -9,7 +9,13 @@ from amoco.arch.eBPF import env -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, +) + +# ruff: noqa: F811 # ------------------------------------------------------- # instruction BPF decoders @@ -20,6 +26,7 @@ ISPECS = [] + # BPF_ALU (0x4) instructions: @ispec("64>[ 001 s 0000 {00} jt(8) jf(8) ~k(32) ]", mnemonic="add") @ispec("64>[ 001 s 1000 {00} jt(8) jf(8) ~k(32) ]", mnemonic="sub") diff --git a/amoco/arch/gas.py b/amoco/arch/gas.py index 17c9d71..4a71fb2 100644 --- a/amoco/arch/gas.py +++ b/amoco/arch/gas.py @@ -405,13 +405,13 @@ def __makelist(self, p): def p_statements(self, p): r"""statements : statements stmt - | stmt""" + | stmt""" p[0] = self.blks def p_endstmt(self, p): - r"""endstmt : ';' - | eol - | comment """ + r"""endstmt : ';' + | eol + | comment""" pass def p_stmt_empty(self, p): @@ -440,7 +440,7 @@ def p_key_directive(self, p): def p_key_asign(self, p): r"""key : symbol '=' arg endstmt - | directive '=' arg endstmt""" + | directive '=' arg endstmt""" p[0] = Gas.Directive(".set", [p[1], p[3]]) def p_key_instr(self, p): @@ -449,28 +449,28 @@ def p_key_instr(self, p): def p_instruction(self, p): r"""instruction : symbol isymbol - | symbol """ + | symbol""" p[0] = " ".join(p[1:]) def p_labels(self, p): r"""labels : labels label - | label""" + | label""" self.__makelist(p) def p_label(self, p): - r"""label : symbol ':' """ + r"""label : symbol ':'""" p[0] = p[1] def p_args(self, p): r"""args : args ',' arg - | arg - | """ + | arg + |""" self.__makelist(p) def p_arg_1(self, p): r"""arg : string - | flonum - | expr""" + | flonum + | expr""" p[0] = p[1] def p_arg_at(self, p): @@ -479,8 +479,8 @@ def p_arg_at(self, p): def p_expr2(self, p): r"""expr : expr op term""" - a = p[1] - b = p[3] + a = p[1] # noqa: F841 + b = p[3] # noqa: F841 p[0] = eval("a %s b" % p[2]) def p_expr1(self, p): @@ -489,51 +489,51 @@ def p_expr1(self, p): def p_op_arith(self, p): r"""op : '+' - | '-' - | '*' - | '/' - | '%' - | shl - | shr""" + | '-' + | '*' + | '/' + | '%' + | shl + | shr""" p[0] = p[1] def p_op_bit(self, p): r"""op : '^' - | '|' - | '&' - | AND - | OR""" + | '|' + | '&' + | AND + | OR""" p[0] = p[1] def p_op_comp(self, p): r"""op : '<' - | '>' - | eq - | neq - | leq - | geq""" + | '>' + | eq + | neq + | leq + | geq""" p[0] = p[1] def p_term_unary(self, p): r"""term : '~' term %prec UNARYOP - | '-' term %prec UNARYOP""" + | '-' term %prec UNARYOP""" if p[1] == "~": p[0] = ~p[2] else: p[0] = -p[2] def p_term_expr(self, p): - r"""term : '(' expr ')' """ + r"""term : '(' expr ')'""" p[0] = p[2] def p_term_symbol(self, p): r"""term : symbol - | directive""" + | directive""" p[0] = expr.reg(p[1]) def p_term_number(self, p): r"""term : integer - | character""" + | character""" p[0] = expr.cst(p[1]) def p_error(self, p): @@ -558,7 +558,7 @@ def parse(self, data): except AttributeError: self.lexer.build(reflags=lex.re.UNICODE) self.parser.build() - except: + except Exception: logger.warning("unexpected parser error") return None try: @@ -569,5 +569,5 @@ def parse(self, data): return L def read(self, filename): - with file(filename, "r") as f: + with open(filename, "r") as f: return self.parse(f.read()) diff --git a/amoco/arch/io.py b/amoco/arch/io.py index ba26cc0..6ebb020 100644 --- a/amoco/arch/io.py +++ b/amoco/arch/io.py @@ -1,14 +1,14 @@ -from amoco.cas.expressions import top +from amoco.cas.expressions import top, cst from types import MethodType from amoco.logger import Log logger = Log(__name__) logger.debug("loading module") -class DefineIO: - def __init__(self,port,name=None): - self.io = IO(port,name) +class DefineIO: + def __init__(self, port, name=None): + self.io = IO(port, name) def __enter__(self): return self @@ -17,26 +17,33 @@ def __exit__(self, exc_type, exc_value, traceback): IO.ports[self.io.port] = self.io def In(self, func): - self.io.In = MethodType(func,self.io) + self.io.In = MethodType(func, self.io) return func def Out(self, func): - self.io.Out = MethodType(func,self.io) + self.io.Out = MethodType(func, self.io) return func + class IO: ports = {} + @classmethod - def get_port(cls,port): - return cls.ports.get(port,cls(port)) + def get_port(cls, port): + if isinstance(port, cst): + port = port.v + return cls.ports.get(port, cls(port)) - def __init__(self,port,name=None): + def __init__(self, port, name=None): self.port = port - self.name = name or "IO#0x%x"%port - def In(self,env,dl): - logger.warning("undefined %s IN"%str(self)) - return top(dl*8) - def Out(self,env,src): - logger.warning("undefined %s OUT (%s)"%(str(self),src)) + self.name = name or "IO#0x%x" % port + + def In(self, env, dl): + logger.warning("undefined %s IN" % str(self)) + return top(dl * 8) + + def Out(self, env, src): + logger.warning("undefined %s OUT (%s)" % (str(self), src)) + def __str__(self): return self.name diff --git a/amoco/arch/mips/cpu_r3000.py b/amoco/arch/mips/cpu_r3000.py index ccd998e..78f1fea 100644 --- a/amoco/arch/mips/cpu_r3000.py +++ b/amoco/arch/mips/cpu_r3000.py @@ -1,31 +1,25 @@ # -*- coding: utf-8 -*- -from amoco.arch.mips.r3000.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.mips.r3000 import env +from amoco.arch.mips.r3000 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_r3000 = type("instruction_r3000", (instruction,), {}) -instruction_r3000.set_uarch(uarch) from amoco.arch.mips.r3000.formats import MIPS_full -from amoco.arch.mips.r3000.formats import MIPS_synthetic instruction_r3000.set_formatter(MIPS_full) # define disassembler: from amoco.arch.mips.r3000 import spec -endian = lambda: -1 -disassemble = disassembler([spec], iclass=instruction_r3000,endian=endian) +def endian(): + return -1 -def PC(state=None): - return pc +disassemble = disassembler([spec], iclass=instruction_r3000, endian=endian) -def get_data_endian(): - return -1 # BE +cpu = CPU(env, asm, disassemble, pc_expr=env.pc, data_endian=-1) diff --git a/amoco/arch/mips/cpu_r3000LE.py b/amoco/arch/mips/cpu_r3000LE.py index f2afba6..53441cc 100644 --- a/amoco/arch/mips/cpu_r3000LE.py +++ b/amoco/arch/mips/cpu_r3000LE.py @@ -1,18 +1,14 @@ # -*- coding: utf-8 -*- -from amoco.arch.mips.r3000.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.mips.r3000 import env +from amoco.arch.mips.r3000 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_r3000 = type("instruction_r3000", (instruction,), {}) -instruction_r3000.set_uarch(uarch) from amoco.arch.mips.r3000.formats import MIPS_full -from amoco.arch.mips.r3000.formats import MIPS_synthetic instruction_r3000.set_formatter(MIPS_full) @@ -21,10 +17,4 @@ disassemble = disassembler([spec], iclass=instruction_r3000) - -def PC(state=None): - return pc - - -def get_data_endian(): - return 1 # LE +cpu = CPU(env, asm, disassemble, pc_expr=env.pc) diff --git a/amoco/arch/mips/r3000/asm.py b/amoco/arch/mips/r3000/asm.py index cf2ebc3..1d25ea2 100644 --- a/amoco/arch/mips/r3000/asm.py +++ b/amoco/arch/mips/r3000/asm.py @@ -4,27 +4,30 @@ # Copyright (C) 2020 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * - -from amoco.cas.utils import * +from .env import pc, npc, ra, zero, HI, LO, bit0, bit1 +from amoco.cas.expressions import comp, composer, cst, mem, ext, tst, top # ------------------------------------------------------------------------------ # helpers and decorators : + def __npc(i_xxx): def pcnpc(ins, fmap): fmap[pc] = fmap[npc] fmap[npc] = fmap[npc] + ins.length i_xxx(ins, fmap) + return pcnpc + # i_xxx is the translation of MIPS-R3000 instruction xxx. # ------------------------------------------------------------------------------ + @__npc def i_ADD(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1+src2) + _v = fmap(src1 + src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v @@ -33,76 +36,84 @@ def i_ADD(ins, fmap): @__npc def i_SUB(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1-src2) + _v = fmap(src1 - src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_SUBU(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1-src2) + _v = fmap(src1 - src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_AND(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1&src2) + _v = fmap(src1 & src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_OR(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1|src2) + _v = fmap(src1 | src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_NOR(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(~(src1|src2)) + _v = fmap(~(src1 | src2)) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_XOR(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1^src2) + _v = fmap(src1 ^ src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + i_ADDI = i_ADDIU = i_ADDU = i_ADD -i_SUBU = i_SUB i_ANDI = i_AND -i_ORI = i_OR +i_ORI = i_OR i_XORI = i_XOR -def i_J(ins,fmap): + +def i_J(ins, fmap): t = ins.operands[0] - target = composer([cst(0,2),t,fmap(pc)[28:32]]) + target = composer([cst(0, 2), t, fmap(pc)[28:32]]) _v = fmap(npc) fmap.update_delayed() fmap[pc] = _v fmap[npc] = target -def i_JAL(ins,fmap): + +def i_JAL(ins, fmap): t = ins.operands[0] - target = composer([cst(0,2),t,fmap(pc)[28:32]]) + target = composer([cst(0, 2), t, fmap(pc)[28:32]]) _v = fmap(npc) fmap.update_delayed() fmap[pc] = _v - fmap[ra] = _v+4 + fmap[ra] = _v + 4 fmap[npc] = target + @__npc -def i_JALR(ins,fmap): +def i_JALR(ins, fmap): rd, rs = ins.operands _v = fmap(npc) target = fmap(rs) @@ -111,118 +122,136 @@ def i_JALR(ins,fmap): fmap[rd] = _v fmap[npc] = target + @__npc -def i_JR(ins,fmap): +def i_JR(ins, fmap): rs = ins.operands[0] target = fmap(rs) fmap.update_delayed() fmap[npc] = target + @__npc -def i_BEQ(ins,fmap): +def i_BEQ(ins, fmap): rs, rt, offset = ins.operands - cond = (fmap(rs)==fmap(rt)) + cond = fmap(rs) == fmap(rt) fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BNE(ins,fmap): +def i_BNE(ins, fmap): rs, rt, offset = ins.operands - cond = (fmap(rs)!=fmap(rt)) + cond = fmap(rs) != fmap(rt) fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BGEZ(ins,fmap): +def i_BGEZ(ins, fmap): rs, offset = ins.operands - cond = fmap(rs.bit(31))==bit0 + cond = fmap(rs.bit(31)) == bit0 fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BGEZAL(ins,fmap): +def i_BGEZAL(ins, fmap): rs, offset = ins.operands - cond = fmap(rs.bit(31))==bit0 + cond = fmap(rs.bit(31)) == bit0 fmap.update_delayed() fmap[ra] = fmap(npc) - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BGTZ(ins,fmap): +def i_BGTZ(ins, fmap): rs, offset = ins.operands - cond = fmap( (rs.bit(31)==bit0) & (rs!=zero) ) + cond = fmap((rs.bit(31) == bit0) & (rs != zero)) fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BLEZ(ins,fmap): +def i_BLEZ(ins, fmap): rs, offset = ins.operands - cond = fmap( (rs.bit(31)==bit1) | (rs==zero) ) + cond = fmap((rs.bit(31) == bit1) | (rs == zero)) fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BLTZ(ins,fmap): +def i_BLTZ(ins, fmap): rs, offset = ins.operands - cond = fmap(rs.bit(31))==bit1 + cond = fmap(rs.bit(31)) == bit1 fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BLTZAL(ins,fmap): +def i_BLTZAL(ins, fmap): rs, offset = ins.operands - cond = fmap(rs.bit(31))==bit1 + cond = fmap(rs.bit(31)) == bit1 fmap.update_delayed() fmap[ra] = fmap(npc) - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BREAK(ins,fmap): - ext("BREAK").call(fmap,code=ins.code) +def i_BREAK(ins, fmap): + ext("BREAK").call(fmap, code=ins.code) + @__npc def i_CFC(ins, fmap): rt, rd = ins.operands - ext("CFC%d"%(ins.z)).call(fmap,rt=rt,rd=rd) + ext("CFC%d" % (ins.z)).call(fmap, rt=rt, rd=rd) + @__npc def i_MFC(ins, fmap): rt, rd = ins.operands - ext("MFC%d"%(ins.z)).call(fmap,rt=rt,rd=rd) + ext("MFC%d" % (ins.z)).call(fmap, rt=rt, rd=rd) + @__npc def i_COP(ins, fmap): fun = ins.cofun - ext("COP%d"%(ins.z)).call(fmap,cofun=fun) + ext("COP%d" % (ins.z)).call(fmap, cofun=fun) + @__npc def i_CTC(ins, fmap): rt, rd = ins.operands - ext("CTC%d"%(ins.z)).call(fmap,rd=rd,rt=rt) + ext("CTC%d" % (ins.z)).call(fmap, rd=rd, rt=rt) + @__npc def i_MTC(ins, fmap): rt, rd = ins.operands - ext("MTC%d"%(ins.z)).call(fmap,rd=rd,rt=rt) + ext("MTC%d" % (ins.z)).call(fmap, rd=rd, rt=rt) + @__npc def i_LWC(ins, fmap): rt, base, offset = ins.operands - data = mem(base+offset,32) - ext("LWC%d"%(ins.z)).call(fmap,rt=rt,data=data) + data = mem(base + offset, 32) + ext("LWC%d" % (ins.z)).call(fmap, rt=rt, data=data) + @__npc def i_SWC(ins, fmap): rt, base, offset = ins.operands - addr = fmap(base+offset) - ext("SWC%d"%(ins.z)).call(fmap,rt=rt,addr=addr) + addr = fmap(base + offset) + ext("SWC%d" % (ins.z)).call(fmap, rt=rt, addr=addr) + @__npc def i_DIV(ins, fmap): rs, rt = ins.operands - if fmap(rt!=zero): - _v_hi = fmap(rs/rt) - _v_lo = fmap(rs%rt) + if fmap(rt != zero): + _v_hi = fmap(rs / rt) + _v_lo = fmap(rs % rt) fmap.update_delayed() fmap[HI] = _v_hi fmap[LO] = _v_lo @@ -231,8 +260,10 @@ def i_DIV(ins, fmap): fmap[HI] = top(32) fmap[LO] = top(32) + i_DIVU = i_DIV + @__npc def i_MULT(ins, fmap): rs, rt = ins.operands @@ -241,186 +272,206 @@ def i_MULT(ins, fmap): fmap[LO] = res[0:32] fmap[HI] = res[32:64] + i_MULTU = i_MULT + @__npc def i_LH(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,16)).signextend(32) + addr = base + src + _v = fmap(mem(addr, 16)).signextend(32) fmap.update_delayed() if dst is not zero: fmap.delayed(dst, _v) + @__npc def i_LHU(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,16)).zeroextend(32) + addr = base + src + _v = fmap(mem(addr, 16)).zeroextend(32) fmap.update_delayed() if dst is not zero: fmap.delayed(dst, _v) + @__npc def i_LUI(ins, fmap): dst, src1 = ins.operands - _v = src1.zeroextend(32)<<16 + _v = src1.zeroextend(32) << 16 fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_LW(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,32)) + addr = base + src + _v = fmap(mem(addr, 32)) fmap.update_delayed() if dst is not zero: fmap.delayed(dst, _v) + @__npc def i_LWL(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v_b3 = fmap(mem(addr,8)) - cond1 = (addr%4)!=0 - _v_b2 = fmap(tst(cond1,mem(addr-1,8),dst[16:24])) - addr = addr - 1 - cond2 = cond1 & ((addr%4)!=0) - _v_b1 = fmap(tst(cond2,mem(addr-1,8),dst[8:16])) + addr = base + src + _v_b3 = fmap(mem(addr, 8)) + cond1 = (addr % 4) != 0 + _v_b2 = fmap(tst(cond1, mem(addr - 1, 8), dst[16:24])) + addr = addr - 1 + cond2 = cond1 & ((addr % 4) != 0) + _v_b1 = fmap(tst(cond2, mem(addr - 1, 8), dst[8:16])) _v_b0 = fmap(dst[0:8]) fmap.update_delayed() if dst is not zero: _v = comp(dst.size) _v[24:32] = _v_b3 _v[16:24] = _v_b2 - _v[ 8:16] = _v_b1 - _v[ 0: 8] = _v_b0 + _v[8:16] = _v_b1 + _v[0:8] = _v_b0 fmap.delayed(dst, _v.simplify()) + @__npc def i_LWR(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v_b0 = fmap(mem(addr,8)) - addr = addr + 1 - cond1 = (addr%4)!=0 - _v_b1 = fmap(tst(cond1,mem(addr,8),dst[8:16])) - addr = addr + 1 - cond2 = cond1 & ((addr%4)!=0) - _v_b2 = fmap(tst(cond2,mem(addr,8),dst[16:24])) + addr = base + src + _v_b0 = fmap(mem(addr, 8)) + addr = addr + 1 + cond1 = (addr % 4) != 0 + _v_b1 = fmap(tst(cond1, mem(addr, 8), dst[8:16])) + addr = addr + 1 + cond2 = cond1 & ((addr % 4) != 0) + _v_b2 = fmap(tst(cond2, mem(addr, 8), dst[16:24])) _v_b3 = fmap(dst[24:32]) fmap.update_delayed() if dst is not zero: _v = comp(dst.size) - _v[0 : 8] = _v_b0 - _v[8 :16] = _v_b1 + _v[0:8] = _v_b0 + _v[8:16] = _v_b1 _v[16:24] = _v_b2 _v[24:32] = _v_b3 fmap.delayed(dst, _v.simplify()) + @__npc def i_SWL(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) val = fmap(src) fmap.update_delayed() - fmap[mem(addr,8)] = val[24:32] - cond1 = (addr%4)!=0 - fmap[mem(addr-1,8)] = tst(cond1,val[16:24],fmap[mem(addr-1,8)]) + fmap[mem(addr, 8)] = val[24:32] + cond1 = (addr % 4) != 0 + fmap[mem(addr - 1, 8)] = tst(cond1, val[16:24], fmap[mem(addr - 1, 8)]) addr = addr - 1 - cond2 = cond1 & ((addr%4)!=0) - fmap[mem(addr-1,8)] = tst(cond2,val[8:16],fmap[mem(addr-1,8)]) + cond2 = cond1 & ((addr % 4) != 0) + fmap[mem(addr - 1, 8)] = tst(cond2, val[8:16], fmap[mem(addr - 1, 8)]) + @__npc def i_SWR(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) val = fmap(src) fmap.update_delayed() - fmap[mem(addr,8)] = val[0:8] + fmap[mem(addr, 8)] = val[0:8] addr = addr + 1 - cond1 = (addr%4)!=0 - fmap[mem(addr,8)] = tst(cond1,val[8:16],fmap[mem(addr,8)]) + cond1 = (addr % 4) != 0 + fmap[mem(addr, 8)] = tst(cond1, val[8:16], fmap[mem(addr, 8)]) addr = addr + 1 - cond2 = cond1 & ((addr%4)!=0) - fmap[mem(addr,8)] = tst(cond2,val[16:24],fmap[mem(addr,8)]) + cond2 = cond1 & ((addr % 4) != 0) + fmap[mem(addr, 8)] = tst(cond2, val[16:24], fmap[mem(addr, 8)]) + @__npc def i_LB(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,8)).signextend(32) + addr = base + src + _v = fmap(mem(addr, 8)).signextend(32) fmap.update_delayed() if dst is not zero: fmap.delay(dst, _v) + @__npc def i_LBU(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,8)).zeroextend(32) + addr = base + src + _v = fmap(mem(addr, 8)).zeroextend(32) fmap.update_delayed() if dst is not zero: fmap.delay(dst, _v) + @__npc -def i_MFHI(ins,fmap): +def i_MFHI(ins, fmap): dst = ins.operands[0] _v = fmap(HI) fmap.update_delayed() fmap[dst] = _v + @__npc -def i_MFLO(ins,fmap): +def i_MFLO(ins, fmap): dst = ins.operands[0] _v = fmap(LO) fmap.update_delayed() fmap[dst] = _v + @__npc -def i_MTHI(ins,fmap): +def i_MTHI(ins, fmap): src = ins.operands[0] _v = fmap(src) fmap.update_delayed() fmap[HI] = _v + @__npc -def i_MTLO(ins,fmap): +def i_MTLO(ins, fmap): src = ins.operands[0] _v = fmap(src) fmap.update_delayed() fmap[LO] = _v + @__npc def i_SB(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) fmap.update_delayed() - fmap[mem(addr,8)] = fmap(src[0:8]) + fmap[mem(addr, 8)] = fmap(src[0:8]) + @__npc def i_SH(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) fmap.update_delayed() - fmap[mem(addr,16)] = fmap(src[0:16]) + fmap[mem(addr, 16)] = fmap(src[0:16]) + @__npc def i_SW(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) fmap.update_delayed() - fmap[mem(addr,32)] = fmap(src) + fmap[mem(addr, 32)] = fmap(src) + @__npc def i_SLL(ins, fmap): rt, rd, sa = ins.operands - res = fmap(rt<>src2).unsigned() + _v = fmap(src1 >> src2).unsigned() fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_SRLV(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1>>src2).unsigned() + _v = fmap(src1 >> src2).unsigned() fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_SYSCALL(ins, fmap): - ext("SYSCALL").call(fmap,code=ins.code) + ext("SYSCALL").call(fmap, code=ins.code) diff --git a/amoco/arch/mips/r3000/env.py b/amoco/arch/mips/r3000/env.py index 0c551a3..0b358c7 100644 --- a/amoco/arch/mips/r3000/env.py +++ b/amoco/arch/mips/r3000/env.py @@ -4,8 +4,11 @@ # Copyright (C) 2020 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license +from amoco.cas.expressions import reg, slc, cst +from amoco.cas.expressions import is_reg_flags, is_reg_pc, is_reg_stack + # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import * # noqa: F403 # reference documentations: # The MIPS Instruction Set Manual @@ -14,106 +17,162 @@ # registers : # ----------- -zero = cst(0,32) +zero = cst(0, 32) # return values: -v0 = reg("v0",32) -v1 = reg("v1",32) +v0 = reg("v0", 32) +v1 = reg("v1", 32) # arguments: -a0 = reg("a0",32) -a1 = reg("a1",32) -a2 = reg("a2",32) -a3 = reg("a3",32) +a0 = reg("a0", 32) +a1 = reg("a1", 32) +a2 = reg("a2", 32) +a3 = reg("a3", 32) # temporary: -t0 = reg("t0",32) -t1 = reg("t1",32) -t2 = reg("t2",32) -t3 = reg("t3",32) -t4 = reg("t4",32) -t5 = reg("t5",32) -t6 = reg("t6",32) -t7 = reg("t7",32) +t0 = reg("t0", 32) +t1 = reg("t1", 32) +t2 = reg("t2", 32) +t3 = reg("t3", 32) +t4 = reg("t4", 32) +t5 = reg("t5", 32) +t6 = reg("t6", 32) +t7 = reg("t7", 32) # saved: -s0 = reg("s0",32) -s1 = reg("s1",32) -s2 = reg("s2",32) -s3 = reg("s3",32) -s4 = reg("s4",32) -s5 = reg("s5",32) -s6 = reg("s6",32) -s7 = reg("s7",32) +s0 = reg("s0", 32) +s1 = reg("s1", 32) +s2 = reg("s2", 32) +s3 = reg("s3", 32) +s4 = reg("s4", 32) +s5 = reg("s5", 32) +s6 = reg("s6", 32) +s7 = reg("s7", 32) # more temporary -t8 = reg("t8",32) -t9 = reg("t9",32) +t8 = reg("t8", 32) +t9 = reg("t9", 32) # kernel -k0 = reg("k0",32) -k1 = reg("k1",32) +k0 = reg("k0", 32) +k1 = reg("k1", 32) # global area pointer -gp = reg("gp",32) +gp = reg("gp", 32) # stack pointer -sp = reg("sp",32) +sp = reg("sp", 32) # frame pointer -fp = reg("fp",32) +fp = reg("fp", 32) # return address -ra = reg("ra",32) +ra = reg("ra", 32) -HI = reg("HI",32) -LO = reg("LO",32) +HI = reg("HI", 32) +LO = reg("LO", 32) -f = [reg("f%d"%i,32) for i in range(32)] +f = [reg("f%d" % i, 32) for i in range(32)] -pc = reg("pc",32) -npc = reg("npc",32) +pc = reg("pc", 32) +npc = reg("npc", 32) # status register -sr = reg("sr",32) +sr = reg("sr", 32) # assembler temp -at = reg("at",32) - -IEc = slc(sr,0,1,"IEc") -KUc = slc(sr,1,1,"KUc") -IEp = slc(sr,2,1,"IEp") -KUp = slc(sr,3,1,"KUp") -IEo = slc(sr,4,1,"IEo") -KUo = slc(sr,5,1,"KUo") -IM = slc(sr,8,8,"IM") -IsC = slc(sr,16,1,"IsC") -SwC = slc(sr,17,1,"SwC") -PZ = slc(sr,18,1,"PZ") -CM = slc(sr,19,1,"CM") -PE = slc(sr,20,1,"PE") -TS = slc(sr,21,1,"TS") -BEV = slc(sr,22,1,"BEV") -RE = slc(sr,25,1,"RE") -CU0 = slc(sr,28,1,"CU0") -CU1 = slc(sr,29,1,"CU1") -CU2 = slc(sr,30,1,"CU2") -CU3 = slc(sr,31,1,"CU3") +at = reg("at", 32) + +IEc = slc(sr, 0, 1, "IEc") +KUc = slc(sr, 1, 1, "KUc") +IEp = slc(sr, 2, 1, "IEp") +KUp = slc(sr, 3, 1, "KUp") +IEo = slc(sr, 4, 1, "IEo") +KUo = slc(sr, 5, 1, "KUo") +IM = slc(sr, 8, 8, "IM") +IsC = slc(sr, 16, 1, "IsC") +SwC = slc(sr, 17, 1, "SwC") +PZ = slc(sr, 18, 1, "PZ") +CM = slc(sr, 19, 1, "CM") +PE = slc(sr, 20, 1, "PE") +TS = slc(sr, 21, 1, "TS") +BEV = slc(sr, 22, 1, "BEV") +RE = slc(sr, 25, 1, "RE") +CU0 = slc(sr, 28, 1, "CU0") +CU1 = slc(sr, 29, 1, "CU1") +CU2 = slc(sr, 30, 1, "CU2") +CU3 = slc(sr, 31, 1, "CU3") is_reg_pc(pc) is_reg_stack(sp) is_reg_flags(sr) -R = [zero,at,v0,v1,a0,a1,a2,a3, - t0,t1,t2,t3,t4,t5,t6,t7, - s0,s1,s2,s3,s4,s5,s6,s7, - t8,t9, - k0,k1, - gp,sp,fp,ra] +R = [ + zero, + at, + v0, + v1, + a0, + a1, + a2, + a3, + t0, + t1, + t2, + t3, + t4, + t5, + t6, + t7, + s0, + s1, + s2, + s3, + s4, + s5, + s6, + s7, + t8, + t9, + k0, + k1, + gp, + sp, + fp, + ra, +] # list of registers used by emulator views: -registers = [v0,v1,a0,a1,a2,a3, - t0,t1,t2,t3,t4,t5,t6,t7,t8,t9, - s0,s1,s2,s3,s4,s5,s6,s7, - gp,sp,fp,ra,pc] - +registers = [ + v0, + v1, + a0, + a1, + a2, + a3, + t0, + t1, + t2, + t3, + t4, + t5, + t6, + t7, + t8, + t9, + s0, + s1, + s2, + s3, + s4, + s5, + s6, + s7, + gp, + sp, + fp, + ra, + pc, +] + +internals = {} diff --git a/amoco/arch/mips/r3000/formats.py b/amoco/arch/mips/r3000/formats.py index eb396bd..54d1c2d 100644 --- a/amoco/arch/mips/r3000/formats.py +++ b/amoco/arch/mips/r3000/formats.py @@ -1,16 +1,19 @@ # -*- coding: utf-8 -*- -from .env import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from amoco.cas.expressions import composer, cst +from amoco.arch.core import Formatter +from amoco.ui.render import Token + def mnemo(i): mn = i.mnemonic.lower() return [(Token.Mnemonic, "{: <12}".format(mn))] -def deref(base,off): + +def deref(base, off): return "+%d(%s)" % (off, base) + def opers(i): s = [] for op in i.operands: @@ -28,14 +31,16 @@ def opers(i): s.pop() return s + def opers_mem(i): s = [] op = i.operands[0] s.append((Token.Register, op.__str__())) s.append((Token.Literal, ", ")) - s.append((Token.Memory,deref(*(i.operands[1:])))) + s.append((Token.Memory, deref(*(i.operands[1:])))) return s + def opers_adr(i): s = opers(i) if i.misc["imm_ref"] is None and i.address is not None: @@ -43,10 +48,11 @@ def opers_adr(i): s[-1] = (Token.Address, "%s" % (imm_ref)) return s + def opers_rel(i): s = opers(i) if i.misc["imm_ref"] is None and i.address is not None: - imm_ref = composer([cst(0,2),i.operands[-1],i.address[28:32]]) + imm_ref = composer([cst(0, 2), i.operands[-1], i.address[28:32]]) s[-1] = (Token.Address, "%s" % (imm_ref)) return s diff --git a/amoco/arch/mips/r3000/spec.py b/amoco/arch/mips/r3000/spec.py index 8a0806a..dc6ad41 100644 --- a/amoco/arch/mips/r3000/spec.py +++ b/amoco/arch/mips/r3000/spec.py @@ -6,7 +6,10 @@ from . import env -from amoco.arch.core import * +from amoco.arch.core import ispec +from amoco.arch.core import type_control_flow, type_data_processing, type_other + +# ruff: noqa: F811 # ------------------------------------------------------- # instruction MIPS-R3000 decoders @@ -18,12 +21,14 @@ ISPECS = [] + @ispec("32<[ 000000 .code(20) 001101]", mnemonic="BREAK") @ispec("32<[ 000000 .code(20) 001100]", mnemonic="SYSCALL") def mips1_noop(obj): obj.operands = [] obj.type = type_control_flow + @ispec("32<[ 000000 rs(5) rt(5) rd(5) 00000 100000]", mnemonic="ADD") @ispec("32<[ 000000 rs(5) rt(5) rd(5) 00000 100010]", mnemonic="SUB") @ispec("32<[ 000000 rs(5) rt(5) rd(5) 00000 100001]", mnemonic="ADDU") @@ -41,11 +46,12 @@ def mips1_drr(obj, rs, rt, rd): src1 = env.R[rs] src2 = env.R[rt] dst = env.R[rd] - if obj.mnemonic in ('SLLV','SRAV','SRLV'): - src1,src2 = src2,src1 + if obj.mnemonic in ("SLLV", "SRAV", "SRLV"): + src1, src2 = src2, src1 obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ 000000 rs(5) rt(5) 00000 00000 011010]", mnemonic="DIV") @ispec("32<[ 000000 rs(5) rt(5) 00000 00000 011011]", mnemonic="DIVU") @ispec("32<[ 000000 rs(5) rt(5) 00000 00000 011000]", mnemonic="MULT") @@ -56,19 +62,22 @@ def mips1_rr(obj, rs, rt): obj.operands = [src1, src2] obj.type = type_data_processing + @ispec("32<[ 000010 t(26)]", mnemonic="J") @ispec("32<[ 000011 t(26)]", mnemonic="JAL") def mips1_jump_rel(obj, t): - obj.operands = [env.cst(t,26)] + obj.operands = [env.cst(t, 26)] obj.misc["delayed"] = True obj.type = type_control_flow + @ispec("32<[ 000000 rs(5) 00000 rd(5) 00000 001001]", mnemonic="JALR") def mips1_jump_abs(obj, rs, rd): - obj.operands = [env.R[rd],env.R[rs]] + obj.operands = [env.R[rd], env.R[rs]] obj.misc["delayed"] = True obj.type = type_control_flow + @ispec("32<[ 000000 rs(5) 00000 00000 00000 001000]", mnemonic="JR") def mips1_jump_abs(obj, rs): obj.operands = [env.R[rs]] @@ -87,6 +96,7 @@ def mips1_dri(obj, rs, rt, imm): obj.operands = [dst, src1, imm] obj.type = type_data_processing + @ispec("32<[ 001100 rs(5) rt(5) imm(16) ]", mnemonic="ANDI") @ispec("32<[ 001101 rs(5) rt(5) imm(16) ]", mnemonic="ORI") @ispec("32<[ 001110 rs(5) rt(5) imm(16) ]", mnemonic="XORI") @@ -97,6 +107,7 @@ def mips1_dri(obj, rs, rt, imm): obj.operands = [dst, src1, imm] obj.type = type_data_processing + @ispec("32<[ 100000 base(5) rt(5) offset(16) ]", mnemonic="LB") @ispec("32<[ 101000 base(5) rt(5) offset(16) ]", mnemonic="SB") @ispec("32<[ 100100 base(5) rt(5) offset(16) ]", mnemonic="LBU") @@ -111,35 +122,39 @@ def mips1_dri(obj, rs, rt, imm): @ispec("32<[ 101110 base(5) rt(5) offset(16) ]", mnemonic="SWR") def mips1_loadstore(obj, base, rt, offset): rt = env.R[rt] - obj.operands = [rt, env.R[base], env.cst(offset,16).signextend(32)] + obj.operands = [rt, env.R[base], env.cst(offset, 16).signextend(32)] obj.type = type_data_processing + @ispec("32<[ 000000 00000 rt(5) rd(5) sa(5) 000000 ]", mnemonic="SLL") @ispec("32<[ 000000 00000 rt(5) rd(5) sa(5) 000011 ]", mnemonic="SRA") @ispec("32<[ 000000 00000 rt(5) rd(5) sa(5) 000010 ]", mnemonic="SRL") def mips1_shifts(obj, rt, rd, sa): dst = env.R[rd] src1 = env.R[rt] - src2 = env.cst(sa,5) + src2 = env.cst(sa, 5) obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ 001111 00000 rt(5) imm(16) ]", mnemonic="LUI") def mips1_di(obj, rt, imm): dst = env.R[rt] - obj.operands = [dst, env.cst(imm,16)] + obj.operands = [dst, env.cst(imm, 16)] obj.type = type_data_processing + @ispec("32<[ 000100 rs(5) rt(5) ~imm(16) ]", mnemonic="BEQ") @ispec("32<[ 000101 rs(5) rt(5) ~imm(16) ]", mnemonic="BNE") def mips1_branch(obj, rs, rt, imm): rs = env.R[rs] rt = env.R[rt] - imm = env.cst((imm<<2).int(-1), 32) + imm = env.cst((imm << 2).int(-1), 32) obj.operands = [rs, rt, imm] obj.misc["delayed"] = True obj.type = type_control_flow + @ispec("32<[ 000001 rs(5) 00001 ~imm(16) ]", mnemonic="BGEZ") @ispec("32<[ 000001 rs(5) 10001 ~imm(16) ]", mnemonic="BGEZAL") @ispec("32<[ 000111 rs(5) 00000 ~imm(16) ]", mnemonic="BGTZ") @@ -148,11 +163,12 @@ def mips1_branch(obj, rs, rt, imm): @ispec("32<[ 000001 rs(5) 10000 ~imm(16) ]", mnemonic="BLTZAL") def mips1_branch(obj, rs, imm): src1 = env.R[rs] - imm = env.cst((imm<<2).int(-1), 32) + imm = env.cst((imm << 2).int(-1), 32) obj.operands = [src1, imm] obj.misc["delayed"] = True obj.type = type_control_flow + @ispec("32<[ 000000 00000 00000 rd(5) 00000 010000 ]", mnemonic="MFHI") @ispec("32<[ 000000 00000 00000 rd(5) 00000 010010 ]", mnemonic="MFLO") def mips1_r(obj, rd): @@ -160,6 +176,7 @@ def mips1_r(obj, rd): obj.operands = [dst] obj.type = type_data_processing + @ispec("32<[ 000000 rs(5) 00000 00000 00000 010001 ]", mnemonic="MTHI") @ispec("32<[ 000000 rs(5) 00000 00000 00000 010011 ]", mnemonic="MTLO") def mips1_r(obj, rs): @@ -167,6 +184,7 @@ def mips1_r(obj, rs): obj.operands = [src] obj.type = type_data_processing + @ispec("32<[ 0100 .z(2) 00010 rt(5) rd(5) 00000000000 ]", mnemonic="CFC") @ispec("32<[ 0100 .z(2) 00000 rt(5) rd(5) 00000000000 ]", mnemonic="MFC") @ispec("32<[ 0100 .z(2) 00110 rt(5) rd(5) 00000000000 ]", mnemonic="CTC") @@ -175,12 +193,14 @@ def mips1_copz_rr(obj, rt, rd): obj.operands = [env.R[rt], rd] obj.type = type_other + @ispec("32<[ 1100 .z(2) base(5) rt(5) offset(16) ]", mnemonic="LWC") @ispec("32<[ 1110 .z(2) base(5) rt(5) offset(16) ]", mnemonic="SWC") def mips1_copz_rbo(obj, base, rt, offset): - obj.operands = [env.R[rt], env.R[base], env.cst(offset,16).signextend(32)] + obj.operands = [env.R[rt], env.R[base], env.cst(offset, 16).signextend(32)] obj.type = type_other + @ispec("32<[ 0100 .z(2) 1 .cofun(25) ]", mnemonic="COP") def mips1_copz_rbo(obj): obj.operands = [] diff --git a/amoco/arch/msp430/asm.py b/amoco/arch/msp430/asm.py index 881ab1f..f9ed1b1 100644 --- a/amoco/arch/msp430/asm.py +++ b/amoco/arch/msp430/asm.py @@ -4,9 +4,10 @@ # Copyright (C) 2013 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * +from .env import pc, sp, cf, zf, vf, nf, COND +from amoco.cas.expressions import bit0, mem, composer, tst -from amoco.cas.utils import * +from amoco.cas.utils import AddWithCarry, RORWithCarry def autoinc(i, fmap): @@ -101,7 +102,7 @@ def i_AND(i, fmap): def i_XOR(i, fmap): fmap[pc] = fmap[pc] + i.length src, dst = i.operands - fmap[dst] = fmap(src ^ dst) + fmap[dst] = result = fmap(src ^ dst) fmap[nf] = result[dst.size - 1 : dst.size] fmap[zf] = result == 0 fmap[cf] = ~fmap(zf) diff --git a/amoco/arch/msp430/cpu.py b/amoco/arch/msp430/cpu.py index 85d131a..9f28ea3 100644 --- a/amoco/arch/msp430/cpu.py +++ b/amoco/arch/msp430/cpu.py @@ -1,17 +1,13 @@ # -*- coding: utf-8 -*- -from amoco.arch.msp430.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.msp430 import env +from amoco.arch.msp430 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_msp430 = type("instruction_msp430", (instruction,), {}) -instruction_msp430.set_uarch(uarch) -from amoco.arch.msp430.formats import MSP430_full from amoco.arch.msp430.formats import MSP430_synthetic instruction_msp430.set_formatter(MSP430_synthetic) @@ -22,10 +18,4 @@ disassemble = disassembler([spec_msp430], iclass=instruction_msp430) disassemble.maxlen = 6 - -def PC(state=None): - return pc - - -def get_data_endian(): - return 1 +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/msp430/env.py b/amoco/arch/msp430/env.py index 61d5cc2..3ee2c4e 100644 --- a/amoco/arch/msp430/env.py +++ b/amoco/arch/msp430/env.py @@ -5,7 +5,9 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc, bit0, bit1 + +from amoco.cas.expressions import * # noqa: F403 # reference documentation: # MSP430x1xx User's Guide, Texas Instruments, 2006. @@ -43,3 +45,5 @@ } registers = R + +internals = {} diff --git a/amoco/arch/msp430/formats.py b/amoco/arch/msp430/formats.py index 3c14501..0899b93 100644 --- a/amoco/arch/msp430/formats.py +++ b/amoco/arch/msp430/formats.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- -from .env import * +from .env import COND, pc, sp, sr from amoco.arch.core import Formatter -from amoco.ui.render import Token, TokenListJoin, highlight +from amoco.ui.render import Token, TokenListJoin +from amoco.ui.views import View def mn(m, pad=8): @@ -137,4 +138,4 @@ def MSP430_synthetic(null, i, toks=False): del s[1:-1] if toks: return s - return highlight(s) + return View.engine.higlight(s) diff --git a/amoco/arch/msp430/parsers.py b/amoco/arch/msp430/parsers.py index 9c25189..ec2243f 100644 --- a/amoco/arch/msp430/parsers.py +++ b/amoco/arch/msp430/parsers.py @@ -16,10 +16,10 @@ from amoco.arch.msp430.cpu import instruction_msp430 as instruction from amoco.arch.msp430 import env + # ------------------------------------------------------------------------------ # parser for MSP430 assembler syntax. class msp430_syntax: - divide = False noprefix = False @@ -67,15 +67,18 @@ class msp430_syntax: instr = mnemo + pp.Optional(opds) + pp.Optional(comment) + @staticmethod def action_reg(toks): rname = toks[0] return env.reg(rname.ref) + @staticmethod def action_hilo(toks): v = toks[1] return env.hi(v) if toks[0] == "%hi" else env.lo(v).zeroextend(32) - def action_exp(toks): + @classmethod + def action_exp(cls, toks): tok = toks[0] if isinstance(tok, env.exp): return tok @@ -83,20 +86,21 @@ def action_exp(toks): op = tok[0] r = tok[1] if isinstance(r, list): - r = action_exp(r) + r = cls.action_exp(r) return env.oper(op, r) elif len(tok) == 3: op = tok[1] l = tok[0] r = tok[2] if isinstance(l, list): - l = action_exp(l) + l = cls.action_exp(l) if isinstance(r, list): - r = action_exp(r) + r = cls.action_exp(r) return env.oper(op, l, r) else: return tok + @staticmethod def action_instr(toks): i = instruction(b"") i.mnemonic = toks[0] @@ -125,7 +129,7 @@ def asmhelper(i): def test_parser(cls): while 1: try: - res = raw_input("%s>" % cls.__name__) + res = input("%s>" % cls.__name__) E = cls.instr.parseString(res, True) print(E) except pp.ParseException: diff --git a/amoco/arch/msp430/spec_msp430.py b/amoco/arch/msp430/spec_msp430.py index fcb29d8..43c2fbf 100644 --- a/amoco/arch/msp430/spec_msp430.py +++ b/amoco/arch/msp430/spec_msp430.py @@ -9,12 +9,16 @@ from amoco.arch.msp430 import env -from amoco.arch.core import * +from amoco.arch.core import ispec, pack +from amoco.arch.core import type_control_flow, type_data_processing + +# ruff: noqa: F811 # ------------------------------------------------------- # instruction MSP430 decoders # ------------------------------------------------------- + # get operand type/value based on addressing mode: def getopd(obj, mode, reg, data, CGR=False): r = env.R[reg] @@ -121,6 +125,7 @@ def msp430_jumps(obj, offset): obj.operands = [off] obj.type = type_control_flow + @ispec("16<[ 001 111 offset(10) ]", mnemonic="JMP", BW=0) def msp430_jumps(obj, offset): obj.cond = 0b111 diff --git a/amoco/arch/pic/F46K22/asm.py b/amoco/arch/pic/F46K22/asm.py index 65e18f7..9e93d20 100644 --- a/amoco/arch/pic/F46K22/asm.py +++ b/amoco/arch/pic/F46K22/asm.py @@ -4,9 +4,18 @@ # Copyright (C) 2014 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * - -from amoco.cas.utils import * +from .env import wreg, wregs, status, statuss, prod, tablat, tblptr +from .env import pc, nf, ovf, cf, dcf, zf, tos, stkptr, bsr, bsrs +from .env import cst, mem, top, tst, comp, bit1, bit0 + +from amoco.cas.utils import ( + AddWithCarry, + SubWithBorrow, + ROLWithCarry, + ROL, + RORWithCarry, + ROR, +) # handlers for preinc/postinc/postdec virtual registers: # ------------------------------------------------------ @@ -247,7 +256,6 @@ def i_CPFSEQ(i, fmap): def i_CPFSGT(i, fmap): fmap[pc] = fmap(pc) + i.length - dst = i.dst src = i.src res = fmap(src - wreg) fmap[pc] = tst(res > 0, fmap(pc) + 2, fmap(pc)) @@ -429,14 +437,14 @@ def i_MOVWF(i, fmap): def i_MULLW(i, fmap): fmap[pc] = fmap(pc) + i.length k = i.imm - res = fmap(wreg ** k) + res = fmap(wreg**k) fmap[prod] = res def i_MULWF(i, fmap): fmap[pc] = fmap(pc) + i.length src = i.imm - res = fmap(wreg ** src) + res = fmap(wreg**src) fmap[prod] = res diff --git a/amoco/arch/pic/F46K22/env.py b/amoco/arch/pic/F46K22/env.py index 33fffcc..916e61f 100644 --- a/amoco/arch/pic/F46K22/env.py +++ b/amoco/arch/pic/F46K22/env.py @@ -5,7 +5,8 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc, cst, mem +from amoco.cas.expressions import * # noqa: F403 # reference documentation: # PIC18(L)F2X/4XK22 Data Sheet, Microchip Technology Inc. diff --git a/amoco/arch/pic/F46K22/formats.py b/amoco/arch/pic/F46K22/formats.py index 08ef438..f75d394 100644 --- a/amoco/arch/pic/F46K22/formats.py +++ b/amoco/arch/pic/F46K22/formats.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -from .env import * from amoco.arch.core import Formatter @@ -34,7 +33,7 @@ def accessbank(i): def adr(i): x = str(i.operands[0]) - return x + ", fast" if i.misc["fast"] == True else x + return x + ", fast" if i.misc["fast"] is True else x def tblrw(i): diff --git a/amoco/arch/pic/F46K22/spec_pic18.py b/amoco/arch/pic/F46K22/spec_pic18.py index a3ae1f5..27289c4 100644 --- a/amoco/arch/pic/F46K22/spec_pic18.py +++ b/amoco/arch/pic/F46K22/spec_pic18.py @@ -6,7 +6,10 @@ from amoco.arch.pic.F46K22 import env -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import type_data_processing, type_control_flow + +# ruff: noqa: F811 # ------------------------------------------------------- # instruction PIC18(L)F2X/4XK22 decoders diff --git a/amoco/arch/pic/cpu_pic18f46k22.py b/amoco/arch/pic/cpu_pic18f46k22.py index 223cf48..35e8011 100644 --- a/amoco/arch/pic/cpu_pic18f46k22.py +++ b/amoco/arch/pic/cpu_pic18f46k22.py @@ -1,15 +1,12 @@ # -*- coding: utf-8 -*- -from amoco.arch.pic.F46K22.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.pic.F46K22 import env +from amoco.arch.pic.F46K22 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_f46k22 = type("instruction_f46k22", (instruction,), {}) -instruction_f46k22.set_uarch(uarch) from amoco.arch.pic.F46K22.formats import PIC_full @@ -20,10 +17,4 @@ disassemble = disassembler([spec_pic18], iclass=instruction_f46k22) - -def PC(state=None): - return pc - - -def get_data_endian(): - return 1 +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/ppc32/asm.py b/amoco/arch/ppc32/asm.py index 5158c5e..e914608 100644 --- a/amoco/arch/ppc32/asm.py +++ b/amoco/arch/ppc32/asm.py @@ -4,9 +4,8 @@ # Copyright (C) 2022 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * +from .env import pc, sp, mem, internals -from amoco.cas.utils import * # ------------------------------------------------------------------------------ # helpers and decorators : @@ -29,6 +28,7 @@ def npc(ins, fmap): def trap(ins, fmap, trapname): - fmap.internals["trap"] = trapname + internals["trap"] = trapname +# TODO diff --git a/amoco/arch/ppc32/cpu.py b/amoco/arch/ppc32/cpu.py index cac4eaf..0ffc572 100644 --- a/amoco/arch/ppc32/cpu.py +++ b/amoco/arch/ppc32/cpu.py @@ -1,15 +1,12 @@ # -*- coding: utf-8 -*- -from amoco.arch.ppc32.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.ppc32 import env +from amoco.arch.ppc32 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_ppc32 = type("instruction_ppc32", (instruction,), {}) -instruction_ppc32.set_uarch(uarch) from amoco.arch.ppc32.formats import PPC_full @@ -18,13 +15,11 @@ # define disassembler: from amoco.arch.ppc32 import spec_booke as spec -endian = lambda: -1 -disassemble = disassembler([spec], iclass=instruction_ppc32,endian=endian) +def endian(): + return -1 -def PC(state=None): - return pc +disassemble = disassembler([spec], iclass=instruction_ppc32, endian=endian) -def get_data_endian(): - return -1 # BE +cpu = CPU(env, asm, disassemble, env.pc, data_endian=-1) diff --git a/amoco/arch/ppc32/cpu_e200.py b/amoco/arch/ppc32/cpu_e200.py index 95f1159..7c80189 100644 --- a/amoco/arch/ppc32/cpu_e200.py +++ b/amoco/arch/ppc32/cpu_e200.py @@ -1,15 +1,12 @@ # -*- coding: utf-8 -*- -from amoco.arch.ppc32.e200.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.ppc32.e200 import env +from amoco.arch.ppc32.e200 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_e200 = type("instruction_e200", (instruction,), {}) -instruction_e200.set_uarch(uarch) from amoco.arch.ppc32.e200.formats import PPC_full @@ -18,13 +15,11 @@ # define disassembler: from amoco.arch.ppc32.e200 import spec_vle -endian = lambda: -1 -disassemble = disassembler([spec_vle], iclass=instruction_e200,endian=endian) +def endian(): + return -1 -def PC(state=None): - return pc +disassemble = disassembler([spec_vle], iclass=instruction_e200, endian=endian) -def get_data_endian(): - return -1 # BE +cpu = CPU(env, asm, disassemble, env.pc, data_endian=-1) diff --git a/amoco/arch/ppc32/e200/asm.py b/amoco/arch/ppc32/e200/asm.py index cf2ebc3..0b90bf2 100644 --- a/amoco/arch/ppc32/e200/asm.py +++ b/amoco/arch/ppc32/e200/asm.py @@ -4,27 +4,30 @@ # Copyright (C) 2020 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * - -from amoco.cas.utils import * +from .env import pc, npc, ra, zero, HI, LO +from amoco.cas.expressions import composer, comp, cst, tst, bit0, bit1, ext, mem, top # ------------------------------------------------------------------------------ # helpers and decorators : + def __npc(i_xxx): def pcnpc(ins, fmap): fmap[pc] = fmap[npc] fmap[npc] = fmap[npc] + ins.length i_xxx(ins, fmap) + return pcnpc + # i_xxx is the translation of MIPS-R3000 instruction xxx. # ------------------------------------------------------------------------------ + @__npc def i_ADD(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1+src2) + _v = fmap(src1 + src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v @@ -33,76 +36,84 @@ def i_ADD(ins, fmap): @__npc def i_SUB(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1-src2) + _v = fmap(src1 - src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_SUBU(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1-src2) + _v = fmap(src1 - src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_AND(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1&src2) + _v = fmap(src1 & src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_OR(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1|src2) + _v = fmap(src1 | src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_NOR(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(~(src1|src2)) + _v = fmap(~(src1 | src2)) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_XOR(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1^src2) + _v = fmap(src1 ^ src2) fmap.update_delayed() if dst is not zero: fmap[dst] = _v + i_ADDI = i_ADDIU = i_ADDU = i_ADD -i_SUBU = i_SUB i_ANDI = i_AND -i_ORI = i_OR +i_ORI = i_OR i_XORI = i_XOR -def i_J(ins,fmap): + +def i_J(ins, fmap): t = ins.operands[0] - target = composer([cst(0,2),t,fmap(pc)[28:32]]) + target = composer([cst(0, 2), t, fmap(pc)[28:32]]) _v = fmap(npc) fmap.update_delayed() fmap[pc] = _v fmap[npc] = target -def i_JAL(ins,fmap): + +def i_JAL(ins, fmap): t = ins.operands[0] - target = composer([cst(0,2),t,fmap(pc)[28:32]]) + target = composer([cst(0, 2), t, fmap(pc)[28:32]]) _v = fmap(npc) fmap.update_delayed() fmap[pc] = _v - fmap[ra] = _v+4 + fmap[ra] = _v + 4 fmap[npc] = target + @__npc -def i_JALR(ins,fmap): +def i_JALR(ins, fmap): rd, rs = ins.operands _v = fmap(npc) target = fmap(rs) @@ -111,118 +122,136 @@ def i_JALR(ins,fmap): fmap[rd] = _v fmap[npc] = target + @__npc -def i_JR(ins,fmap): +def i_JR(ins, fmap): rs = ins.operands[0] target = fmap(rs) fmap.update_delayed() fmap[npc] = target + @__npc -def i_BEQ(ins,fmap): +def i_BEQ(ins, fmap): rs, rt, offset = ins.operands - cond = (fmap(rs)==fmap(rt)) + cond = fmap(rs) == fmap(rt) fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BNE(ins,fmap): +def i_BNE(ins, fmap): rs, rt, offset = ins.operands - cond = (fmap(rs)!=fmap(rt)) + cond = fmap(rs) != fmap(rt) fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BGEZ(ins,fmap): +def i_BGEZ(ins, fmap): rs, offset = ins.operands - cond = fmap(rs.bit(31))==bit0 + cond = fmap(rs.bit(31)) == bit0 fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BGEZAL(ins,fmap): +def i_BGEZAL(ins, fmap): rs, offset = ins.operands - cond = fmap(rs.bit(31))==bit0 + cond = fmap(rs.bit(31)) == bit0 fmap.update_delayed() fmap[ra] = fmap(npc) - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BGTZ(ins,fmap): +def i_BGTZ(ins, fmap): rs, offset = ins.operands - cond = fmap( (rs.bit(31)==bit0) & (rs!=zero) ) + cond = fmap((rs.bit(31) == bit0) & (rs != zero)) fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BLEZ(ins,fmap): +def i_BLEZ(ins, fmap): rs, offset = ins.operands - cond = fmap( (rs.bit(31)==bit1) | (rs==zero) ) + cond = fmap((rs.bit(31) == bit1) | (rs == zero)) fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BLTZ(ins,fmap): +def i_BLTZ(ins, fmap): rs, offset = ins.operands - cond = fmap(rs.bit(31))==bit1 + cond = fmap(rs.bit(31)) == bit1 fmap.update_delayed() - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BLTZAL(ins,fmap): +def i_BLTZAL(ins, fmap): rs, offset = ins.operands - cond = fmap(rs.bit(31))==bit1 + cond = fmap(rs.bit(31)) == bit1 fmap.update_delayed() fmap[ra] = fmap(npc) - fmap[npc] = tst(cond,fmap(npc-4)+offset,fmap(npc)) + fmap[npc] = tst(cond, fmap(npc - 4) + offset, fmap(npc)) + @__npc -def i_BREAK(ins,fmap): - ext("BREAK").call(fmap,code=ins.code) +def i_BREAK(ins, fmap): + ext("BREAK").call(fmap, code=ins.code) + @__npc def i_CFC(ins, fmap): rt, rd = ins.operands - ext("CFC%d"%(ins.z)).call(fmap,rt=rt,rd=rd) + ext("CFC%d" % (ins.z)).call(fmap, rt=rt, rd=rd) + @__npc def i_MFC(ins, fmap): rt, rd = ins.operands - ext("MFC%d"%(ins.z)).call(fmap,rt=rt,rd=rd) + ext("MFC%d" % (ins.z)).call(fmap, rt=rt, rd=rd) + @__npc def i_COP(ins, fmap): fun = ins.cofun - ext("COP%d"%(ins.z)).call(fmap,cofun=fun) + ext("COP%d" % (ins.z)).call(fmap, cofun=fun) + @__npc def i_CTC(ins, fmap): rt, rd = ins.operands - ext("CTC%d"%(ins.z)).call(fmap,rd=rd,rt=rt) + ext("CTC%d" % (ins.z)).call(fmap, rd=rd, rt=rt) + @__npc def i_MTC(ins, fmap): rt, rd = ins.operands - ext("MTC%d"%(ins.z)).call(fmap,rd=rd,rt=rt) + ext("MTC%d" % (ins.z)).call(fmap, rd=rd, rt=rt) + @__npc def i_LWC(ins, fmap): rt, base, offset = ins.operands - data = mem(base+offset,32) - ext("LWC%d"%(ins.z)).call(fmap,rt=rt,data=data) + data = mem(base + offset, 32) + ext("LWC%d" % (ins.z)).call(fmap, rt=rt, data=data) + @__npc def i_SWC(ins, fmap): rt, base, offset = ins.operands - addr = fmap(base+offset) - ext("SWC%d"%(ins.z)).call(fmap,rt=rt,addr=addr) + addr = fmap(base + offset) + ext("SWC%d" % (ins.z)).call(fmap, rt=rt, addr=addr) + @__npc def i_DIV(ins, fmap): rs, rt = ins.operands - if fmap(rt!=zero): - _v_hi = fmap(rs/rt) - _v_lo = fmap(rs%rt) + if fmap(rt != zero): + _v_hi = fmap(rs / rt) + _v_lo = fmap(rs % rt) fmap.update_delayed() fmap[HI] = _v_hi fmap[LO] = _v_lo @@ -231,8 +260,10 @@ def i_DIV(ins, fmap): fmap[HI] = top(32) fmap[LO] = top(32) + i_DIVU = i_DIV + @__npc def i_MULT(ins, fmap): rs, rt = ins.operands @@ -241,186 +272,206 @@ def i_MULT(ins, fmap): fmap[LO] = res[0:32] fmap[HI] = res[32:64] + i_MULTU = i_MULT + @__npc def i_LH(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,16)).signextend(32) + addr = base + src + _v = fmap(mem(addr, 16)).signextend(32) fmap.update_delayed() if dst is not zero: fmap.delayed(dst, _v) + @__npc def i_LHU(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,16)).zeroextend(32) + addr = base + src + _v = fmap(mem(addr, 16)).zeroextend(32) fmap.update_delayed() if dst is not zero: fmap.delayed(dst, _v) + @__npc def i_LUI(ins, fmap): dst, src1 = ins.operands - _v = src1.zeroextend(32)<<16 + _v = src1.zeroextend(32) << 16 fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_LW(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,32)) + addr = base + src + _v = fmap(mem(addr, 32)) fmap.update_delayed() if dst is not zero: fmap.delayed(dst, _v) + @__npc def i_LWL(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v_b3 = fmap(mem(addr,8)) - cond1 = (addr%4)!=0 - _v_b2 = fmap(tst(cond1,mem(addr-1,8),dst[16:24])) - addr = addr - 1 - cond2 = cond1 & ((addr%4)!=0) - _v_b1 = fmap(tst(cond2,mem(addr-1,8),dst[8:16])) + addr = base + src + _v_b3 = fmap(mem(addr, 8)) + cond1 = (addr % 4) != 0 + _v_b2 = fmap(tst(cond1, mem(addr - 1, 8), dst[16:24])) + addr = addr - 1 + cond2 = cond1 & ((addr % 4) != 0) + _v_b1 = fmap(tst(cond2, mem(addr - 1, 8), dst[8:16])) _v_b0 = fmap(dst[0:8]) fmap.update_delayed() if dst is not zero: _v = comp(dst.size) _v[24:32] = _v_b3 _v[16:24] = _v_b2 - _v[ 8:16] = _v_b1 - _v[ 0: 8] = _v_b0 + _v[8:16] = _v_b1 + _v[0:8] = _v_b0 fmap.delayed(dst, _v.simplify()) + @__npc def i_LWR(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v_b0 = fmap(mem(addr,8)) - addr = addr + 1 - cond1 = (addr%4)!=0 - _v_b1 = fmap(tst(cond1,mem(addr,8),dst[8:16])) - addr = addr + 1 - cond2 = cond1 & ((addr%4)!=0) - _v_b2 = fmap(tst(cond2,mem(addr,8),dst[16:24])) + addr = base + src + _v_b0 = fmap(mem(addr, 8)) + addr = addr + 1 + cond1 = (addr % 4) != 0 + _v_b1 = fmap(tst(cond1, mem(addr, 8), dst[8:16])) + addr = addr + 1 + cond2 = cond1 & ((addr % 4) != 0) + _v_b2 = fmap(tst(cond2, mem(addr, 8), dst[16:24])) _v_b3 = fmap(dst[24:32]) fmap.update_delayed() if dst is not zero: _v = comp(dst.size) - _v[0 : 8] = _v_b0 - _v[8 :16] = _v_b1 + _v[0:8] = _v_b0 + _v[8:16] = _v_b1 _v[16:24] = _v_b2 _v[24:32] = _v_b3 fmap.delayed(dst, _v.simplify()) + @__npc def i_SWL(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) val = fmap(src) fmap.update_delayed() - fmap[mem(addr,8)] = val[24:32] - cond1 = (addr%4)!=0 - fmap[mem(addr-1,8)] = tst(cond1,val[16:24],fmap[mem(addr-1,8)]) + fmap[mem(addr, 8)] = val[24:32] + cond1 = (addr % 4) != 0 + fmap[mem(addr - 1, 8)] = tst(cond1, val[16:24], fmap[mem(addr - 1, 8)]) addr = addr - 1 - cond2 = cond1 & ((addr%4)!=0) - fmap[mem(addr-1,8)] = tst(cond2,val[8:16],fmap[mem(addr-1,8)]) + cond2 = cond1 & ((addr % 4) != 0) + fmap[mem(addr - 1, 8)] = tst(cond2, val[8:16], fmap[mem(addr - 1, 8)]) + @__npc def i_SWR(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) val = fmap(src) fmap.update_delayed() - fmap[mem(addr,8)] = val[0:8] + fmap[mem(addr, 8)] = val[0:8] addr = addr + 1 - cond1 = (addr%4)!=0 - fmap[mem(addr,8)] = tst(cond1,val[8:16],fmap[mem(addr,8)]) + cond1 = (addr % 4) != 0 + fmap[mem(addr, 8)] = tst(cond1, val[8:16], fmap[mem(addr, 8)]) addr = addr + 1 - cond2 = cond1 & ((addr%4)!=0) - fmap[mem(addr,8)] = tst(cond2,val[16:24],fmap[mem(addr,8)]) + cond2 = cond1 & ((addr % 4) != 0) + fmap[mem(addr, 8)] = tst(cond2, val[16:24], fmap[mem(addr, 8)]) + @__npc def i_LB(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,8)).signextend(32) + addr = base + src + _v = fmap(mem(addr, 8)).signextend(32) fmap.update_delayed() if dst is not zero: fmap.delay(dst, _v) + @__npc def i_LBU(ins, fmap): dst, base, src = ins.operands - addr = base+src - _v = fmap(mem(addr,8)).zeroextend(32) + addr = base + src + _v = fmap(mem(addr, 8)).zeroextend(32) fmap.update_delayed() if dst is not zero: fmap.delay(dst, _v) + @__npc -def i_MFHI(ins,fmap): +def i_MFHI(ins, fmap): dst = ins.operands[0] _v = fmap(HI) fmap.update_delayed() fmap[dst] = _v + @__npc -def i_MFLO(ins,fmap): +def i_MFLO(ins, fmap): dst = ins.operands[0] _v = fmap(LO) fmap.update_delayed() fmap[dst] = _v + @__npc -def i_MTHI(ins,fmap): +def i_MTHI(ins, fmap): src = ins.operands[0] _v = fmap(src) fmap.update_delayed() fmap[HI] = _v + @__npc -def i_MTLO(ins,fmap): +def i_MTLO(ins, fmap): src = ins.operands[0] _v = fmap(src) fmap.update_delayed() fmap[LO] = _v + @__npc def i_SB(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) fmap.update_delayed() - fmap[mem(addr,8)] = fmap(src[0:8]) + fmap[mem(addr, 8)] = fmap(src[0:8]) + @__npc def i_SH(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) fmap.update_delayed() - fmap[mem(addr,16)] = fmap(src[0:16]) + fmap[mem(addr, 16)] = fmap(src[0:16]) + @__npc def i_SW(ins, fmap): src, base, off = ins.operands - addr = fmap(base+off) + addr = fmap(base + off) fmap.update_delayed() - fmap[mem(addr,32)] = fmap(src) + fmap[mem(addr, 32)] = fmap(src) + @__npc def i_SLL(ins, fmap): rt, rd, sa = ins.operands - res = fmap(rt<>src2).unsigned() + _v = fmap(src1 >> src2).unsigned() fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_SRLV(ins, fmap): dst, src1, src2 = ins.operands - _v = fmap(src1>>src2).unsigned() + _v = fmap(src1 >> src2).unsigned() fmap.update_delayed() if dst is not zero: fmap[dst] = _v + @__npc def i_SYSCALL(ins, fmap): - ext("SYSCALL").call(fmap,code=ins.code) + ext("SYSCALL").call(fmap, code=ins.code) diff --git a/amoco/arch/ppc32/e200/env.py b/amoco/arch/ppc32/e200/env.py index 6f960dd..1b6fecd 100644 --- a/amoco/arch/ppc32/e200/env.py +++ b/amoco/arch/ppc32/e200/env.py @@ -5,44 +5,46 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc +from amoco.cas.expressions import is_reg_pc, is_reg_stack, is_reg_flags +from amoco.cas.expressions import * # noqa: F403 # registers : # ----------- -GPR = [reg("r%d"%i,32) for i in range(32)] +GPR = [reg("r%d" % i, 32) for i in range(32)] XER = reg("XER", 32) -SO = slc(XER,31,1,"SO") -OV = slc(XER,30,1,"OV") -CA = slc(XER,29,1,"CA") -NoB = slc(XER,0,7,"NoB") +SO = slc(XER, 31, 1, "SO") +OV = slc(XER, 30, 1, "OV") +CA = slc(XER, 29, 1, "CA") +NoB = slc(XER, 0, 7, "NoB") -FPR = [reg("f%d"%i,32) for i in range(32)] +FPR = [reg("f%d" % i, 32) for i in range(32)] FPSCR = reg("FPSCR", 32) -CR = reg("CR",32) -MSR = reg("MSR",32) -CTR = reg("CTR",32) -LR = reg("lr",32) +CR = reg("CR", 32) +MSR = reg("MSR", 32) +CTR = reg("CTR", 32) +LR = reg("lr", 32) -CR0 = slc(CR,28,4,"CR0") -CR1 = slc(CR,24,4,"CR1") -CR2 = slc(CR,20,4,"CR2") -CR3 = slc(CR,16,4,"CR3") -CR4 = slc(CR,12,4,"CR4") -CR5 = slc(CR, 8,4,"CR5") -CR6 = slc(CR, 4,4,"CR6") -CR7 = slc(CR, 0,4,"CR7") +CR0 = slc(CR, 28, 4, "CR0") +CR1 = slc(CR, 24, 4, "CR1") +CR2 = slc(CR, 20, 4, "CR2") +CR3 = slc(CR, 16, 4, "CR3") +CR4 = slc(CR, 12, 4, "CR4") +CR5 = slc(CR, 8, 4, "CR5") +CR6 = slc(CR, 4, 4, "CR6") +CR7 = slc(CR, 0, 4, "CR7") -LT = slc(CR0,3,1,"LT") -GT = slc(CR0,2,1,"GT") -EQ = slc(CR0,1,1,"EQ") -SO_ = slc(CR0,0,1,"SO") +LT = slc(CR0, 3, 1, "LT") +GT = slc(CR0, 2, 1, "GT") +EQ = slc(CR0, 1, 1, "EQ") +SO_ = slc(CR0, 0, 1, "SO") -pc = reg("pc",32) -sp = reg("sp",32) +pc = reg("pc", 32) +sp = reg("sp", 32) is_reg_pc(pc) is_reg_stack(sp) @@ -51,5 +53,4 @@ R = GPR # list of registers used by emulator views: -registers = R+[SO,CR0,LR,pc] - +registers = R + [SO, CR0, LR, pc] diff --git a/amoco/arch/ppc32/e200/formats.py b/amoco/arch/ppc32/e200/formats.py index eb396bd..6726547 100644 --- a/amoco/arch/ppc32/e200/formats.py +++ b/amoco/arch/ppc32/e200/formats.py @@ -1,16 +1,19 @@ # -*- coding: utf-8 -*- -from .env import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from .env import composer, cst +from amoco.arch.core import Formatter +from amoco.ui.render import Token + def mnemo(i): mn = i.mnemonic.lower() return [(Token.Mnemonic, "{: <12}".format(mn))] -def deref(base,off): + +def deref(base, off): return "+%d(%s)" % (off, base) + def opers(i): s = [] for op in i.operands: @@ -28,14 +31,16 @@ def opers(i): s.pop() return s + def opers_mem(i): s = [] op = i.operands[0] s.append((Token.Register, op.__str__())) s.append((Token.Literal, ", ")) - s.append((Token.Memory,deref(*(i.operands[1:])))) + s.append((Token.Memory, deref(*(i.operands[1:])))) return s + def opers_adr(i): s = opers(i) if i.misc["imm_ref"] is None and i.address is not None: @@ -43,10 +48,11 @@ def opers_adr(i): s[-1] = (Token.Address, "%s" % (imm_ref)) return s + def opers_rel(i): s = opers(i) if i.misc["imm_ref"] is None and i.address is not None: - imm_ref = composer([cst(0,2),i.operands[-1],i.address[28:32]]) + imm_ref = composer([cst(0, 2), i.operands[-1], i.address[28:32]]) s[-1] = (Token.Address, "%s" % (imm_ref)) return s diff --git a/amoco/arch/ppc32/e200/spec_e200.py b/amoco/arch/ppc32/e200/spec_e200.py index 150c69c..9d7bd84 100644 --- a/amoco/arch/ppc32/e200/spec_e200.py +++ b/amoco/arch/ppc32/e200/spec_e200.py @@ -4,9 +4,6 @@ # Copyright (C) 2022 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from . import env - # import generic PowerPC ISA (book E): -from amoco.arch.ppc32.spec_booke import * - +from amoco.arch.ppc32.spec_booke import * # noqa: F403 diff --git a/amoco/arch/ppc32/env.py b/amoco/arch/ppc32/env.py index e06915d..36bc50d 100644 --- a/amoco/arch/ppc32/env.py +++ b/amoco/arch/ppc32/env.py @@ -5,49 +5,51 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc +from amoco.cas.expressions import is_reg_pc, is_reg_stack, is_reg_flags +from amoco.cas.expressions import * # noqa: F403 # registers : # ----------- # general purpose: -GPR = [reg("r%d"%i,32) for i in range(32)] +GPR = [reg("r%d" % i, 32) for i in range(32)] # Integer Exception register: XER = reg("XER", 32) # XER flags: -SO = slc(XER,31,1,"SO") -OV = slc(XER,30,1,"OV") -CA = slc(XER,29,1,"CA") -NoB = slc(XER,0,7,"NoB") +SO = slc(XER, 31, 1, "SO") +OV = slc(XER, 30, 1, "OV") +CA = slc(XER, 29, 1, "CA") +NoB = slc(XER, 0, 7, "NoB") # floating-point registers: -FPR = [reg("f%d"%i,64) for i in range(32)] +FPR = [reg("f%d" % i, 64) for i in range(32)] FPSCR = reg("FPSCR", 32) -CR = reg("CR",32) # control register -MSR = reg("MSR",32) -CTR = reg("CTR",32) # counter register -LR = reg("lr",32) # link register +CR = reg("CR", 32) # control register +MSR = reg("MSR", 32) +CTR = reg("CTR", 32) # counter register +LR = reg("lr", 32) # link register -CR0 = slc(CR,28,4,"CR0") -CR1 = slc(CR,24,4,"CR1") -CR2 = slc(CR,20,4,"CR2") -CR3 = slc(CR,16,4,"CR3") -CR4 = slc(CR,12,4,"CR4") -CR5 = slc(CR, 8,4,"CR5") -CR6 = slc(CR, 4,4,"CR6") -CR7 = slc(CR, 0,4,"CR7") +CR0 = slc(CR, 28, 4, "CR0") +CR1 = slc(CR, 24, 4, "CR1") +CR2 = slc(CR, 20, 4, "CR2") +CR3 = slc(CR, 16, 4, "CR3") +CR4 = slc(CR, 12, 4, "CR4") +CR5 = slc(CR, 8, 4, "CR5") +CR6 = slc(CR, 4, 4, "CR6") +CR7 = slc(CR, 0, 4, "CR7") -LT = slc(CR0,3,1,"LT") -GT = slc(CR0,2,1,"GT") -EQ = slc(CR0,1,1,"EQ") -SO_ = slc(CR0,0,1,"SO") +LT = slc(CR0, 3, 1, "LT") +GT = slc(CR0, 2, 1, "GT") +EQ = slc(CR0, 1, 1, "EQ") +SO_ = slc(CR0, 0, 1, "SO") -PID = reg("PID",32) +PID = reg("PID", 32) -pc = reg("pc",32) -sp = reg("sp",32) +pc = reg("pc", 32) +sp = reg("sp", 32) is_reg_pc(pc) is_reg_stack(sp) @@ -56,53 +58,59 @@ R = GPR # list of registers used by emulator views: -registers = R+[SO,CR0,LR,pc] +registers = R + [SO, CR0, LR, pc] + def DCREG(indx): - return reg("DCRN_%d"%indx,32) + return reg("DCRN_%d" % indx, 32) + + def SPREG(indx): - return D_SPREG.get(indx,reg("SPREG#%d"%indx,32)) + return D_SPREG.get(indx, reg("SPREG#%d" % indx, 32)) + D_SPREG = { - 58: reg("CSRR0",32), - 59: reg("CSRR1",32), - 9: CTR, - 316: reg("DAC1",32), - 317: reg("DAC2",32), - 308: reg("DBCR0",32), - 309: reg("DBCR1",32), - 310: reg("DBCR2",32), - 304: reg("DBSR",32), - 61: reg("DEAR",32), - 22: reg("DEC",32), - 54: reg("DECAR",32), - 318: reg("DVC1",32), - 319: reg("DVC2",32), - 62: reg("ESR",32), - 63: reg("IVPR",32), - 312: reg("IAC1",32), - 313: reg("IAC2",32), - 314: reg("IAC3",32), - 315: reg("IAC4",32), - 400: reg("IVOR0",32), - 401: reg("IVOR1",32), - 402: reg("IVOR2",32), - 403: reg("IVOR3",32), - 404: reg("IVOR4",32), - 405: reg("IVOR5",32), - 406: reg("IVOR6",32), - 407: reg("IVOR7",32), - 408: reg("IVOR8",32), - 409: reg("IVOR9",32), - 410: reg("IVOR10",32), - 411: reg("IVOR11",32), - 412: reg("IVOR12",32), - 413: reg("IVOR13",32), - 414: reg("IVOR14",32), - 415: reg("IVOR15",32), - 8: LR, - 48: PID, - 286: reg("PIR",32), - 287: reg("PVR",32), - 1: XER, + 58: reg("CSRR0", 32), + 59: reg("CSRR1", 32), + 9: CTR, + 316: reg("DAC1", 32), + 317: reg("DAC2", 32), + 308: reg("DBCR0", 32), + 309: reg("DBCR1", 32), + 310: reg("DBCR2", 32), + 304: reg("DBSR", 32), + 61: reg("DEAR", 32), + 22: reg("DEC", 32), + 54: reg("DECAR", 32), + 318: reg("DVC1", 32), + 319: reg("DVC2", 32), + 62: reg("ESR", 32), + 63: reg("IVPR", 32), + 312: reg("IAC1", 32), + 313: reg("IAC2", 32), + 314: reg("IAC3", 32), + 315: reg("IAC4", 32), + 400: reg("IVOR0", 32), + 401: reg("IVOR1", 32), + 402: reg("IVOR2", 32), + 403: reg("IVOR3", 32), + 404: reg("IVOR4", 32), + 405: reg("IVOR5", 32), + 406: reg("IVOR6", 32), + 407: reg("IVOR7", 32), + 408: reg("IVOR8", 32), + 409: reg("IVOR9", 32), + 410: reg("IVOR10", 32), + 411: reg("IVOR11", 32), + 412: reg("IVOR12", 32), + 413: reg("IVOR13", 32), + 414: reg("IVOR14", 32), + 415: reg("IVOR15", 32), + 8: LR, + 48: PID, + 286: reg("PIR", 32), + 287: reg("PVR", 32), + 1: XER, } + +internals = {} diff --git a/amoco/arch/ppc32/formats.py b/amoco/arch/ppc32/formats.py index 80a0681..72f8653 100644 --- a/amoco/arch/ppc32/formats.py +++ b/amoco/arch/ppc32/formats.py @@ -1,16 +1,19 @@ # -*- coding: utf-8 -*- -from .env import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from .env import composer, cst +from amoco.arch.core import Formatter +from amoco.ui.render import Token + def mnemo(i): mn = i.mnemonic.lower() return [(Token.Mnemonic, "{: <12}".format(mn))] -def deref(base,off): + +def deref(base, off): return "+%d(%s)" % (off, base) + def opers(i): s = [] for op in i.operands: @@ -28,14 +31,16 @@ def opers(i): s.pop() return s + def opers_mem(i): s = [] op = i.operands[0] s.append((Token.Register, op.__str__())) s.append((Token.Literal, ", ")) - s.append((Token.Memory,deref(*(i.operands[1:])))) + s.append((Token.Memory, deref(*(i.operands[1:])))) return s + def opers_adr(i): s = opers(i) if i.misc["imm_ref"] is None and i.address is not None: @@ -43,10 +48,11 @@ def opers_adr(i): s[-1] = (Token.Address, "%s" % (imm_ref)) return s + def opers_rel(i): s = opers(i) if i.misc["imm_ref"] is None and i.address is not None: - imm_ref = composer([cst(0,2),i.operands[-1],i.address[28:32]]) + imm_ref = composer([cst(0, 2), i.operands[-1], i.address[28:32]]) s[-1] = (Token.Address, "%s" % (imm_ref)) return s @@ -62,5 +68,3 @@ def opers_rel(i): PPC_full = Formatter(PPC_full_formats) PPC_full.default = format_default - - diff --git a/amoco/arch/ppc32/spec_booke.py b/amoco/arch/ppc32/spec_booke.py index 46a0fdc..d37742e 100644 --- a/amoco/arch/ppc32/spec_booke.py +++ b/amoco/arch/ppc32/spec_booke.py @@ -6,7 +6,15 @@ from . import env -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_system, + type_other, +) + +# ruff: noqa: F811 # ------------------------------------------------------- # instruction PPC Book E decoders @@ -18,6 +26,7 @@ ISPECS = [] + @ispec("32<[ 011111 rD(5) rA(5) rB(5) .OE 100001010 .Rc ]", mnemonic="add") @ispec("32<[ 011111 rD(5) rA(5) rB(5) .OE 000001010 .Rc ]", mnemonic="addc") @ispec("32<[ 011111 rD(5) rA(5) rB(5) .OE 010001010 .Rc ]", mnemonic="adde") @@ -29,31 +38,35 @@ @ispec("32<[ 011111 rD(5) rA(5) rB(5) .OE 000001000 .Rc ]", mnemonic="subfc") @ispec("32<[ 011111 rD(5) rA(5) rB(5) .OE 010001000 .Rc ]", mnemonic="subfe") @ispec("32<[ 011111 rD(5) rA(5) rB(5) .OE 110001000 .Rc ]", mnemonic="subfe64") -def ppc_OE_Rc(obj,rD,rA,rB): - if obj.mnemonic.endswith("64") and obj.Rc==1: +def ppc_OE_Rc(obj, rD, rA, rB): + if obj.mnemonic.endswith("64") and obj.Rc == 1: raise InstructionError(obj) - obj.operands = [env.GPR[rD],env.GPR[rA],env.GPR[rB]] + obj.operands = [env.GPR[rD], env.GPR[rA], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 011111 rT(5) rA(5) rB(5) .OE 111101001 - ]", mnemonic="divd") @ispec("32<[ 011111 rT(5) rA(5) rB(5) .OE 111001001 - ]", mnemonic="divdu") @ispec("32<[ 011111 rT(5) rA(5) rB(5) .OE 011101001 - ]", mnemonic="mulld") -def ppc_OE(obj,rT,rA,rB): - obj.operands = [env.GPR[rT],env.GPR[rA],env.GPR[rB]] +def ppc_OE(obj, rT, rA, rB): + obj.operands = [env.GPR[rT], env.GPR[rA], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 011111 rT(5) rA(5) rB(5) - 001001001 - ]", mnemonic="mulhd") @ispec("32<[ 011111 rT(5) rA(5) rB(5) - 000001001 - ]", mnemonic="mulhdu") -def ppc_mulhd(obj,rT,rA,rB): - obj.operands = [env.GPR[rT],env.GPR[rA],env.GPR[rB]] +def ppc_mulhd(obj, rT, rA, rB): + obj.operands = [env.GPR[rT], env.GPR[rA], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 011111 rT(5) rA(5) rB(5) - 001001011 .Rc ]", mnemonic="mulhw") @ispec("32<[ 011111 rT(5) rA(5) rB(5) - 000001011 .Rc ]", mnemonic="mulhwu") -def ppc_Rc(obj,rT,rA,rB): - obj.operands = [env.GPR[rT],env.GPR[rA],env.GPR[rB]] +def ppc_Rc(obj, rT, rA, rB): + obj.operands = [env.GPR[rT], env.GPR[rA], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 100010=U rT(5) rA(5) D(16) ]", mnemonic="lbz") @ispec("32<[ 100011=U rT(5) rA(5) D(16) ]", mnemonic="lbzu") @ispec("32<[ 100010=U rT(5) rA(5) D(16) ]", mnemonic="lha") @@ -69,17 +82,18 @@ def ppc_Rc(obj,rT,rA,rB): @ispec("32<[ 101101=U rT(5) rA(5) D(16) ]", mnemonic="sthu") @ispec("32<[ 100100=U rT(5) rA(5) D(16) ]", mnemonic="stw") @ispec("32<[ 100101=U rT(5) rA(5) D(16) ]", mnemonic="stwu") -def ppc_load_store(obj,U,rT,rA,D): - if rA==0: - addr = env.cst(0,32) +def ppc_load_store(obj, U, rT, rA, D): + if rA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[rA] - if U==1: + if U == 1: obj.rA = rA - addr += env.cst(D,16).signextend(32) - obj.operands = [env.GPR[rT],env.ptr(addr)] + addr += env.cst(D, 16).signextend(32) + obj.operands = [env.GPR[rT], env.ptr(addr)] obj.type = type_data_processing + @ispec("32<[ 110010=U rT(5) rA(5) D(16) ]", mnemonic="lfd") @ispec("32<[ 110011=U rT(5) rA(5) D(16) ]", mnemonic="lfdu") @ispec("32<[ 110000=U rT(5) rA(5) D(16) ]", mnemonic="lfs") @@ -89,17 +103,18 @@ def ppc_load_store(obj,U,rT,rA,D): @ispec("32<[ 110100=U rT(5) rA(5) D(16) ]", mnemonic="stfs") @ispec("32<[ 110101=U rT(5) rA(5) D(16) ]", mnemonic="stfsu") @ispec("32<[ 101111=U rT(5) rA(5) D(16) ]", mnemonic="stmw") -def ppc_load_store(obj,U,rT,rA,D): - if rA==0: - addr = env.cst(0,32) +def ppc_load_store(obj, U, rT, rA, D): + if rA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[rA] - if U==1: + if U == 1: obj.rA = rA - addr += env.cst(D,16).signextend(32)<<2 - obj.operands = [env.FPR[rT],env.ptr(addr)] + addr += env.cst(D, 16).signextend(32) << 2 + obj.operands = [env.FPR[rT], env.ptr(addr)] obj.type = type_data_processing + @ispec("32<[ 111010 rT(5) rA(5) DE(12) 000 0=U ]", mnemonic="lbze") @ispec("32<[ 111010 rT(5) rA(5) DE(12) 000 1=U ]", mnemonic="lbzue") @ispec("32<[ 111010 rT(5) rA(5) DE(12) 010 0=U ]", mnemonic="lhae") @@ -114,32 +129,34 @@ def ppc_load_store(obj,U,rT,rA,D): @ispec("32<[ 111010 rT(5) rA(5) DE(12) 101 1=U ]", mnemonic="sthue") @ispec("32<[ 111010 rT(5) rA(5) DE(12) 111 0=U ]", mnemonic="stwe") @ispec("32<[ 111010 rT(5) rA(5) DE(12) 111 1=U ]", mnemonic="stwue") -def ppc_load_store(obj,rT,rA,DE,U): - if rA==0: - addr = env.cst(0,32) +def ppc_load_store(obj, rT, rA, DE, U): + if rA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[rA] - if U==1: + if U == 1: obj.rA = rA - addr += env.cst(DE,12).signextend(32) - obj.operands = [env.GPR[rT],env.ptr(addr)] + addr += env.cst(DE, 12).signextend(32) + obj.operands = [env.GPR[rT], env.ptr(addr)] obj.type = type_data_processing + @ispec("32<[ 111110 rT(5) rA(5) DE(12) 000 0=U ]", mnemonic="lde") @ispec("32<[ 111110 rT(5) rA(5) DE(12) 000 1=U ]", mnemonic="ldue") @ispec("32<[ 111110 rT(5) rA(5) DE(12) 100 0=U ]", mnemonic="stde") @ispec("32<[ 111110 rT(5) rA(5) DE(12) 100 1=U ]", mnemonic="stdue") -def ppc_load_store(obj,rT,rA,DE,U): - if rA==0: - addr = env.cst(0,32) +def ppc_load_store(obj, rT, rA, DE, U): + if rA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[rA] - if U==1: + if U == 1: obj.rA = rA - addr += env.cst(DE,12).signextend(32)<<2 - obj.operands = [env.GPR[rT],env.ptr(addr)] + addr += env.cst(DE, 12).signextend(32) << 2 + obj.operands = [env.GPR[rT], env.ptr(addr)] obj.type = type_data_processing + @ispec("32<[ 111110 rT(5) rA(5) DE(12) 011 0=U ]", mnemonic="lfde") @ispec("32<[ 111110 rT(5) rA(5) DE(12) 011 1=U ]", mnemonic="lfdue") @ispec("32<[ 111110 rT(5) rA(5) DE(12) 010 0=U ]", mnemonic="lfse") @@ -148,17 +165,18 @@ def ppc_load_store(obj,rT,rA,DE,U): @ispec("32<[ 111110 rT(5) rA(5) DE(12) 111 1=U ]", mnemonic="stfdue") @ispec("32<[ 111110 rT(5) rA(5) DE(12) 110 0=U ]", mnemonic="stfse") @ispec("32<[ 111110 rT(5) rA(5) DE(12) 110 1=U ]", mnemonic="stfsue") -def ppc_load_store(obj,rT,rA,DE,U): - if rA==0: - addr = env.cst(0,32) +def ppc_load_store(obj, rT, rA, DE, U): + if rA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[rA] - if U==1: + if U == 1: obj.rA = rA - addr += env.cst(DE,12).signextend(32)<<2 - obj.operands = [env.FPR[rT],env.ptr(addr)] + addr += env.cst(DE, 12).signextend(32) << 2 + obj.operands = [env.FPR[rT], env.ptr(addr)] obj.type = type_data_processing + @ispec("32<[ 011111 rT(5) rA(5) rB(5) 0001 0=U 1 0 111 - ]", mnemonic="lbzx") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 0001 1=U 1 0 111 - ]", mnemonic="lbzux") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 0001 0=U 1 1 111 - ]", mnemonic="lbzxe") @@ -193,17 +211,18 @@ def ppc_load_store(obj,rT,rA,DE,U): @ispec("32<[ 011111 rT(5) rA(5) rB(5) 0010 1=U 1 0 111 - ]", mnemonic="stwux") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 0010 0=U 1 1 111 - ]", mnemonic="stwxe") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 0010 1=U 1 1 111 - ]", mnemonic="stwuxe") -def ppc_load_store(obj,rT,rA,rB,U): - if rA==0: - addr = env.cst(0,32) +def ppc_load_store(obj, rT, rA, rB, U): + if rA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[rA] - if U==1: + if U == 1: obj.rA = rA addr += env.GPR[rB] - obj.operands = [env.GPR[rT],env.ptr(addr)] + obj.operands = [env.GPR[rT], env.ptr(addr)] obj.type = type_data_processing + @ispec("32<[ 011111 rT(5) rA(5) rB(5) 1001 0=U 1 0 111 - ]", mnemonic="lfdx") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 1001 1=U 1 0 111 - ]", mnemonic="lfdux") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 1001 0=U 1 1 111 - ]", mnemonic="lfdxe") @@ -222,17 +241,18 @@ def ppc_load_store(obj,rT,rA,rB,U): @ispec("32<[ 011111 rT(5) rA(5) rB(5) 1010 1=U 1 0 111 - ]", mnemonic="stfsux") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 1010 0=U 1 1 111 - ]", mnemonic="stfsxe") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 1010 1=U 1 1 111 - ]", mnemonic="stfsuxe") -def ppc_load(obj,rT,rA,rB,U): - if rA==0: - addr = env.cst(0,32) +def ppc_load(obj, rT, rA, rB, U): + if rA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[rA] - if U==1: + if U == 1: obj.rA = rA addr += env.GPR[rB] - obj.operands = [env.FPR[rT],env.ptr(addr)] + obj.operands = [env.FPR[rT], env.ptr(addr)] obj.type = type_data_processing + @ispec("32<[ 011111 rT(5) rA(5) rB(5) 011101 1=E 111 - ]", mnemonic="ldarxe") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 000001 0=E 100 - ]", mnemonic="lwarx") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 000111 1=E 110 - ]", mnemonic="lwarxe") @@ -247,48 +267,62 @@ def ppc_load(obj,rT,rA,rB,U): @ispec("32<[ 011111 rT(5) rA(5) rB(5) 101001 1=E 110 - ]", mnemonic="stwbrxe") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 001001 0=E 110 - ]", mnemonic="stwcx") @ispec("32<[ 011111 rT(5) rA(5) rB(5) 001001 1=E 110 - ]", mnemonic="stwcxe") -def ppc_load(obj,rT,rA,rB,E): - if rA==0: +def ppc_load(obj, rT, rA, rB, E): + if rA == 0: addr = env.GPR[rB] else: - addr = env.GPR[rA]+env.GPR[rB] - obj.operands = [env.GPR[rT],env.ptr(addr)] + addr = env.GPR[rA] + env.GPR[rB] + obj.operands = [env.GPR[rT], env.ptr(addr)] obj.type = type_data_processing + @ispec("32<[ 011111 rT(5) rA(5) NB(5) 1001010101 - ]", mnemonic="lswi") -@ispec("32<[ 011111 rT(5) rA(5) NB(5) 1000010101 - ]", mnemonic="lswx") @ispec("32<[ 011111 rT(5) rA(5) NB(5) 1011010101 - ]", mnemonic="stswi") -@ispec("32<[ 011111 rT(5) rA(5) NB(5) 1010010101 - ]", mnemonic="stswx") -def ppc_load(obj,rT,rA,NB): - if rA==0: - addr = env.GPR[rB] +def ppc_load(obj, rT, rA, NB): + if rA == 0: + addr = env.cst(0, 32) else: - addr = env.GPR[rA]+env.GPR[rB] - if obj.mnemonic=="lswi" and NB==0: + addr = env.GPR[rA] + if obj.mnemonic == "lswi" and NB == 0: n = 32 else: n = NB - obj.operands = [env.GPR[rT],env.ptr(addr),NB] + obj.operands = [env.GPR[rT], env.ptr(addr), n] + obj.type = type_data_processing + + +@ispec("32<[ 011111 rT(5) rA(5) rB(5) 1000010101 - ]", mnemonic="lswx") +@ispec("32<[ 011111 rT(5) rA(5) rB(5) 1010010101 - ]", mnemonic="stswx") +def ppc_load(obj, rT, rA, rB): + if rA == 0: + addr = env.GPR[rB] + else: + addr = env.GPR[rA] + env.GPR[rB] + n = env.XER[25:32] + obj.operands = [env.GPR[rT], env.ptr(addr), n] obj.type = type_data_processing + @ispec("32<[ 00111 s rT(5) rA(5) SI(16) ]", mnemonic="addi") @ispec("32<[ 00011 1=s rT(5) rA(5) SI(16) ]", mnemonic="mulli") @ispec("32<[ 00100 0=s rT(5) rA(5) SI(16) ]", mnemonic="subfic") -def ppc_S(obj,s,rT,rA,SI): +def ppc_S(obj, s, rT, rA, SI): obj.s = s - if s==0: - imm = env.cst(SI,16).signextend(32) + if s == 0: + imm = env.cst(SI, 16).signextend(32) else: - imm = env.cst(SI,32)<<16 - obj.operands = [env.GPR[rT],env.GPR[rA],imm] + imm = env.cst(SI, 32) << 16 + obj.operands = [env.GPR[rT], env.GPR[rA], imm] obj.type = type_data_processing + @ispec("32<[ 00110 .Rc rT(5) rA(5) SI(16) ]", mnemonic="addic") -def ppc_Rc(obj,rT,rA,SI): - imm = env.cst(SI,16).signextend(32) - obj.operands = [env.GPR[rT],env.GPR[rA],imm] +def ppc_Rc(obj, rT, rA, SI): + imm = env.cst(SI, 16).signextend(32) + obj.operands = [env.GPR[rT], env.GPR[rA], imm] obj.type = type_data_processing + @ispec("32<[ 011111 rT(5) rA(5) ----- .OE 0=E 11101010 .Rc ]", mnemonic="addme") @ispec("32<[ 011111 rT(5) rA(5) ----- .OE 1=E 11101010 .Rc ]", mnemonic="addme64") @ispec("32<[ 011111 rT(5) rA(5) ----- .OE 0=E 11001010 .Rc ]", mnemonic="addze") @@ -298,13 +332,14 @@ def ppc_Rc(obj,rT,rA,SI): @ispec("32<[ 011111 rT(5) rA(5) ----- .OE 1=E 11101000 .Rc ]", mnemonic="subfme64") @ispec("32<[ 011111 rT(5) rA(5) ----- .OE 0=E 11001000 .Rc ]", mnemonic="subfze") @ispec("32<[ 011111 rT(5) rA(5) ----- .OE 1=E 11001000 .Rc ]", mnemonic="subfze64") -def ppc_OE_Rc(obj,rT,rA,E): - if obj.mnemonic.endswith("64") and obj.Rc==1: +def ppc_OE_Rc(obj, rT, rA, E): + if obj.mnemonic.endswith("64") and obj.Rc == 1: raise InstructionError(obj) obj.E = E - obj.operands = [env.GPR[rT],env.GPR[rA]] + obj.operands = [env.GPR[rT], env.GPR[rA]] obj.type = type_data_processing + @ispec("32<[ 011111 rS(5) rA(5) rB(5) 0000011100 .Rc ]", mnemonic="and") @ispec("32<[ 011111 rS(5) rA(5) rB(5) 0000111100 .Rc ]", mnemonic="andc") @ispec("32<[ 011111 rS(5) rA(5) rB(5) 0100011100 .Rc ]", mnemonic="eqv") @@ -316,54 +351,60 @@ def ppc_OE_Rc(obj,rT,rA,E): @ispec("32<[ 011111 rS(5) rA(5) rB(5) 1100011000 .Rc ]", mnemonic="sraw") @ispec("32<[ 011111 rS(5) rA(5) rB(5) 1000011000 .Rc ]", mnemonic="srw") @ispec("32<[ 011111 rS(5) rA(5) rB(5) 0100111100 .Rc ]", mnemonic="xor") -def ppc_Rc(obj,rS,rA,rB): - obj.operands = [env.GPR[rA],env.GPR[rS],env.GPR[rB]] +def ppc_Rc(obj, rS, rA, rB): + obj.operands = [env.GPR[rA], env.GPR[rS], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 011111 rS(5) rA(5) SH(5) 1100011000 .Rc ]", mnemonic="srawi") -def ppc_Rc(obj,rS,rA,SH): - obj.operands = [env.GPR[rA],env.GPR[rS],env.cst(SH,5)] +def ppc_Rc(obj, rS, rA, SH): + obj.operands = [env.GPR[rA], env.GPR[rS], env.cst(SH, 5)] obj.type = type_data_processing + @ispec("32<[ 011111 rS(5) rA(5) rB(5) 0000011011 - ]", mnemonic="sld") @ispec("32<[ 011111 rS(5) rA(5) rB(5) 1100011010 - ]", mnemonic="srad") @ispec("32<[ 011111 rS(5) rA(5) rB(5) 1000011011 - ]", mnemonic="srd") -def ppc_sld(obj,rS,rA,rB): - obj.operands = [env.GPR[rA],env.GPR[rS],env.GPR[rB]] +def ppc_sld(obj, rS, rA, rB): + obj.operands = [env.GPR[rA], env.GPR[rS], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 011110 rS(5) rA(5) rB(5) mb(5) mb0 1000 - ]", mnemonic="rldcl") @ispec("32<[ 011110 rS(5) rA(5) rB(5) mb(5) mb0 1001 - ]", mnemonic="rldcr") -def ppc_rldc(obj,rS,rA,rB,mb,mb0): - mask = env.cst(mb+(mb0<<5),32) - obj.operands = [env.GPR[rA],env.GPR[rS],env.GPR[rB],mask] +def ppc_rldc(obj, rS, rA, rB, mb, mb0): + mask = env.cst(mb + (mb0 << 5), 32) + obj.operands = [env.GPR[rA], env.GPR[rS], env.GPR[rB], mask] obj.type = type_data_processing + @ispec("32<[ 010100 rS(5) rA(5) sh(5) mb(5) me(5) .Rc ]", mnemonic="rlwimi") @ispec("32<[ 010111 rS(5) rA(5) sh(5) mb(5) me(5) .Rc ]", mnemonic="rlwnm") @ispec("32<[ 010101 rS(5) rA(5) sh(5) mb(5) me(5) .Rc ]", mnemonic="rlwinm") -def ppc_Rc(obj,rS,rA,sh,mb,me): - sh = env.cst(sh,5) - mb = env.cst(mb,5) - me = env.cst(me,5) - obj.operands = [env.GPR[rA],env.GPR[rS],sh,mb,me] +def ppc_Rc(obj, rS, rA, sh, mb, me): + sh = env.cst(sh, 5) + mb = env.cst(mb, 5) + me = env.cst(me, 5) + obj.operands = [env.GPR[rA], env.GPR[rS], sh, mb, me] obj.type = type_data_processing + @ispec("32<[ 011110 rS(5) rA(5) sh(5) mb(5) mb0 000 sh0 - ]", mnemonic="rldicl") @ispec("32<[ 011110 rS(5) rA(5) sh(5) mb(5) mb0 001 sh0 - ]", mnemonic="rldicr") @ispec("32<[ 011110 rS(5) rA(5) sh(5) mb(5) mb0 010 sh0 - ]", mnemonic="rldic") @ispec("32<[ 011110 rS(5) rA(5) sh(5) mb(5) mb0 011 sh0 - ]", mnemonic="rldimi") -def ppc_rld(obj,rS,rA,sh,mb,mb0,sh0): - mask = env.cst(mb+(mb0<<5),32) - obj.operands = [env.GPR[rA],env.GPR[rS],env.cst(sh+(sh0<<5),6),mask] +def ppc_rld(obj, rS, rA, sh, mb, mb0, sh0): + mask = env.cst(mb + (mb0 << 5), 32) + obj.operands = [env.GPR[rA], env.GPR[rS], env.cst(sh + (sh0 << 5), 6), mask] obj.type = type_data_processing + @ispec("32<[ 011110 rS(5) rA(5) sh(5) 110011 101 sh0 - ]", mnemonic="sradi") -def ppc_rld(obj,rS,rA,sh,sh0): - mask = env.cst(mb+(mb0<<5),32) - obj.operands = [env.GPR[rA],env.GPR[rS],env.cst(sh+(sh0<<5),6)] +def ppc_rld(obj, rS, rA, sh, sh0): + obj.operands = [env.GPR[rA], env.GPR[rS], env.cst(sh + (sh0 << 5), 6)] obj.type = type_data_processing + @ispec("32<[ 111111 FRT(5) ----- FRB(5) 0100001000 .Rc ]", mnemonic="fabs") @ispec("32<[ 111111 FRT(5) ----- FRB(5) 0000001110 .Rc ]", mnemonic="fctiw") @ispec("32<[ 111111 FRT(5) ----- FRB(5) 0000001111 .Rc ]", mnemonic="fctiwz") @@ -371,35 +412,39 @@ def ppc_rld(obj,rS,rA,sh,sh0): @ispec("32<[ 111111 FRT(5) ----- FRB(5) 0010001000 .Rc ]", mnemonic="fnabs") @ispec("32<[ 111111 FRT(5) ----- FRB(5) 0000101000 .Rc ]", mnemonic="fneg") @ispec("32<[ 111111 FRT(5) ----- FRB(5) 0000001100 .Rc ]", mnemonic="frsp") -def ppc_Rc(obj,FRT,FRB): - obj.operands = [env.FPR[FRT],env.FPR[FRB]] +def ppc_Rc(obj, FRT, FRB): + obj.operands = [env.FPR[FRT], env.FPR[FRB]] obj.type = type_data_processing + @ispec("32<[ 111111 FRT(5) ----- FRB(5) 1101001110 - ]", mnemonic="fcfid") @ispec("32<[ 111111 FRT(5) ----- FRB(5) 1100101110 - ]", mnemonic="fctid") @ispec("32<[ 111111 FRT(5) ----- FRB(5) 1100101111 - ]", mnemonic="fctidz") -def ppc_fcfid(obj,FRT,FRB): - obj.operands = [env.FPR[FRT],env.FPR[FRB]] +def ppc_fcfid(obj, FRT, FRB): + obj.operands = [env.FPR[FRT], env.FPR[FRB]] obj.type = type_data_processing + @ispec("32<[ 111111 FRT(5) FRA(5) FRB(5) -----10101 .Rc ]", mnemonic="fadd") @ispec("32<[ 111011 FRT(5) FRA(5) FRB(5) -----10101 .Rc ]", mnemonic="fadds") @ispec("32<[ 111111 FRT(5) FRA(5) FRB(5) -----10010 .Rc ]", mnemonic="fdiv") @ispec("32<[ 111011 FRT(5) FRA(5) FRB(5) -----10010 .Rc ]", mnemonic="fdivs") @ispec("32<[ 111111 FRT(5) FRA(5) FRB(5) -----10100 .Rc ]", mnemonic="fsub") @ispec("32<[ 111011 FRT(5) FRA(5) FRB(5) -----10100 .Rc ]", mnemonic="fsubs") -def ppc_Rc(obj,FRT,FRA,FRB): - obj.operands = [env.FPR[FRT],env.FPR[FRA],env.FPR[FRB]] +def ppc_Rc(obj, FRT, FRA, FRB): + obj.operands = [env.FPR[FRT], env.FPR[FRA], env.FPR[FRB]] obj.type = type_data_processing + @ispec("32<[ 111011 FRT(5) ----- FRB(5) ----- 11000 .Rc ]", mnemonic="fres") @ispec("32<[ 111111 FRT(5) ----- FRB(5) ----- 11010 .Rc ]", mnemonic="frsqrte") @ispec("32<[ 111111 FRT(5) ----- FRB(5) ----- 10110 .Rc ]", mnemonic="fsqrt") @ispec("32<[ 111011 FRT(5) ----- FRB(5) ----- 10110 .Rc ]", mnemonic="fsqrts") -def ppc_Rc(obj,FRT,FRB): - obj.operands = [env.FPR[FRT],env.FPR[FRB]] +def ppc_Rc(obj, FRT, FRB): + obj.operands = [env.FPR[FRT], env.FPR[FRB]] obj.type = type_data_processing + @ispec("32<[ 111111 FRT(5) FRA(5) FRB(5) FRC(5) 11101 .Rc ]", mnemonic="fmadd") @ispec("32<[ 111011 FRT(5) FRA(5) FRB(5) FRC(5) 11101 .Rc ]", mnemonic="fmadds") @ispec("32<[ 111111 FRT(5) FRA(5) FRB(5) FRC(5) 11100 .Rc ]", mnemonic="fmsub") @@ -409,177 +454,203 @@ def ppc_Rc(obj,FRT,FRB): @ispec("32<[ 111111 FRT(5) FRA(5) FRB(5) FRC(5) 11110 .Rc ]", mnemonic="fnmsub") @ispec("32<[ 111011 FRT(5) FRA(5) FRB(5) FRC(5) 11110 .Rc ]", mnemonic="fnmsubs") @ispec("32<[ 111111 FRT(5) FRA(5) FRB(5) FRC(5) 10111 .Rc ]", mnemonic="fsel") -def ppc_Rc(obj,FRT,FRA,FRB,FRC): - obj.operands = [env.FPR[FRT],env.FPR[FRA],env.FPR[FRC],env.FPR[FRB]] +def ppc_Rc(obj, FRT, FRA, FRB, FRC): + obj.operands = [env.FPR[FRT], env.FPR[FRA], env.FPR[FRC], env.FPR[FRB]] obj.type = type_data_processing + @ispec("32<[ 111111 FRT(5) FRA(5) ----- FRC(5) 11101 .Rc ]", mnemonic="fmul") @ispec("32<[ 111011 FRT(5) FRA(5) ----- FRC(5) 11101 .Rc ]", mnemonic="fmuls") -def ppc_Rc(obj,FRT,FRA,FRC): - obj.operands = [env.FPR[FRT],env.FPR[FRA],env.FPR[FRC],env.FPR[FRB]] +def ppc_Rc(obj, FRT, FRA, FRC): + obj.operands = [env.FPR[FRT], env.FPR[FRA], env.FPR[FRC]] obj.type = type_data_processing + @ispec("32<[ 111111 FRT(5) ----- ----- 10010 00111 .Rc ]", mnemonic="mffs") -def ppc_Rc(obj,FRT): +def ppc_Rc(obj, FRT): obj.operands = [env.FPR[FRT]] obj.type = type_data_processing + @ispec("32<[ 111111 - FLM(8) - FRB(5) 1011000111 .Rc ]", mnemonic="mtfsf") -def ppc_Rc(obj,FLM,FRB): - obj.operands = [env.cst(FLM,8),env.FPR[FRB]] +def ppc_Rc(obj, FLM, FRB): + obj.operands = [env.cst(FLM, 8), env.FPR[FRB]] obj.type = type_data_processing + @ispec("32<[ 111111 BF(3) ------- U(4) - 0010000110 .Rc ]", mnemonic="mtfsfi") -def ppc_Rc(obj,BF,U): - obj.operands = [env.cst(BF,3),env.cst(U,4)] +def ppc_Rc(obj, BF, U): + obj.operands = [env.cst(BF, 3), env.cst(U, 4)] obj.type = type_data_processing + @ispec("32<[ 111111 BF(3) -- FRA(5) FRB(5) 0000000000 - ]", mnemonic="fcmpu") @ispec("32<[ 111111 BF(3) -- FRA(5) FRB(5) 0000100000 - ]", mnemonic="fcmpuo") -def ppc_fcmpu(obj,BF,FRA,FRB): - obj.operands = [BF,env.FPR[FRA],env.FPR[FRB]] +def ppc_fcmpu(obj, BF, FRA, FRB): + obj.operands = [BF, env.FPR[FRA], env.FPR[FRB]] obj.type = type_data_processing + @ispec("32<[ 01111 0=s rS(5) rA(5) UI(16) ]", mnemonic="andi") @ispec("32<[ 01111 1=s rS(5) rA(5) UI(16) ]", mnemonic="andis") @ispec("32<[ 01100 0=s rS(5) rA(5) UI(16) ]", mnemonic="ori") @ispec("32<[ 01100 1=s rS(5) rA(5) UI(16) ]", mnemonic="oris") @ispec("32<[ 01101 0=s rS(5) rA(5) UI(16) ]", mnemonic="xori") @ispec("32<[ 01101 1=s rS(5) rA(5) UI(16) ]", mnemonic="xoris") -def ppc_S(obj,s,rS,rA,UI): +def ppc_S(obj, s, rS, rA, UI): obj.Rc = 1 obj.s = s - if s==0: - imm = env.cst(UI,16).zeroextend(32) + if s == 0: + imm = env.cst(UI, 16).zeroextend(32) else: - imm = env.cst(UI,32)<<16 - obj.operands = [env.GPR[rA],env.GPR[rS],imm] + imm = env.cst(UI, 32) << 16 + obj.operands = [env.GPR[rA], env.GPR[rS], imm] obj.type = type_data_processing + @ispec("32<[ 010 E 10 LI(24) .AA .LK ]", mnemonic="b") -def ppc_E_AA_LK(obj,E,LI): +def ppc_E_AA_LK(obj, E, LI): obj.E = E - soff = env.cst(LI,24).signextend(32)<<2 + soff = env.cst(LI, 24).signextend(32) << 2 obj.operands = [soff] obj.type = type_control_flow + @ispec("32<[ 010000 ~BO(5) ~BI(5) BD(14) .AA .LK ]", mnemonic="bc") @ispec("32<[ 001001 ~BO(5) ~BI(5) BD(14) .AA .LK ]", mnemonic="bce") -def ppc_AA_LK(obj,BO,BI,BD): - soff = env.cst(BD,14).signextend(32)<<2 - obj.operands = [BO,BI,soff] +def ppc_AA_LK(obj, BO, BI, BD): + soff = env.cst(BD, 14).signextend(32) << 2 + obj.operands = [BO, BI, soff] obj.type = type_control_flow + @ispec("32<[ 010011 ~BO(5) ~BI(5) ----- 100001000 .E .LK ]", mnemonic="bcctr") @ispec("32<[ 010011 ~BO(5) ~BI(5) ----- 000001000 .E .LK ]", mnemonic="bclr") -def ppc_E_LK(obj,BO,BI): - obj.operands = [BO,BI] +def ppc_E_LK(obj, BO, BI): + obj.operands = [BO, BI] obj.type = type_control_flow + @ispec("32<[ 011111 TO(5) RA(5) RB(5) 0001000100 - ]", mnemonic="td") @ispec("32<[ 011111 TO(5) RA(5) RB(5) 0000000100 - ]", mnemonic="tw") -def ppc_trap(obj,TO,RA,RB): - obj.operands = [env.cst(TO,5),env.GPR[RA],env.GPR[RB]] +def ppc_trap(obj, TO, RA, RB): + obj.operands = [env.cst(TO, 5), env.GPR[RA], env.GPR[RB]] obj.type = type_system + @ispec("32<[ 011111 ----- RA(5) RB(5) 1100010010=E - ]", mnemonic="tlbivax") @ispec("32<[ 011111 ----- RA(5) RB(5) 1100010011=E - ]", mnemonic="tlbivaxe") -def ppc_trap(obj,RA,RB,E): - if RA==0: - addr = env.cst(0,32) +def ppc_trap(obj, RA, RB, E): + if RA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[RA] obj.E = E - obj.operands = [addr,env.GPR[RB]] + obj.operands = [addr, env.GPR[RB]] obj.type = type_system + @ispec("32<[ 000010 TO(5) RA(5) SI(16) ]", mnemonic="tdi") @ispec("32<[ 000011 TO(5) RA(5) SI(16) ]", mnemonic="twi") -def ppc_trap(obj,TO,RA,SI): - obj.operands = [env.cst(TO,5),env.GPR[RA],env.cst(SI,16).signextend(32)] +def ppc_trap(obj, TO, RA, SI): + obj.operands = [env.cst(TO, 5), env.GPR[RA], env.cst(SI, 16).signextend(32)] obj.type = type_system + @ispec("32<[ 011111 BF(3) - L rA(5) rB(5) 0000000000 - ]", mnemonic="cmp") @ispec("32<[ 011111 BF(3) - L rA(5) rB(5) 0000100000 - ]", mnemonic="cmpl") -def ppc_cmp(obj,BF,L,rA,rB): - obj.operands = [BF,L,env.GPR[rA],env.GPR[rB]] +def ppc_cmp(obj, BF, L, rA, rB): + obj.operands = [BF, L, env.GPR[rA], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 010011 BF(3) -- BFA(3) ------- 0000000000 - ]", mnemonic="mcfr") @ispec("32<[ 111111 BF(3) -- BFA(3) ------- 0001000000 - ]", mnemonic="mcfrs") -def ppc_mcfr(obj,BF,BFA): - obj.operands = [BF,BFA] +def ppc_mcfr(obj, BF, BFA): + obj.operands = [BF, BFA] obj.type = type_data_processing + @ispec("32<[ 011111 BF(3) ----- ------- 1000000000 - ]", mnemonic="mcrxr") @ispec("32<[ 011111 BF(3) ----- ------- 1000100000 - ]", mnemonic="mcrxr64") -def ppc_mcrx(obj,BF): +def ppc_mcrx(obj, BF): obj.operands = [BF] obj.type = type_data_processing + @ispec("32<[ 111111 BT(5) ---------- 0001000110 .Rc ]", mnemonic="mtfsb0") @ispec("32<[ 111111 BT(5) ---------- 0000100110 .Rc ]", mnemonic="mtfsb1") -def ppc_mcrx(obj,BT): +def ppc_mcrx(obj, BT): obj.operands = [BT] obj.type = type_data_processing + @ispec("32<[ 011111 RT(5) RA(5) ----- 0100010011 - ]", mnemonic="mfapidi") -def ppc_mfapidi(obj,RT,RA): - obj.operands = [env.GPR[RT],env.GPR[RA]] +def ppc_mfapidi(obj, RT, RA): + obj.operands = [env.GPR[RT], env.GPR[RA]] obj.type = type_data_processing + @ispec("32<[ 011111 RT(5) ----- ----- 0000010011 - ]", mnemonic="mfcr") @ispec("32<[ 011111 RT(5) ----- ----- 0001010011 - ]", mnemonic="mfmsr") @ispec("32<[ 011111 RT(5) ----- ----- 0010010010 - ]", mnemonic="mtmsr") -def ppc_mfcr(obj,RT): +def ppc_mfcr(obj, RT): obj.operands = [env.GPR[RT]] obj.type = type_data_processing + @ispec("32<[ 011111 RT(5) dcrn2(5) dcrn1(5) 0101000011 - ]", mnemonic="mfdcr") -def ppc_mfdcr(obj,RT,dcrn2,dcrn1): - obj.operands = [env.GPR[RT],env.DCREG(dcrn2+(dcrn1<<5))] +def ppc_mfdcr(obj, RT, dcrn2, dcrn1): + obj.operands = [env.GPR[RT], env.DCREG(dcrn2 + (dcrn1 << 5))] obj.type = type_data_processing + @ispec("32<[ 011111 RS(5) dcrn2(5) dcrn1(5) 0111000011 - ]", mnemonic="mtdcr") -def ppc_mtdcr(obj,RS,dcrn2,dcrn1): - obj.operands = [env.DCREG(dcrn2+(dcrn1<<5)),env.GPR[RS]] +def ppc_mtdcr(obj, RS, dcrn2, dcrn1): + obj.operands = [env.DCREG(dcrn2 + (dcrn1 << 5)), env.GPR[RS]] obj.type = type_data_processing + @ispec("32<[ 011111 RT(5) sprn2(5) sprn1(5) 0101010011 - ]", mnemonic="mfspr") -def ppc_mfspr(obj,RT,sprn2,sprn1): - obj.operands = [env.GPR[RT],env.SPREG(sprn2+(sprn1<<5))] +def ppc_mfspr(obj, RT, sprn2, sprn1): + obj.operands = [env.GPR[RT], env.SPREG(sprn2 + (sprn1 << 5))] obj.type = type_data_processing + @ispec("32<[ 011111 RS(5) sprn2(5) sprn1(5) 0111010011 - ]", mnemonic="mtspr") -def ppc_mtspr(obj,RS,sprn2,sprn1): - obj.operands = [env.SPREG(sprn2+(sprn1<<5)),env.GPR[RS]] +def ppc_mtspr(obj, RS, sprn2, sprn1): + obj.operands = [env.SPREG(sprn2 + (sprn1 << 5)), env.GPR[RS]] obj.type = type_data_processing + @ispec("32<[ 011111 RS(5) - FXM(8) - 0010010000 - ]", mnemonic="mfspr") -def ppc_mtcrf(obj,RS,FXM): - obj.operands = [env.cst(FXM,8),env.GPR[RS]] +def ppc_mtcrf(obj, RS, FXM): + obj.operands = [env.cst(FXM, 8), env.GPR[RS]] obj.type = type_data_processing + @ispec("32<[ 001011 BF(3) - L rA(5) SI(16) ]", mnemonic="cmpi") -def ppc_cmpi(obj,BF,L,rA,SI): +def ppc_cmpi(obj, BF, L, rA, SI): if obj.mnemonic == "cmpi": - imm = env.cst(SI,16).signextend(32) + imm = env.cst(SI, 16).signextend(32) else: - imm = env.cst(SI,16).zeroextend(32) - obj.operands = [BF,L,env.GPR[rA],imm] + imm = env.cst(SI, 16).zeroextend(32) + obj.operands = [BF, L, env.GPR[rA], imm] obj.type = type_data_processing + @ispec("32<[ 011111 rS(5) rA(5) ----- 0000 0 11010 .Rc ]", mnemonic="cntlzw") @ispec("32<[ 011111 rS(5) rA(5) ----- 0000 1 11010 .Rc ]", mnemonic="cntlzd") @ispec("32<[ 011111 rS(5) rA(5) ----- 1110 1 11010 .Rc ]", mnemonic="extsb") @ispec("32<[ 011111 rS(5) rA(5) ----- 1110 0 11010 .Rc ]", mnemonic="extsh") @ispec("32<[ 011111 rS(5) rA(5) ----- 1111 0 11010 .Rc ]", mnemonic="extsw") -def ppc_Rc(obj,rS,rA): - if obj.mnemonic=="cntlzd" and obj.Rc==1: +def ppc_Rc(obj, rS, rA): + if obj.mnemonic == "cntlzd" and obj.Rc == 1: raise InstructionError(obj) - obj.operands = [env.GPR[rA],env.GPR[rS]] + obj.operands = [env.GPR[rA], env.GPR[rS]] obj.type = type_data_processing + @ispec("32<[ 010011 BT(5) BA(5) BB(5) 0100000001 - ]", mnemonic="crand") @ispec("32<[ 010011 BT(5) BA(5) BB(5) 0010000001 - ]", mnemonic="crandc") @ispec("32<[ 010011 BT(5) BA(5) BB(5) 0100100001 - ]", mnemonic="creqv") @@ -588,10 +659,11 @@ def ppc_Rc(obj,rS,rA): @ispec("32<[ 010011 BT(5) BA(5) BB(5) 0111000001 - ]", mnemonic="cror") @ispec("32<[ 010011 BT(5) BA(5) BB(5) 0110100001 - ]", mnemonic="crorc") @ispec("32<[ 010011 BT(5) BA(5) BB(5) 0011000001 - ]", mnemonic="crxor") -def ppc_cr(obj,BT,BA,BB): - obj.operands = [env.CR[BT:BT+1], env.CR[BA:BA+1], env.CR[BB:BB+1]] +def ppc_cr(obj, BT, BA, BB): + obj.operands = [env.CR[BT : BT + 1], env.CR[BA : BA + 1], env.CR[BB : BB + 1]] obj.type = type_data_processing + @ispec("32<[ 011111 ----- rA(5) rB(5) 101111 0 110 - ]", mnemonic="dcba") @ispec("32<[ 011111 ----- rA(5) rB(5) 101111 1 110 - ]", mnemonic="dcbae") @ispec("32<[ 011111 ----- rA(5) rB(5) 000101 0 110 - ]", mnemonic="dcbf") @@ -604,20 +676,22 @@ def ppc_cr(obj,BT,BA,BB): @ispec("32<[ 011111 ----- rA(5) rB(5) 111111 1 110 - ]", mnemonic="dcbze") @ispec("32<[ 011111 ----- rA(5) rB(5) 111101 0 110 - ]", mnemonic="icbi") @ispec("32<[ 011111 ----- rA(5) rB(5) 111101 1 110 - ]", mnemonic="icbie") -def ppc_dc(obj,rA,rB): - obj.operands = [env.GPR[rA],env.GPR[rB]] +def ppc_dc(obj, rA, rB): + obj.operands = [env.GPR[rA], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 011111 CT(5) rA(5) rB(5) 010001 0 110- ]", mnemonic="dcbt") @ispec("32<[ 011111 CT(5) rA(5) rB(5) 010001 1 110- ]", mnemonic="dcbte") @ispec("32<[ 011111 CT(5) rA(5) rB(5) 001111 0 110- ]", mnemonic="dcbtst") @ispec("32<[ 011111 CT(5) rA(5) rB(5) 001111 1 110- ]", mnemonic="dcbtste") @ispec("32<[ 011111 CT(5) rA(5) rB(5) 000001 0 110- ]", mnemonic="icbt") @ispec("32<[ 011111 CT(5) rA(5) rB(5) 000001 1 110- ]", mnemonic="icbte") -def ppc_dc2(obj,CT,rA,rB): - obj.operands = [env.cst(CT,5),env.GPR[rA],env.GPR[rB]] +def ppc_dc2(obj, CT, rA, rB): + obj.operands = [env.cst(CT, 5), env.GPR[rA], env.GPR[rB]] obj.type = type_data_processing + @ispec("32<[ 010011 --------------- 0010010110 - ]", mnemonic="isync") @ispec("32<[ 011111 --------------- 1001010110 - ]", mnemonic="msync") @ispec("32<[ 010011 --------------- 0000110011 - ]", mnemonic="rfci") @@ -628,35 +702,39 @@ def ppc_dc2(obj): obj.operands = [] obj.type = type_other + @ispec("32<[ 011111 data(15) 1110110010 - ]", mnemonic="tlbre") @ispec("32<[ 011111 data(15) 1111010010 - ]", mnemonic="tlbwe") -def ppc_dc2(obj,data): - obj.tlb_data = env.cst(data,15) +def ppc_dc2(obj, data): + obj.tlb_data = env.cst(data, 15) obj.operands = [] obj.type = type_other + @ispec("32<[ 011111 ----- rA(5) rB(5) 1110010010 - ]", mnemonic="tlbsx") @ispec("32<[ 011111 ----- rA(5) rB(5) 1110010011 - ]", mnemonic="tlbsxe") -def ppc_tlb(obj,rA,rB): - if rA==0: - addr = env.cst(0,32) +def ppc_tlb(obj, rA, rB): + if rA == 0: + addr = env.cst(0, 32) else: addr = env.GPR[rA] - obj.operands = [addr,env.GPR[rB]] + obj.operands = [addr, env.GPR[rB]] obj.type = type_other + @ispec("32<[ 011111 MO(5) ---------- 1101010110 - ]", mnemonic="mbar") -def ppc_dc2(obj,MO): - obj.operands = [env.cst(MO,5)] +def ppc_dc2(obj, MO): + obj.operands = [env.cst(MO, 5)] obj.type = type_other + @ispec("32<[ 011111 RS(5) ----- ----- 0010000011 - ]", mnemonic="wrtee") -def ppc_dc2(obj,RS): +def ppc_dc2(obj, RS): obj.operands = [env.GPR[RS][31:32]] obj.type = type_system + @ispec("32<[ 011111 ----- ----- E---- 0010100011 - ]", mnemonic="wrteei") -def ppc_dc2(obj,E): - obj.operands = [env.cst(E,1)] +def ppc_dc2(obj, E): + obj.operands = [env.cst(E, 1)] obj.type = type_system - diff --git a/amoco/arch/ppc32/spec_vle.py b/amoco/arch/ppc32/spec_vle.py index f7e5901..bc8bc5f 100644 --- a/amoco/arch/ppc32/spec_vle.py +++ b/amoco/arch/ppc32/spec_vle.py @@ -6,11 +6,16 @@ from . import env -from amoco.arch.core import * +from amoco.arch.core import ispec +from amoco.arch.core import type_data_processing ISPECS = [] + @ispec("16<[ 000001 00 rY(4) rX(4) ]", mnemonic="se_add") -def ppc_addx(obj,rX,rY): - obj.operands = [env.GPR[rX],env.GPR[rY]] +def ppc_addx(obj, rX, rY): + obj.operands = [env.GPR[rX], env.GPR[rY]] obj.type = type_data_processing + + +# TODO diff --git a/amoco/arch/riscv/cpu_rv32i.py b/amoco/arch/riscv/cpu_rv32i.py index b325cd3..474969f 100644 --- a/amoco/arch/riscv/cpu_rv32i.py +++ b/amoco/arch/riscv/cpu_rv32i.py @@ -1,18 +1,14 @@ # -*- coding: utf-8 -*- -from amoco.arch.riscv.rv32i.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.riscv.rv32i import env +from amoco.arch.riscv.rv32i import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_riscv = type("instruction_riscv", (instruction,), {}) -instruction_riscv.set_uarch(uarch) from amoco.arch.riscv.rv32i.formats import RISCV_full -from amoco.arch.riscv.rv32i.formats import RISCV_synthetic instruction_riscv.set_formatter(RISCV_full) @@ -21,10 +17,4 @@ disassemble = disassembler([spec_rv32i], iclass=instruction_riscv) - -def PC(state=None): - return pc - - -def get_data_endian(): - return 1 # LE +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/riscv/cpu_rv64i.py b/amoco/arch/riscv/cpu_rv64i.py index 2ac9a01..17b93ca 100644 --- a/amoco/arch/riscv/cpu_rv64i.py +++ b/amoco/arch/riscv/cpu_rv64i.py @@ -1,18 +1,14 @@ # -*- coding: utf-8 -*- -from amoco.arch.riscv.rv64i.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.riscv.rv64i import env +from amoco.arch.riscv.rv64i import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_riscv64 = type("instruction_riscv64", (instruction,), {}) -instruction_riscv64.set_uarch(uarch) from amoco.arch.riscv.rv64i.formats import RISCV_full -from amoco.arch.riscv.rv64i.formats import RISCV_synthetic instruction_riscv64.set_formatter(RISCV_full) @@ -21,10 +17,4 @@ disassemble = disassembler([spec_rv64i], iclass=instruction_riscv64) - -def PC(state=None): - return pc - - -def get_data_endian(): - return 1 # LE +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/riscv/formats.py b/amoco/arch/riscv/formats.py index bc5f0eb..eca3e89 100644 --- a/amoco/arch/riscv/formats.py +++ b/amoco/arch/riscv/formats.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -from .env import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from .env import x +from amoco.arch.core import Formatter +from amoco.ui.render import Token def mnemo(i): diff --git a/amoco/arch/riscv/rv32i/asm.py b/amoco/arch/riscv/rv32i/asm.py index e07a4b4..88ceb37 100644 --- a/amoco/arch/riscv/rv32i/asm.py +++ b/amoco/arch/riscv/rv32i/asm.py @@ -4,10 +4,9 @@ # Copyright (C) 2017 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * -from ..utils import * +from .env import sp, pc, cst, tst, zero, mem, oper +from .env import internals, OP_LTU, OP_GEU, OP_ASR -from amoco.cas.utils import * # ------------------------------------------------------------------------------ # helpers and decorators : @@ -30,7 +29,7 @@ def npc(ins, fmap): def trap(ins, fmap, trapname): - fmap.internals["trap"] = trapname + internals["trap"] = trapname # i_xxx is the translation of RISC-V instruction xxx. @@ -297,42 +296,6 @@ def i_BGEU(ins, fmap): fmap[pc] = fmap(tst(oper(OP_GEU, r1, r2), pc + imm, pc + ins.length)) -@__npc -def i_SB(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src[0:8]) - - -@__npc -def i_SH(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src[0:16]) - - -@__npc -def i_SW(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src) - - -@__npc -def i_LB(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src).signextend(32) - - -i_LH = i_LW = i_LB - - -@__npc -def i_LBU(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src).zeroextend(32) - - -i_LHU = i_LBU - - @__npc def i_FENCE(ins, fmap): pass diff --git a/amoco/arch/riscv/rv32i/env.py b/amoco/arch/riscv/rv32i/env.py index ef8dea3..44d9e88 100644 --- a/amoco/arch/riscv/rv32i/env.py +++ b/amoco/arch/riscv/rv32i/env.py @@ -5,7 +5,8 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, cst, is_reg_pc, is_reg_stack +from amoco.cas.expressions import * # noqa: F403 # reference documentations: # The RISC-V Instruction Set Manual, volume I, User level ISA, version 1.2. @@ -82,4 +83,6 @@ is_reg_pc(pc) is_reg_stack(sp) -registers = x+[pc] +registers = x + [pc] + +internals = {} diff --git a/amoco/arch/riscv/rv32i/formats.py b/amoco/arch/riscv/rv32i/formats.py index bc5f0eb..eca3e89 100644 --- a/amoco/arch/riscv/rv32i/formats.py +++ b/amoco/arch/riscv/rv32i/formats.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -from .env import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from .env import x +from amoco.arch.core import Formatter +from amoco.ui.render import Token def mnemo(i): diff --git a/amoco/arch/riscv/rv32i/spec_rv32i.py b/amoco/arch/riscv/rv32i/spec_rv32i.py index 360200e..720c21b 100644 --- a/amoco/arch/riscv/rv32i/spec_rv32i.py +++ b/amoco/arch/riscv/rv32i/spec_rv32i.py @@ -6,7 +6,15 @@ from amoco.arch.riscv.rv32i import env -from amoco.arch.core import * +from amoco.arch.core import ispec +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_cpu_state, + type_system, +) + +# ruff: noqa: F811 # ------------------------------------------------------- # instruction RISC-V decoders @@ -139,7 +147,7 @@ def riscv_csr(obj, imm, rs1, rd): r1 = env.x[rs1] dst = env.x[rd] csr = env.csr[imm] - obj.operands = [dst, r1] + obj.operands = [dst, r1, csr] obj.type = type_cpu_state diff --git a/amoco/arch/riscv/rv64i/asm.py b/amoco/arch/riscv/rv64i/asm.py index 6165135..359ccdd 100644 --- a/amoco/arch/riscv/rv64i/asm.py +++ b/amoco/arch/riscv/rv64i/asm.py @@ -4,10 +4,9 @@ # Copyright (C) 2017 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * -from ..utils import * +from .env import sp, pc, cst, tst, mem, oper +from .env import internals, zero, OP_LTU, OP_ASR, OP_GEU -from amoco.cas.utils import * # ------------------------------------------------------------------------------ # helpers and decorators : @@ -30,7 +29,7 @@ def npc(ins, fmap): def trap(ins, fmap, trapname): - fmap.internals["trap"] = trapname + internals["trap"] = trapname # i_xxx is the translation of RISC-V instruction xxx. @@ -297,42 +296,6 @@ def i_BGEU(ins, fmap): fmap[pc] = fmap(tst(oper(OP_GEU, r1, r2), pc + imm, pc + ins.length)) -@__npc -def i_SB(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src[0:8]) - - -@__npc -def i_SH(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src[0:16]) - - -@__npc -def i_SW(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src) - - -@__npc -def i_LB(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src).signextend(64) - - -i_LH = i_LW = i_LB - - -@__npc -def i_LBU(ins, fmap): - dst, src = ins.operands - fmap[dst] = fmap(src).zeroextend(64) - - -i_LHU = i_LBU - - @__npc def i_FENCE(ins, fmap): pass diff --git a/amoco/arch/riscv/rv64i/env.py b/amoco/arch/riscv/rv64i/env.py index 09ec8f8..6355629 100644 --- a/amoco/arch/riscv/rv64i/env.py +++ b/amoco/arch/riscv/rv64i/env.py @@ -5,7 +5,7 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, cst, is_reg_pc, is_reg_stack # reference documentations: # The RISC-V Instruction Set Manual, volume I, Unpriviledged ISA, version 20190608. @@ -80,4 +80,6 @@ is_reg_pc(pc) is_reg_stack(sp) -registers = x+[pc] +registers = x + [pc] + +internals = {} diff --git a/amoco/arch/riscv/rv64i/formats.py b/amoco/arch/riscv/rv64i/formats.py index bc5f0eb..eca3e89 100644 --- a/amoco/arch/riscv/rv64i/formats.py +++ b/amoco/arch/riscv/rv64i/formats.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -from .env import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from .env import x +from amoco.arch.core import Formatter +from amoco.ui.render import Token def mnemo(i): diff --git a/amoco/arch/riscv/rv64i/spec_rv64i.py b/amoco/arch/riscv/rv64i/spec_rv64i.py index 62cd48c..56ca67a 100644 --- a/amoco/arch/riscv/rv64i/spec_rv64i.py +++ b/amoco/arch/riscv/rv64i/spec_rv64i.py @@ -6,7 +6,13 @@ from amoco.arch.riscv.rv64i import env -from amoco.arch.core import * +from amoco.arch.core import ispec +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_cpu_state, + type_system, +) # ------------------------------------------------------- # instruction RISC-V decoders @@ -52,6 +58,7 @@ def riscv_ri_arithmetic1(obj, imm, rs1, rd): obj.operands = [dst, src1, imm] obj.type = type_data_processing + @ispec("32<[ ~imm(12) rs1(5) 000 rd(5) 0011011 ]", mnemonic="ADDIW") def riscv_ri_arithmetic3(obj, imm, rs1, rd): src1 = env.x[rs1] @@ -158,7 +165,7 @@ def riscv_csr(obj, imm, rs1, rd): r1 = env.x[rs1] dst = env.x[rd] csr = env.csr[imm] - obj.operands = [dst, r1] + obj.operands = [dst, r1, csr] obj.type = type_cpu_state diff --git a/amoco/arch/riscv/utils.py b/amoco/arch/riscv/utils.py index ed91b14..3f06110 100644 --- a/amoco/arch/riscv/utils.py +++ b/amoco/arch/riscv/utils.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from amoco.cas.expressions import slc def hi(r): diff --git a/amoco/arch/sparc/asm.py b/amoco/arch/sparc/asm.py index a169f5e..517296e 100644 --- a/amoco/arch/sparc/asm.py +++ b/amoco/arch/sparc/asm.py @@ -4,10 +4,12 @@ # Copyright (C) 2013 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * -from .utils import * +from .env import sp, pc, npc, g0, r, nf, zf, vf, cf, y, cwp, wim +from .env import NWINDOWS +from .env import internals, mem, cst, comp, tst, top, bit0, bit1 +from .utils import CONDB -from amoco.cas.utils import * +from amoco.cas.utils import AddWithCarry, SubWithBorrow def __mem(a, sz): @@ -36,7 +38,7 @@ def pcnpc(ins, fmap): def trap(ins, fmap, trapname): - fmap.internals["trap"] = trapname + internals["trap"] = trapname # i_xxx is the translation of SPARC V8 instruction xxx. @@ -191,7 +193,7 @@ def i_stda(ins, fmap): def i_ldstub(ins, fmap): - i_ldub(ins, fmap) #i_ldub advances the pc/npc + i_ldub(ins, fmap) # i_ldub advances the pc/npc src = ins.operands[0] fmap[__mem(src, 8)] = cst(0xFF, 8) @@ -435,7 +437,7 @@ def i_mulscc(ins, fmap): if fmap(y[0:1]) == 0: op2 = cst(0, 32) else: - op2 = fmap(src2) + op2 = multiplier _r, carry, overflow = AddWithCarry(_rs1, op2) # update icc: fmap[nf] = _r[31:32] @@ -454,16 +456,16 @@ def i_mulscc(ins, fmap): def i_umul(ins, fmap): src1, src2, dst = ins.operands src1.sf = src2.sf = False - _r = fmap(src1 ** src2) # pow is used for long mul (_r is 64 bits here) + _r = fmap(src1**src2) # pow is used for long mul (_r is 64 bits here) fmap[y] = _r[32:64] if dst is not g0: fmap[dst] = _r[0:32] if ins.misc["icc"]: fmap[nf] = _r[31:32] fmap[zf] = _r == 0 - fmap[ - vf - ] = bit0 # umul does not set overflow (compilers are supposed to check Y!=0 if needed) + fmap[vf] = ( + bit0 # umul does not set overflow (compilers are supposed to check Y!=0 if needed) + ) fmap[cf] = bit0 @@ -471,16 +473,16 @@ def i_umul(ins, fmap): def i_smul(ins, fmap): src1, src2, dst = ins.operands src1.sf = src2.sf = True - _r = fmap(src1 ** src2) # pow is used for long mul (_r is 64 bits here) + _r = fmap(src1**src2) # pow is used for long mul (_r is 64 bits here) fmap[y] = _r[32:64] if dst is not g0: fmap[dst] = _r[0:32] if ins.misc["icc"]: fmap[nf] = _r[31:32] fmap[zf] = _r == 0 - fmap[ - vf - ] = bit0 # smul does not set overflow (compilers are supposed to check Y!=(_r>>31) if needed) + fmap[vf] = ( + bit0 # smul does not set overflow (compilers are supposed to check Y!=(_r>>31) if needed) + ) fmap[cf] = bit0 diff --git a/amoco/arch/sparc/cpu_v8.py b/amoco/arch/sparc/cpu_v8.py index a8a5dc7..0fdaf0d 100644 --- a/amoco/arch/sparc/cpu_v8.py +++ b/amoco/arch/sparc/cpu_v8.py @@ -1,17 +1,13 @@ # -*- coding: utf-8 -*- -from amoco.arch.sparc.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.sparc import env +from amoco.arch.sparc import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_sparc = type("instruction_sparc", (instruction,), {}) -instruction_sparc.set_uarch(uarch) -from amoco.arch.sparc.formats import SPARC_V8_full from amoco.arch.sparc.formats import SPARC_V8_synthetic instruction_sparc.set_formatter(SPARC_V8_synthetic) @@ -19,12 +15,11 @@ # define disassembler: from amoco.arch.sparc import spec_v8 -disassemble = disassembler([spec_v8], endian=lambda: -1, iclass=instruction_sparc) +def endian(): + return -1 -def PC(state=None): - return pc +disassemble = disassembler([spec_v8], endian=endian, iclass=instruction_sparc) -def get_data_endian(): - return -1 +cpu = CPU(env, asm, disassemble, env.pc, data_endian=-1) diff --git a/amoco/arch/sparc/env.py b/amoco/arch/sparc/env.py index 636e158..337a0d2 100644 --- a/amoco/arch/sparc/env.py +++ b/amoco/arch/sparc/env.py @@ -5,7 +5,9 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc +from amoco.cas.expressions import is_reg_pc, is_reg_stack +from amoco.cas.expressions import * # noqa: F403 # reference documentation: # The SPARC Architecture Manual Version 8, Revision SAV080SI9308. @@ -92,8 +94,12 @@ def hi(r): def lo(r): return slc(r, 0, 10) + registers = r + [psr, y, pc, npc] +is_reg_pc(pc) +is_reg_stack(sp) + # psr symbols: impl = slc(psr, 28, 4) # implementation ver = slc(psr, 24, 4) # version @@ -124,3 +130,5 @@ def lo(r): fcc = slc(fsr, 10, 2) # condition codes (=,<,>,?) aexc = slc(fsr, 5, 5) # IEEE 754 fp exceptions accumulator cexc = slc(fsr, 0, 5) # current IEEE 754 exception + +internals = {} diff --git a/amoco/arch/sparc/formats.py b/amoco/arch/sparc/formats.py index 1c38880..5c7f9a3 100644 --- a/amoco/arch/sparc/formats.py +++ b/amoco/arch/sparc/formats.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- -from .env import * -from .utils import * +from .env import pc, cst, g0, i7, o7 from amoco.arch.core import Formatter -from amoco.ui.render import highlight, Token +from amoco.ui.render import Token from amoco.ui.render import TokenListJoin, LambdaTokenListJoin from amoco.ui.render import replace_mnemonic_token, replace_opn_token +from amoco.ui.views import View def regs(i): @@ -25,7 +25,7 @@ def address(a): l = reg_or_imm(a.l)[0][1] op = a.op.symbol r = reg_or_imm(a.r)[0][1] - return [(Token.Address, "%s%s%s"%(l, op, r))] + return [(Token.Address, "%s%s%s" % (l, op, r))] def deref(a): @@ -34,13 +34,15 @@ def deref(a): seg = "" else: seg = a.seg - res = "[%s]%s"%(address(a.base+a.disp)[0][1],seg) + res = "[%s]%s" % (address(a.base + a.disp)[0][1], seg) return [(Token.Memory, res)] + def mnemo(i): "returns a list of a single Mnemonic token" return [(Token.Mnemonic, "{i.mnemonic:<8}".format(i=i))] + def mnemo_icc(i): "returns a list of a single Mnemonic token with condition code" s = i.mnemonic @@ -74,9 +76,9 @@ def reg_or_imm(x, t="%d"): hilo = ["%lo", x.x] # Other cases elif x._is_ext: - return [(Token.Address, "%s"%x.ref)] + return [(Token.Address, "%s" % x.ref)] elif x._is_reg: - return [(Token.Register, "%"+x.ref)] + return [(Token.Register, "%" + x.ref)] elif x._is_cst: return [(Token.Constant, t % x.value)] elif x._is_eqn: @@ -91,7 +93,7 @@ def reg_or_imm(x, t="%d"): if hilo is None: return [(Token.Register, str(x))] else: - res = "%s(%s)"%(hilo[0],address(hilo[1])[0][1]) + res = "%s(%s)" % (hilo[0], address(hilo[1])[0][1]) return [(Token.Address, res)] @@ -103,10 +105,10 @@ def label(i): if i.operands[0]._is_ext: return [(Token.Address, str(i.operands[0].ref))] if i.operands[0]._is_reg: - return [(Token.Register, "%%%s"%(i.operands[0].ref))] + return [(Token.Register, "%%%s" % (i.operands[0].ref))] if i.operands[0]._is_cst: offset = i.operands[0].signextend(32) * 4 - target = i.misc["dst"] or (_pc+offset) + target = i.misc["dst"] or (_pc + offset) return [(Token.Address, str(target))] raise TypeError("operand type not supported") @@ -130,51 +132,52 @@ def label(i): ), ] format_xb = [mnemo_cond, label] -format_call = [mnemo, lambda i: TokenListJoin(", ", label(i) + - [(Token.Constant, "0")])] +format_call = [mnemo, lambda i: TokenListJoin(", ", label(i) + [(Token.Constant, "0")])] format_jmpl = [ mnemo, lambda i: TokenListJoin(", ", address(i.operands[0]) + regn(i, 1)), ] format_addr = [mnemo, lambda i: address(i.operands[0])] -format_t = [lambda i: [(Token.Mnemonic, "{:<8}".format(CONDT[i.cond]))] + - reg_or_imm(i.operands[0])] +format_t = [ + lambda i: [(Token.Mnemonic, "{:<8}".format(CONDT[i.cond]))] + + reg_or_imm(i.operands[0]) +] format_wr = [ mnemo, - lambda i: TokenListJoin(", ",regn(i, 0) + - reg_or_imm(i.operands[1], "%#x") + - regn(i, 2)), + lambda i: TokenListJoin( + ", ", regn(i, 0) + reg_or_imm(i.operands[1], "%#x") + regn(i, 2) + ), ] format_cpop = [ mnemo, lambda i: [(Token.Constant, "{i.operands[0]:d}")] - + TokenListJoin(", ", regs(i)[1:]), + + TokenListJoin(", ", regs(i)[1:]), ] SPARC_V8_full_formats = { - "sparc_ld_" : format_ld, - "sparc_ldf_ldc" : format_ld, - "sparc_st_" : format_st, - "sparc_stf_stc" : format_st, - "sparc_logic_" : format_logic, - "sethi" : format_sethi, - "nop" : [mnemo], - "sparc_arith_" : format_arith, - "sparc_shift_" : format_arith, - "sparc_tagged_" : format_arith, - "sparc_Bicc" : format_xb, - "call" : format_call, - "jmpl" : format_jmpl, - "rett" : format_addr, - "t" : format_t, - "sparc_rd_" : [mnemo, LambdaTokenListJoin(", ", regs)], - "sparc_wr_" : format_wr, - "stbar" : [mnemo], - "flush" : format_addr, - "sparc_Fpop1_group1" : [mnemo, LambdaTokenListJoin(", ", regs)], - "sparc_Fpop1_group2" : [mnemo, LambdaTokenListJoin(", ", regs)], - "sparc_Fpop2_" : [mnemo, LambdaTokenListJoin(", ", regs)], - "sparc_Cpop" : format_cpop, + "sparc_ld_": format_ld, + "sparc_ldf_ldc": format_ld, + "sparc_st_": format_st, + "sparc_stf_stc": format_st, + "sparc_logic_": format_logic, + "sethi": format_sethi, + "nop": [mnemo], + "sparc_arith_": format_arith, + "sparc_shift_": format_arith, + "sparc_tagged_": format_arith, + "sparc_Bicc": format_xb, + "call": format_call, + "jmpl": format_jmpl, + "rett": format_addr, + "t": format_t, + "sparc_rd_": [mnemo, LambdaTokenListJoin(", ", regs)], + "sparc_wr_": format_wr, + "stbar": [mnemo], + "flush": format_addr, + "sparc_Fpop1_group1": [mnemo, LambdaTokenListJoin(", ", regs)], + "sparc_Fpop1_group2": [mnemo, LambdaTokenListJoin(", ", regs)], + "sparc_Fpop2_": [mnemo, LambdaTokenListJoin(", ", regs)], + "sparc_Cpop": format_cpop, } SPARC_V8_full = Formatter(SPARC_V8_full_formats) @@ -268,45 +271,45 @@ def SPARC_Synthetic_renaming(s, i, toks=False): and not i.misc["icc"] and i.operands[0] == i.operands[1] == g0 ): - replace_mnemonic_token(s,"clr") - replace_opn_token(s,1,None) - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "clr") + replace_opn_token(s, 1, None) + replace_opn_token(s, 0, None) elif i.mnemonic == "or" and not i.misc["icc"] and i.operands[0] == g0: - replace_mnemonic_token(s,"mov") - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "mov") + replace_opn_token(s, 0, None) elif i.mnemonic == "or" and not i.misc["icc"] and i.operands[0] == i.operands[2]: - replace_mnemonic_token(s,"bset") - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "bset") + replace_opn_token(s, 0, None) elif i.mnemonic == "rd": op1 = str(i.operands[0]) if op1.startswith("asr") or op1 in ("y", "psr", "wim", "tbr"): - replace_mnemonic_token(s,"mov") + replace_mnemonic_token(s, "mov") elif i.mnemonic == "wr" and i.operands[0] == g0: - replace_mnemonic_token(s,"mov") - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "mov") + replace_opn_token(s, 0, None) elif i.mnemonic == "sub" and i.misc["icc"] and i.operands[2] == g0: - replace_mnemonic_token(s,"cmp") - replace_opn_token(s,2,None) + replace_mnemonic_token(s, "cmp") + replace_opn_token(s, 2, None) elif i.mnemonic == "jmpl" and i.operands[1] == g0: if i.operands[0] == (i7 + cst(8)): s = [(Token.Mnemonic, "ret")] elif i.operands[0] == (o7 + cst(8)): s = [(Token.Mnemonic, "retl")] else: - replace_mnemonic_token(s,"jmp") - replace_opn_token(s,1,None) + replace_mnemonic_token(s, "jmp") + replace_opn_token(s, 1, None) elif i.mnemonic == "jmpl" and i.operands[1] == o7: - replace_mnemonic_token(s,"call") - replace_opn_token(s,1,None) + replace_mnemonic_token(s, "call") + replace_opn_token(s, 1, None) elif ( i.mnemonic == "or" and i.misc["icc"] and i.operands[1]._is_reg and i.operands[0] == i.operands[2] == g0 ): - replace_mnemonic_token(s,"tst") - replace_opn_token(s,2,None) - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "tst") + replace_opn_token(s, 2, None) + replace_opn_token(s, 0, None) elif ( i.mnemonic == "restore" and i.operands[0] == i.operands[1] == i.operands[2] == g0 @@ -315,48 +318,52 @@ def SPARC_Synthetic_renaming(s, i, toks=False): if i.mnemonic == "save" and i.operands[0] == i.operands[1] == i.operands[2] == g0: s = [(Token.Mnemonic, "save")] if i.mnemonic == "xnor" and i.operands[1] == g0: - replace_mnemonic_token(s,"not") - replace_opn_token(s,1,None) + replace_mnemonic_token(s, "not") + replace_opn_token(s, 1, None) if i.operands[0] == i.operands[2]: - replace_opn_token(s,2,None) + replace_opn_token(s, 2, None) elif i.mnemonic == "sub" and i.operands[0] == g0 and i.operands[1]._is_reg: - replace_mnemonic_token(s,"neg") - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "neg") + replace_opn_token(s, 0, None) if i.operands[1] == i.operands[2]: - replace_opn_token(s,2,None) - elif i.mnemonic == "add" and i.operands[0] == i.operands[2] and i.operands[1]._is_cst: + replace_opn_token(s, 2, None) + elif ( + i.mnemonic == "add" and i.operands[0] == i.operands[2] and i.operands[1]._is_cst + ): m = "inccc" if i.misc["icc"] else "inc" - replace_mnemonic_token(s,m) + replace_mnemonic_token(s, m) if i.operands[1] == 1: - replace_opn_token(s,2,None) - replace_opn_token(s,1,None) + replace_opn_token(s, 2, None) + replace_opn_token(s, 1, None) else: - replace_opn_token(s,0,None) - elif i.mnemonic == "sub" and i.operands[0] == i.operands[2] and i.operands[1]._is_cst: + replace_opn_token(s, 0, None) + elif ( + i.mnemonic == "sub" and i.operands[0] == i.operands[2] and i.operands[1]._is_cst + ): m = "deccc" if i.misc["icc"] else "dec" - replace_mnemonic_token(s,m) + replace_mnemonic_token(s, m) if i.operands[1] == 1: - replace_opn_token(s,2,None) - replace_opn_token(s,1,None) + replace_opn_token(s, 2, None) + replace_opn_token(s, 1, None) else: - replace_opn_token(s,0,None) + replace_opn_token(s, 0, None) elif i.mnemonic == "and" and i.misc["icc"] and i.operands[2] == g0: - replace_mnemonic_token(s,"btst") - replace_opn_token(s,2,None) - s[1],s[3] = s[3],s[1] + replace_mnemonic_token(s, "btst") + replace_opn_token(s, 2, None) + s[1], s[3] = s[3], s[1] elif i.mnemonic == "andn" and not i.misc["icc"] and i.operands[0] == i.operands[2]: - replace_mnemonic_token(s,"bclr") - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "bclr") + replace_opn_token(s, 0, None) elif i.mnemonic == "xor" and not i.misc["icc"] and i.operands[0] == i.operands[2]: - replace_mnemonic_token(s,"btog") - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "btog") + replace_opn_token(s, 0, None) elif i.mnemonic == "stb" and i.operands[0] == g0: - replace_mnemonic_token(s,"clrb") - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "clrb") + replace_opn_token(s, 0, None) elif i.mnemonic == "sth" and i.operands[0] == g0: - replace_mnemonic_token(s,"clrh") - replace_opn_token(s,0,None) + replace_mnemonic_token(s, "clrh") + replace_opn_token(s, 0, None) elif i.mnemonic == "st" and i.operands[0] == g0: - replace_mnemonic_token(s,"clr") - replace_opn_token(s,0,None) - return s if toks else highlight(s) + replace_mnemonic_token(s, "clr") + replace_opn_token(s, 0, None) + return s if toks else View.engine.highlight(s) diff --git a/amoco/arch/sparc/parsers.py b/amoco/arch/sparc/parsers.py index 602720a..6fe562c 100644 --- a/amoco/arch/sparc/parsers.py +++ b/amoco/arch/sparc/parsers.py @@ -16,10 +16,10 @@ from amoco.arch.sparc.cpu_v8 import instruction_sparc as instruction from amoco.arch.sparc import env + # ------------------------------------------------------------------------------ # parser for sparc assembler syntax. class sparc_syntax: - divide = False noprefix = False @@ -67,16 +67,19 @@ class sparc_syntax: instr = mnemo + pp.Optional(opds) + pp.Optional(comment) + @staticmethod def action_reg(toks): rname = toks[0] if rname.ref.startswith("asr"): return env.reg(rname.ref) return env.__dict__[rname.ref] + @staticmethod def action_hilo(toks): v = toks[1] return env.hi(v) if toks[0] == "%hi" else env.lo(v).zeroextend(32) + @staticmethod def action_exp(toks): tok = toks[0] if isinstance(tok, env.exp): @@ -85,20 +88,21 @@ def action_exp(toks): op = tok[0] r = tok[1] if isinstance(r, list): - r = action_exp(r) + r = sparc_syntax.action_exp(r) return env.oper(op, r) elif len(tok) == 3: op = tok[1] l = tok[0] r = tok[2] if isinstance(l, list): - l = action_exp(l) + l = sparc_syntax.action_exp(l) if isinstance(r, list): - r = action_exp(r) + r = sparc_syntax.action_exp(r) return env.oper(op, l, r) else: return tok + @staticmethod def action_instr(toks): i = instruction(b"") i.mnemonic = toks[0] @@ -112,90 +116,94 @@ def action_instr(toks): exp.setParseAction(action_exp) instr.setParseAction(action_instr) + from amoco.cas.expressions import cst, op from amoco.arch.sparc.spec_v8 import ISPECS from amoco.arch.sparc.formats import CONDB, CONDT -spec_table = dict([(spec.iattr['mnemonic'], spec) for spec in ISPECS ]) -b_synonyms = {'b':'ba','bgeu':'bcc','blu':'bcs','bz':'be','bnz':'bne'} -t_synonyms = {'t':'ta','tgeu':'tcc','tlu':'tcs','tz':'te','tnz':'tne'} -b_cond = dict([(mn,cond) for cond,mn in CONDB.items()]) -t_cond = dict([(mn,cond) for cond,mn in CONDT.items()]) + +spec_table = dict([(spec.iattr["mnemonic"], spec) for spec in ISPECS]) +b_synonyms = {"b": "ba", "bgeu": "bcc", "blu": "bcs", "bz": "be", "bnz": "bne"} +t_synonyms = {"t": "ta", "tgeu": "tcc", "tlu": "tcs", "tz": "te", "tnz": "tne"} +b_cond = dict([(mn, cond) for cond, mn in CONDB.items()]) +t_cond = dict([(mn, cond) for cond, mn in CONDT.items()]) + + def asmhelper(i): for idx, a in enumerate(i.operands): if a._is_mem: i.operands[idx] = a.a # Add implicit arguments - if i.mnemonic in ['inc','dec'] and len(i.operands) == 1: - i.operands.insert(0,cst(1)) + if i.mnemonic in ["inc", "dec"] and len(i.operands) == 1: + i.operands.insert(0, cst(1)) # Expand reduced forms - if i.mnemonic=='bset': - i.mnemonic = 'or' - i.operands.insert(0,i.operands[1]) - elif i.mnemonic=='mov': - i.mnemonic = 'or' - i.operands.insert(0,env.g0) - elif i.mnemonic=='retl': - i.mnemonic = 'jmpl' - i.operands.insert(0,op('+',env.o7,cst(8))) - i.operands.insert(1,env.g0) - elif i.mnemonic=='jmp': - i.mnemonic = 'jmpl' - i.operands.insert(1,env.g0) - elif i.mnemonic=='clr' and i.operands[0]._is_reg: - i.mnemonic = 'or' - i.operands.insert(0,env.g0) - i.operands.insert(0,env.g0) - elif i.mnemonic=='clr': - i.mnemonic = 'st' - i.operands.insert(0,env.g0) - elif i.mnemonic=='inc': - i.mnemonic = 'add' - i.operands.insert(0,i.operands[1]) - elif i.mnemonic=='dec': - i.mnemonic = 'sub' - i.operands.insert(0,i.operands[1]) - elif i.mnemonic=='cmp': - i.mnemonic = 'subcc' - i.operands.insert(2,env.g0) - elif i.mnemonic=='btst': - i.mnemonic = 'andcc' - i.operands.insert(2,env.g0) - i.operands[0:2] = [ i.operands[1], i.operands[0] ] - elif i.mnemonic=='nop': - i.mnemonic = 'sethi' - i.operands = [ cst(0,22), env.g0 ] - elif i.mnemonic=='restore' and len(i.operands) == 0: - i.operands = [ env.g0, env.g0, env.g0 ] + if i.mnemonic == "bset": + i.mnemonic = "or" + i.operands.insert(0, i.operands[1]) + elif i.mnemonic == "mov": + i.mnemonic = "or" + i.operands.insert(0, env.g0) + elif i.mnemonic == "retl": + i.mnemonic = "jmpl" + i.operands.insert(0, op("+", env.o7, cst(8))) + i.operands.insert(1, env.g0) + elif i.mnemonic == "jmp": + i.mnemonic = "jmpl" + i.operands.insert(1, env.g0) + elif i.mnemonic == "clr" and i.operands[0]._is_reg: + i.mnemonic = "or" + i.operands.insert(0, env.g0) + i.operands.insert(0, env.g0) + elif i.mnemonic == "clr": + i.mnemonic = "st" + i.operands.insert(0, env.g0) + elif i.mnemonic == "inc": + i.mnemonic = "add" + i.operands.insert(0, i.operands[1]) + elif i.mnemonic == "dec": + i.mnemonic = "sub" + i.operands.insert(0, i.operands[1]) + elif i.mnemonic == "cmp": + i.mnemonic = "subcc" + i.operands.insert(2, env.g0) + elif i.mnemonic == "btst": + i.mnemonic = "andcc" + i.operands.insert(2, env.g0) + i.operands[0:2] = [i.operands[1], i.operands[0]] + elif i.mnemonic == "nop": + i.mnemonic = "sethi" + i.operands = [cst(0, 22), env.g0] + elif i.mnemonic == "restore" and len(i.operands) == 0: + i.operands = [env.g0, env.g0, env.g0] # Branches and cc - if i.mnemonic.endswith('cc') and not i.mnemonic in ['taddcc' , 'tsubcc', 'mulscc']: + if i.mnemonic.endswith("cc") and i.mnemonic not in ["taddcc", "tsubcc", "mulscc"]: i.mnemonic = i.mnemonic[:-2] - i.misc['icc'] = True - if i.mnemonic.endswith(',a'): - i.misc['annul'] = True - i.mnemonic = i.mnemonic.rstrip(',a') + i.misc["icc"] = True + if i.mnemonic.endswith(",a"): + i.misc["annul"] = True + i.mnemonic = i.mnemonic.rstrip(",a") if i.mnemonic in b_synonyms: i.mnemonic = b_synonyms[i.mnemonic] if i.mnemonic in b_cond: i.cond = b_cond[i.mnemonic] - i.mnemonic = 'b' + i.mnemonic = "b" if i.mnemonic in t_synonyms: i.mnemonic = t_synonyms[i.mnemonic] if i.mnemonic in t_cond: i.cond = t_cond[i.mnemonic] - i.mnemonic = 't' - if i.mnemonic=='call': - if len(i.operands)>1 and i.operands[1] != cst(0): - raise ValueError('call has a non-zero second argument') - i.operands = [ i.operands[0] ] + i.mnemonic = "t" + if i.mnemonic == "call": + if len(i.operands) > 1 and i.operands[1] != cst(0): + raise ValueError("call has a non-zero second argument") + i.operands = [i.operands[0]] # Additional internal tweaks - if i.mnemonic=='sethi' and i.operands[0]._is_cst: + if i.mnemonic == "sethi" and i.operands[0]._is_cst: i.operands[0].size = 22 - elif i.mnemonic=='std': + elif i.mnemonic == "std": i.rd = env.r.index(i.operands[0]) - elif i.mnemonic=='ldd': + elif i.mnemonic == "ldd": i.rd = env.r.index(i.operands[1]) i.spec = spec_table[i.mnemonic] - i.bytes = (0,0,0,0) # To have i.length == 4, for pc_npc emulation + i.bytes = (0, 0, 0, 0) # To have i.length == 4, for pc_npc emulation return i @@ -206,7 +214,7 @@ def asmhelper(i): def test_parser(cls): while 1: try: - res = raw_input("%s>" % cls.__name__) + res = input("%s>" % cls.__name__) E = cls.instr.parseString(res, True) print(E) except pp.ParseException: diff --git a/amoco/arch/sparc/spec_v8.py b/amoco/arch/sparc/spec_v8.py index fe63b75..7353943 100644 --- a/amoco/arch/sparc/spec_v8.py +++ b/amoco/arch/sparc/spec_v8.py @@ -12,7 +12,17 @@ from amoco.arch.sparc import env -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_other, + type_cpu_state, + type_undefined, + type_other, +) + +# ruff: noqa: F811 # ------------------------------------------------------- # instruction sparcs decoders @@ -23,23 +33,72 @@ # format 3 # --------- + # ld instructions: -@ispec("32[ 11 rd(5) 0 0=a 1001 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldsb") -@ispec("32[ 11 rd(5) 0 0=a 1010 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldsh",) -@ispec("32[ 11 rd(5) 0 0=a 0001 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldub",) -@ispec("32[ 11 rd(5) 0 0=a 0010 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="lduh",) -@ispec("32[ 11 rd(5) 0 0=a 0000 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="ld") -@ispec("32[ 11 rd(5) 0 0=a 0011 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldd") -@ispec("32[ 11 rd(5) 0 0=a 1101 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldstub",) -@ispec("32[ 11 rd(5) 0 0=a 1111 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="swap",) -@ispec("32[ 11 rd(5) 0 1=a 1001 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldsba") -@ispec("32[ 11 rd(5) 0 1=a 1010 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldsha",) -@ispec("32[ 11 rd(5) 0 1=a 0001 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="lduba",) -@ispec("32[ 11 rd(5) 0 1=a 0010 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="lduha",) -@ispec("32[ 11 rd(5) 0 1=a 0000 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="lda") -@ispec("32[ 11 rd(5) 0 1=a 0011 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldda") -@ispec("32[ 11 rd(5) 0 1=a 1101 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="ldstuba",) -@ispec("32[ 11 rd(5) 0 1=a 1111 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="swapa",) +@ispec( + "32[ 11 rd(5) 0 0=a 1001 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldsb", +) +@ispec( + "32[ 11 rd(5) 0 0=a 1010 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldsh", +) +@ispec( + "32[ 11 rd(5) 0 0=a 0001 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldub", +) +@ispec( + "32[ 11 rd(5) 0 0=a 0010 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="lduh", +) +@ispec( + "32[ 11 rd(5) 0 0=a 0000 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ld", +) +@ispec( + "32[ 11 rd(5) 0 0=a 0011 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldd", +) +@ispec( + "32[ 11 rd(5) 0 0=a 1101 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldstub", +) +@ispec( + "32[ 11 rd(5) 0 0=a 1111 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="swap", +) +@ispec( + "32[ 11 rd(5) 0 1=a 1001 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldsba", +) +@ispec( + "32[ 11 rd(5) 0 1=a 1010 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldsha", +) +@ispec( + "32[ 11 rd(5) 0 1=a 0001 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="lduba", +) +@ispec( + "32[ 11 rd(5) 0 1=a 0010 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="lduha", +) +@ispec( + "32[ 11 rd(5) 0 1=a 0000 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="lda", +) +@ispec( + "32[ 11 rd(5) 0 1=a 0011 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldda", +) +@ispec( + "32[ 11 rd(5) 0 1=a 1101 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="ldstuba", +) +@ispec( + "32[ 11 rd(5) 0 1=a 1111 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="swapa", +) def sparc_ld_(obj, rd, a, op3, rs1, i, asi, rs2, simm13): adr = env.r[rs1] if i == 0: @@ -83,14 +142,38 @@ def sparc_ldf_ldc(obj, rd, a, op3, rs1, i, unused, rs2, simm13): # st instructions: -@ispec("32[ 11 rd(5) 0 0=a 0101 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="stb") -@ispec("32[ 11 rd(5) 0 0=a 0110 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="sth") -@ispec("32[ 11 rd(5) 0 0=a 0100 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="st") -@ispec("32[ 11 rd(5) 0 0=a 0111 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", mnemonic="std") -@ispec("32[ 11 rd(5) 0 1=a 0101 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="stba") -@ispec("32[ 11 rd(5) 0 1=a 0110 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="stha") -@ispec("32[ 11 rd(5) 0 1=a 0100 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="sta") -@ispec("32[ 11 rd(5) 0 1=a 0111 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", mnemonic="stda") +@ispec( + "32[ 11 rd(5) 0 0=a 0101 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="stb", +) +@ispec( + "32[ 11 rd(5) 0 0=a 0110 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="sth", +) +@ispec( + "32[ 11 rd(5) 0 0=a 0100 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="st", +) +@ispec( + "32[ 11 rd(5) 0 0=a 0111 =op3(6) rs1(5) i asi(8) rs2(5) =simm13(13) ]", + mnemonic="std", +) +@ispec( + "32[ 11 rd(5) 0 1=a 0101 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="stba", +) +@ispec( + "32[ 11 rd(5) 0 1=a 0110 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="stha", +) +@ispec( + "32[ 11 rd(5) 0 1=a 0100 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="sta", +) +@ispec( + "32[ 11 rd(5) 0 1=a 0111 =op3(6) rs1(5) 0=i asi(8) rs2(5) =simm13(13) ]", + mnemonic="stda", +) def sparc_st_(obj, rd, a, op3, rs1, i, asi, rs2, simm13): adr = env.r[rs1] if i == 0: @@ -244,13 +327,13 @@ def sparc_rd_(obj, rd, rs1, _src): obj.operands = [_src, dst] obj.type = type_other + @ispec("32[ 10 00000 101000 01111 - ------------- ]", mnemonic="stbar") def sparc_rd_(obj, _src): - _src == env.y - dst = env.r[rd] - obj.operands = [_src, dst] + obj.operands = [] obj.type = type_other + @ispec( "32[ 10 rd(5) 101000 rs1(5) i -------- rs2(5) =simm13(13) ]", mnemonic="wr", @@ -300,6 +383,7 @@ def sparc_sethi(obj, rd, imm22): obj.operands = [src, dst] obj.type = type_data_processing + @ispec("32[ 00 00000 100 0000000000000000000000 ]", mnemonic="nop") def sparc_nop(obj): obj.type = type_data_processing diff --git a/amoco/arch/superh/cpu_sh2.py b/amoco/arch/superh/cpu_sh2.py index 2c240fc..9f9faaa 100644 --- a/amoco/arch/superh/cpu_sh2.py +++ b/amoco/arch/superh/cpu_sh2.py @@ -1,15 +1,12 @@ # -*- coding: utf-8 -*- -from amoco.arch.superh.sh2.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.superh.sh2 import env +from amoco.arch.superh.sh2 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_sh2 = type("instruction_sh2", (instruction,), {}) -instruction_sh2.set_uarch(uarch) from amoco.arch.superh.sh2.formats import SH2_full @@ -18,12 +15,11 @@ # define disassembler: from amoco.arch.superh.sh2 import spec_sh2 -disassemble = disassembler([spec_sh2], endian=lambda: -1, iclass=instruction_sh2) +def endian(): + return -1 -def PC(state=None): - return pc +disassemble = disassembler([spec_sh2], endian=endian, iclass=instruction_sh2) -def get_data_endian(): - return -1 +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/superh/cpu_sh4.py b/amoco/arch/superh/cpu_sh4.py index dac7719..86a341f 100644 --- a/amoco/arch/superh/cpu_sh4.py +++ b/amoco/arch/superh/cpu_sh4.py @@ -1,17 +1,13 @@ # -*- coding: utf-8 -*- -from amoco.arch.superh.sh4.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.superh.sh4 import env +from amoco.arch.superh.sh4 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_sh4 = type("instruction_sh4", (instruction,), {}) -instruction_sh4.set_uarch(uarch) -from amoco.arch.superh.sh4.formats import SH4_full from amoco.arch.superh.sh4.formats import SH4_synthetic instruction_sh4.set_formatter(SH4_synthetic) @@ -19,8 +15,11 @@ # define disassembler: from amoco.arch.superh.sh4 import spec_sh4 -disassemble = disassembler([spec_sh4], endian=lambda: -1, iclass=instruction_sh4) +def endian(): + return -1 + + +disassemble = disassembler([spec_sh4], endian=endian, iclass=instruction_sh4) -def PC(state=None): - return pc +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/superh/sh2/asm.py b/amoco/arch/superh/sh2/asm.py index 9d3a393..e41242a 100644 --- a/amoco/arch/superh/sh2/asm.py +++ b/amoco/arch/superh/sh2/asm.py @@ -4,10 +4,11 @@ # Copyright (C) 2018 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * -from .utils import * +from .env import sp, pc, npc, R15, R, PR, T, M, Q, MACL, MACH, CS, SR +from .env import mem, tst, cst, op, ext, composer, operator, geu, ltu +from .env import bit0, bit1, OP_ASR, ror, rol -from amoco.cas.utils import * +from amoco.cas.utils import AddWithCarry, SubWithBorrow def __mem(a, sz): @@ -78,7 +79,7 @@ def i_MOVML(ins, fmap): assert src._is_mem assert src.a.base == R15 assert dst._is_reg - for r in R[: obj.m]: + for r in R[: ins.m]: if r == sp: r = PR fmap[r] = fmap(src) @@ -88,7 +89,7 @@ def i_MOVML(ins, fmap): assert src._is_reg assert dst._is_mem assert dst.a.base == R15 - for r in R[obj.m :: -1]: + for r in R[ins.m :: -1]: if r == sp: r = PR fmap[R15] = fmap(R15) - 4 @@ -103,7 +104,7 @@ def i_MOVMU(ins, fmap): assert src._is_mem assert src.a.base == R15 assert dst._is_reg - for r in R[obj.m :]: + for r in R[ins.m :]: if r == sp: r = PR fmap[r] = fmap(src) @@ -113,7 +114,7 @@ def i_MOVMU(ins, fmap): assert src._is_reg assert dst._is_mem assert dst.a.base == R15 - for r in R[obj.m :][::-1]: + for r in R[ins.m :][::-1]: if r == sp: r = PR fmap[R15] = fmap(R15) - 4 @@ -333,8 +334,8 @@ def i_CLIPS(ins, fmap): elif ins.size == 16: ul = cst(+32767, 32) ll = cst(-32768, 32) - fmap[Rn] = fmap(tst(Rn > ul, ul, Rn)) - fmap[CS] = fmap(tst(Rn > ul, bit1, CS)) + fmap[Rn] = fmap(tst(Rn > ul, ul, ll)) + fmap[CS] = bit1 @__pc @@ -345,7 +346,7 @@ def i_CLIPU(ins, fmap): elif ins.size == 16: ul = cst(0xFFFF, 32) fmap[Rn] = fmap(tst(Rn > ul, ul, Rn)) - fmap[CS] = fmap(tst(Rn > ul, bit1, CS)) + fmap[CS] = bit1 @__pc @@ -421,7 +422,7 @@ def i_DMULS(ins, fmap): Rm, Rn = ins.operands r1 = fmap(Rm).signed() r2 = fmap(Rn).signed() - x = fmap(r1 ** r2) + x = fmap(r1**r2) fmap[MACL] = x[0:32] fmap[MACH] = x[32:64] @@ -431,7 +432,7 @@ def i_DMULU(ins, fmap): Rm, Rn = ins.operands r1 = fmap(Rm).unsigned() r2 = fmap(Rn).unsigned() - x = fmap(r1 ** r2) + x = fmap(r1**r2) fmap[MACL] = x[0:32] fmap[MACH] = x[32:64] @@ -458,7 +459,7 @@ def i_EXTU(ins, fmap): @__pc def i_MAC(ins, fmap): m, n = ins.operands - res = fmap(m ** n) + fmap(composer([MACL, MACH])) + res = fmap(m**n) + fmap(composer([MACL, MACH])) fmap[MACL] = res[0:32] fmap[MACH] = res[0:32] postincr(ins, fmap) @@ -623,8 +624,8 @@ def i_SLEEP(ins, fmap): @__pc def i_TRAPA(ins, fmap): - _push_(fmap,fmap(pc)) - _push_(fmap,fmap(SR)) + _push_(fmap, fmap(pc)) + _push_(fmap, fmap(SR)) fmap[pc] = ext(ins.operands[0]) @@ -661,6 +662,7 @@ def i_BT(ins, fmap): dst = pc fmap[dst] = fmap(tst(T == bit1, npc + disp, dst)) + @__pc def i_BRA(ins, fmap): disp = ins.operands[0] diff --git a/amoco/arch/superh/sh2/env.py b/amoco/arch/superh/sh2/env.py index 31bd7a7..6f4564a 100644 --- a/amoco/arch/superh/sh2/env.py +++ b/amoco/arch/superh/sh2/env.py @@ -5,7 +5,9 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc +from amoco.cas.expressions import is_reg_pc, is_reg_flags, is_reg_stack +from amoco.cas.expressions import * # noqa: F403 # reference documentation: # The SH-2A, SH-2A-FPU Software Manual, rev. 3.00, July 8 2005. @@ -83,4 +85,6 @@ BE0 = slc(IBNR, 14, 1, "BE0") BE1 = slc(IBNR, 15, 1, "BE1") -registers = R+[SR,pc,npc] +registers = R + [SR, pc, npc] + +internals = {} diff --git a/amoco/arch/superh/sh2/formats.py b/amoco/arch/superh/sh2/formats.py index ea2dc00..351a5c5 100644 --- a/amoco/arch/superh/sh2/formats.py +++ b/amoco/arch/superh/sh2/formats.py @@ -1,9 +1,7 @@ # -*- coding: utf-8 -*- -from .env import * -from .utils import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from amoco.arch.core import Formatter +from amoco.ui.render import Token def mnemo(i): diff --git a/amoco/arch/superh/sh2/spec_sh2.py b/amoco/arch/superh/sh2/spec_sh2.py index 52b827a..f5c0f45 100644 --- a/amoco/arch/superh/sh2/spec_sh2.py +++ b/amoco/arch/superh/sh2/spec_sh2.py @@ -11,7 +11,15 @@ from amoco.arch.superh.sh2 import env -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_other, +) + +# ruff: noqa: F811 + # ------------------------------------------------------- # sh-2 decoders @@ -423,7 +431,6 @@ def sh2_branch(obj, d): @ispec("16<[ 1010 d(12) ]", mnemonic="BRA") @ispec("16<[ 1011 d(12) ]", mnemonic="BSR") def sh2_branch(obj, d): - R0 = env.R[0] offset = env.cst(d, 12).signextend(32) obj.operands = [offset * 2] obj.misc["delayed"] = True @@ -522,7 +529,6 @@ def sh2_default(obj, m, _op2): @ispec("16<[ 0100 n(4) 11100101 ]", mnemonic="STBANK") def sh2_default(obj, n): - Rn = env.R[n] obj.operands = [env.R[0], env.mem(n, 32)] obj.type = type_other diff --git a/amoco/arch/superh/sh4/env.py b/amoco/arch/superh/sh4/env.py index f3899a1..c1c49fc 100644 --- a/amoco/arch/superh/sh4/env.py +++ b/amoco/arch/superh/sh4/env.py @@ -5,7 +5,8 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc +from amoco.cas.expressions import * # noqa: F403 # reference documentation: # The SH-4 CPU Core Architecture, 12 september 2002. @@ -81,4 +82,6 @@ URB = slc(MMUCR, 18, 6, "MMUCR.URB") LRUI = slc(MMUCR, 26, 6, "MMUCR.LRUI") -registers = R + r + [SR, PC, npc, nnpc] +registers = R + r + [SR, pc, npc, nnpc] + +internals = {} diff --git a/amoco/arch/superh/sh4/spec_sh4.py b/amoco/arch/superh/sh4/spec_sh4.py index 9afeffc..eb1dc8b 100644 --- a/amoco/arch/superh/sh4/spec_sh4.py +++ b/amoco/arch/superh/sh4/spec_sh4.py @@ -9,10 +9,6 @@ # ref: The SH-4 CPU Core Architecture, 12 september 2002. -from amoco.arch.superh.sh4 import env - -from amoco.arch.core import * - # ------------------------------------------------------- # sh-4 decoders # ------------------------------------------------------- @@ -22,7 +18,7 @@ # import sh-2 instructions # ------------------------- -from amoco.arch.superh.sh2.spec_sh2 import * +from amoco.arch.superh.sh2.spec_sh2 import * # noqa: F403 # add sh3/sh4 instructions # ------------------------- diff --git a/amoco/arch/tricore/asm.py b/amoco/arch/tricore/asm.py index fdb7c99..d6cf8da 100644 --- a/amoco/arch/tricore/asm.py +++ b/amoco/arch/tricore/asm.py @@ -4,14 +4,18 @@ # Copyright (C) 2021 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * -from .utils import * +from .env import pc, ra, sp, A, V, C, D, SV, AV, SAV, FCX, PCXO, PCXI, PCXS +from .env import PIE, IE, CDE, FCXO, FCXS, PCPN, CCPN, UL, CSFR, PSW, internals +from .env import tst, cst, op, top, composer, mem, bit1, bit0, OP_ASR, OP_GEU +from .env import OP_AND, OP_OR, OP_XOR, OP_LTU, Upper_Context, Lower_Context +from .utils import reverse16, ssov, suov -from amoco.cas.utils import * +from amoco.cas.utils import AddWithCarry, SubWithBorrow # ------------------------------------------------------------------------------ # helpers and decorators : + def __npc(i_xxx): def npc(ins, fmap): fmap[pc] = fmap(pc) + ins.length @@ -27,118 +31,138 @@ def trap(ins, fmap, trapname): # i_xxx is the translation of TriCore instruction xxx. # ------------------------------------------------------------------------------ + @__npc def i_MOV(ins, fmap): dst, src = ins.operands fmap[dst] = fmap(src) + i_MOV_A = i_MOV_AA = i_MOV_D = i_MOV + @__npc def i_MOVH(ins, fmap): dst, src = ins.operands v = fmap(src).zeroextend(32) - fmap[dst] = v<<16 + fmap[dst] = v << 16 + i_MOVH_A = i_MOVH + @__npc def i_CMOV(ins, fmap): dst, cond, src = ins.operands - fmap[dst] = fmap(tst(cond!=0,src,dst)) + fmap[dst] = fmap(tst(cond != 0, src, dst)) + @__npc def i_CMOVN(ins, fmap): dst, cond, src = ins.operands - fmap[dst] = fmap(tst(cond==0,src,dst)) + fmap[dst] = fmap(tst(cond == 0, src, dst)) + @__npc def i_LEA(ins, fmap): dst = ins.operands[0] - if ins.mode=="Absolute": + if ins.mode == "Absolute": src = ins.operands[1] fmap[dst] = src else: - base,off = ins.operands[1:3] - fmap[dst] = fmap(base+(off.signextend(32))) + base, off = ins.operands[1:3] + fmap[dst] = fmap(base + (off.signextend(32))) + @__npc def i_LHA(ins, fmap): dst = ins.operands[0] - if ins.mode=="Absolute": + if ins.mode == "Absolute": src = ins.operands[1] fmap[dst] = src + @__npc def i_ABS(ins, fmap): dst, src = ins.operands v = fmap(src) - fmap[dst] = tst(v>=0,v,0-v) + fmap[dst] = tst(v >= 0, v, 0 - v) + @__npc def i_ABS_B(ins, fmap): dst, src = ins.operands v = fmap(src) - fmap[dst] = composer([tst(p>=0,p,0-p) for p in (v[0:8],v[8:16],v[16:24],v[24:32])]) + fmap[dst] = composer( + [tst(p >= 0, p, 0 - p) for p in (v[0:8], v[8:16], v[16:24], v[24:32])] + ) + @__npc def i_ABS_H(ins, fmap): dst, src = ins.operands v = fmap(src) - fmap[dst] = composer([tst(p>=0,p,0-p) for p in (v[0:16],v[16:32])]) + fmap[dst] = composer([tst(p >= 0, p, 0 - p) for p in (v[0:16], v[16:32])]) + @__npc def i_ABSS(ins, fmap): dst, src = ins.operands v = fmap(src) - fmap[dst] = ssov(tst(v>=0,v,0-v),32) + fmap[dst] = ssov(tst(v >= 0, v, 0 - v), 32) + @__npc def i_ABSS_H(ins, fmap): dst, src = ins.operands v = fmap(src) - fmap[dst] = composer([ssov(tst(p>=0,p,0-p),32) for p in (v[0:16],v[16:32])]) + fmap[dst] = composer([ssov(tst(p >= 0, p, 0 - p), 32) for p in (v[0:16], v[16:32])]) @__npc def i_ADD(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = AddWithCarry(fmap(src1),fmap(src2)) + result, carry, overflow = AddWithCarry(fmap(src1), fmap(src2)) fmap[dst] = result fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + i_ADDI = i_ADDIH = i_ADD + @__npc def i_ADD_A(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1+src2) + result = fmap(src1 + src2) fmap[dst] = result + i_ADDIH_A = i_ADD_A + @__npc def i_ADD_B(ins, fmap): dst, src1, src2 = ins.operands result = [] overflow = bit0 advanced_overflow = bit0 - for i in (0,8,16,24): - s1 = fmap(src1[i:i+8]) - s2 = fmap(src2[i:i+8]) - _r,_c,_o = AddWithCarry(s1,s2) + for i in (0, 8, 16, 24): + s1 = fmap(src1[i : i + 8]) + s2 = fmap(src2[i : i + 8]) + _r, _c, _o = AddWithCarry(s1, s2) result.append(_r) overflow |= _o - advanced_overflow |= _r[7:8]^_r[6:7] + advanced_overflow |= _r[7:8] ^ _r[6:7] fmap[dst] = composer(result) fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) + fmap[SV] = tst(overflow, bit1, fmap(SV)) fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_ADD_H(ins, fmap): @@ -146,198 +170,217 @@ def i_ADD_H(ins, fmap): result = [] overflow = bit0 advanced_overflow = bit0 - for i in (0,16): - s1 = fmap(src1[i:i+16]) - s2 = fmap(src2[i:i+16]) - _r,_c,_o = AddWithCarry(s1,s2) + for i in (0, 16): + s1 = fmap(src1[i : i + 16]) + s2 = fmap(src2[i : i + 16]) + _r, _c, _o = AddWithCarry(s1, s2) result.append(_r) overflow |= _o - advanced_overflow |= _r[15:16]^_r[14:15] + advanced_overflow |= _r[15:16] ^ _r[14:15] fmap[dst] = composer(result) fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) + fmap[SV] = tst(overflow, bit1, fmap(SV)) fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) @__npc def i_ADDC(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = AddWithCarry(fmap(src1),fmap(src2),fmap(C)) + result, carry, overflow = AddWithCarry(fmap(src1), fmap(src2), fmap(C)) fmap[dst] = result fmap[C] = carry fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_ADDS(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = AddWithCarry(fmap(src1),fmap(src2)) - fmap[dst] = ssov(result,32) + result, carry, overflow = AddWithCarry(fmap(src1), fmap(src2)) + fmap[dst] = ssov(result, 32) fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_ADDS_U(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = AddWithCarry(fmap(src1),fmap(src2)) - fmap[dst] = suov(result,32) + result, carry, overflow = AddWithCarry(fmap(src1), fmap(src2)) + fmap[dst] = suov(result, 32) fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_ADDX(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = AddWithCarry(fmap(src1),fmap(src2)) + result, carry, overflow = AddWithCarry(fmap(src1), fmap(src2)) fmap[dst] = result fmap[C] = carry fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_CADD(ins, fmap): dst, cond, src1, src2 = ins.operands - result,carry,overflow = AddWithCarry(fmap(src1),fmap(src2)) - cond = fmap(cond!=0) - fmap[dst] = tst(cond,result,fmap(dst)) - fmap[V] = tst(cond,overflow,fmap(V)) - fmap[SV] = tst(cond&overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] - fmap[AV] = tst(cond,advanced_overflow,fmap(AV)) - fmap[SAV] = tst(cond&advanced_overflow,bit1,fmap(SAV)) + result, carry, overflow = AddWithCarry(fmap(src1), fmap(src2)) + cond = fmap(cond != 0) + fmap[dst] = tst(cond, result, fmap(dst)) + fmap[V] = tst(cond, overflow, fmap(V)) + fmap[SV] = tst(cond & overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] + fmap[AV] = tst(cond, advanced_overflow, fmap(AV)) + fmap[SAV] = tst(cond & advanced_overflow, bit1, fmap(SAV)) + @__npc def i_CADDN(ins, fmap): dst, cond, src1, src2 = ins.operands - result,carry,overflow = AddWithCarry(fmap(src1),fmap(src2)) - cond = fmap(cond==0) - fmap[dst] = tst(cond,result,fmap(dst)) - fmap[V] = tst(cond,overflow,fmap(V)) - fmap[SV] = tst(cond&overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] - fmap[AV] = tst(cond,advanced_overflow,fmap(AV)) - fmap[SAV] = tst(cond&advanced_overflow,bit1,fmap(SAV)) + result, carry, overflow = AddWithCarry(fmap(src1), fmap(src2)) + cond = fmap(cond == 0) + fmap[dst] = tst(cond, result, fmap(dst)) + fmap[V] = tst(cond, overflow, fmap(V)) + fmap[SV] = tst(cond & overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] + fmap[AV] = tst(cond, advanced_overflow, fmap(AV)) + fmap[SAV] = tst(cond & advanced_overflow, bit1, fmap(SAV)) + @__npc def i_ADDSC_A(ins, fmap): dst, src1, src2, n = ins.operands - result = fmap(src1+(src2<>3))&0xfffffffc) + result = fmap((src1 + (src2 >> 3)) & 0xFFFFFFFC) fmap[dst] = result + @__npc def i_SUB(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = SubWithBorrow(fmap(src1),fmap(src2)) + result, carry, overflow = SubWithBorrow(fmap(src1), fmap(src2)) fmap[dst] = result fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + i_SUBI = i_SUBIH = i_SUB + @__npc def i_RSUB(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = SubWithBorrow(fmap(src2),fmap(src1)) + result, carry, overflow = SubWithBorrow(fmap(src2), fmap(src1)) fmap[dst] = result fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_RSUBS(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = SubWithBorrow(fmap(src2),fmap(src1)) - fmap[dst] = ssov(result,32) + result, carry, overflow = SubWithBorrow(fmap(src2), fmap(src1)) + fmap[dst] = ssov(result, 32) fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_RSUBS_U(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = SubWithBorrow(fmap(src2),fmap(src1)) - fmap[dst] = suov(result,32) + result, carry, overflow = SubWithBorrow(fmap(src2), fmap(src1)) + fmap[dst] = suov(result, 32) fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_SUB_A(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1-src2) + result = fmap(src1 - src2) fmap[dst] = result + i_SUBIH_A = i_SUB_A + @__npc def i_SUBC(ins, fmap): dst, src1, src2 = ins.operands - result,carry,overflow = SubWithBorrow(fmap(src1),fmap(src2),fmap(C)) + result, carry, overflow = SubWithBorrow(fmap(src1), fmap(src2), fmap(C)) fmap[dst] = result fmap[C] = carry fmap[V] = overflow - fmap[SV] = tst(overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] + fmap[SV] = tst(overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] fmap[AV] = advanced_overflow - fmap[SAV] = tst(advanced_overflow,bit1,fmap(SAV)) + fmap[SAV] = tst(advanced_overflow, bit1, fmap(SAV)) + @__npc def i_CSUB(ins, fmap): dst, cond, src1, src2 = ins.operands - result,carry,overflow = SubWithBorrow(fmap(src1),fmap(src2)) - cond = fmap(cond!=0) - fmap[dst] = tst(cond,result,fmap(dst)) - fmap[V] = tst(cond,overflow,fmap(V)) - fmap[SV] = tst(cond&overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] - fmap[AV] = tst(cond,advanced_overflow,fmap(AV)) - fmap[SAV] = tst(cond&advanced_overflow,bit1,fmap(SAV)) + result, carry, overflow = SubWithBorrow(fmap(src1), fmap(src2)) + cond = fmap(cond != 0) + fmap[dst] = tst(cond, result, fmap(dst)) + fmap[V] = tst(cond, overflow, fmap(V)) + fmap[SV] = tst(cond & overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] + fmap[AV] = tst(cond, advanced_overflow, fmap(AV)) + fmap[SAV] = tst(cond & advanced_overflow, bit1, fmap(SAV)) + @__npc def i_CSUBN(ins, fmap): dst, cond, src1, src2 = ins.operands - result,carry,overflow = SubWithBorrow(fmap(src1),fmap(src2)) - cond = fmap(cond==0) - fmap[dst] = tst(cond,result,fmap(dst)) - fmap[V] = tst(cond,overflow,fmap(V)) - fmap[SV] = tst(cond&overflow,bit1,fmap(SV)) - advanced_overflow = result[31:32]^result[30:31] - fmap[AV] = tst(cond,advanced_overflow,fmap(AV)) - fmap[SAV] = tst(cond&advanced_overflow,bit1,fmap(SAV)) + result, carry, overflow = SubWithBorrow(fmap(src1), fmap(src2)) + cond = fmap(cond == 0) + fmap[dst] = tst(cond, result, fmap(dst)) + fmap[V] = tst(cond, overflow, fmap(V)) + fmap[SV] = tst(cond & overflow, bit1, fmap(SV)) + advanced_overflow = result[31:32] ^ result[30:31] + fmap[AV] = tst(cond, advanced_overflow, fmap(AV)) + fmap[SAV] = tst(cond & advanced_overflow, bit1, fmap(SAV)) + @__npc def i_SH(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(tst(src2>=0,src1<>(-src2))) + result = fmap(tst(src2 >= 0, src1 << src2, src1 >> (-src2))) fmap[dst] = result + @__npc def i_SHA(ins, fmap): dst, src1, src2 = ins.operands @@ -345,21 +388,22 @@ def i_SHA(ins, fmap): count = fmap(src2) if count._is_cst: n = count.value - result = x<=0 else op(OP_ASR,x,-n) + result = x << n if n >= 0 else op(OP_ASR, x, -n) carry = bit0 - if n>0: - carry = x[32-n:32]!=0 - elif n<0: - carry = x[0:-n]!=0 + if n > 0: + carry = x[32 - n : 32] != 0 + elif n < 0: + carry = x[0:-n] != 0 else: - result = fmap(tst(src2>=0,src1<= 0, src1 << src2, op(OP_ASR, src1, -src2))) carry = top(1) fmap[dst] = result fmap[C] = carry fmap[SV] = top(1) - advanced_overflow = result[31:32]^result[30:31] - fmap[AV] = tst(cond,advanced_overflow,fmap(AV)) - fmap[SAV] = tst(cond&advanced_overflow,bit1,fmap(SAV)) + advanced_overflow = result[31:32] ^ result[30:31] + fmap[AV] = tst(src2 >= 0, advanced_overflow, fmap(AV)) + fmap[SAV] = tst((src2 >= 0) & advanced_overflow, bit1, fmap(SAV)) + @__npc def i_SHAS(ins, fmap): @@ -368,476 +412,548 @@ def i_SHAS(ins, fmap): count = fmap(src2) if count._is_cst: n = count.value - result = x<=0 else op(OP_ASR,x,-n) + result = x << n if n >= 0 else op(OP_ASR, x, -n) carry = bit0 - if n>0: - carry = x[32-n:32]!=0 - elif n<0: - carry = x[0:-n]!=0 + if n > 0: + carry = x[32 - n : 32] != 0 + elif n < 0: + carry = x[0:-n] != 0 else: - result = fmap(tst(src2>=0,src1<= 0, src1 << src2, op(OP_ASR, src1, -src2))) carry = top(1) - fmap[dst] = ssov(result,32) + fmap[dst] = ssov(result, 32) fmap[C] = carry fmap[SV] = top(1) - advanced_overflow = result[31:32]^result[30:31] - fmap[AV] = tst(cond,advanced_overflow,fmap(AV)) - fmap[SAV] = tst(cond&advanced_overflow,bit1,fmap(SAV)) + advanced_overflow = result[31:32] ^ result[30:31] + fmap[AV] = tst(src2 >= 0, advanced_overflow, fmap(AV)) + fmap[SAV] = tst((src2 >= 0) & advanced_overflow, bit1, fmap(SAV)) + @__npc def i_AND(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1&src2) + result = fmap(src1 & src2) fmap[dst] = result + @__npc def i_NAND(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(~(src1&src2)) + result = fmap(~(src1 & src2)) fmap[dst] = result + @__npc def i_ANDN(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1&(~src2)) + result = fmap(src1 & (~src2)) fmap[dst] = result + @__npc def i_OR(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1|src2) + result = fmap(src1 | src2) fmap[dst] = result + @__npc def i_NOR(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(~(src1|src2)) + result = fmap(~(src1 | src2)) fmap[dst] = result + @__npc def i_ORN(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1|(~src2)) + result = fmap(src1 | (~src2)) fmap[dst] = result + @__npc def i_XOR(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1^src2) + result = fmap(src1 ^ src2) fmap[dst] = result + @__npc def i_XNOR(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(~(src1^src2)) + result = fmap(~(src1 ^ src2)) fmap[dst] = result + @__npc def i_EQ(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1==src2) + result = fmap(src1 == src2) fmap[dst] = result.zeroextend(dst.size) + i_EQ_A = i_EQ + @__npc def i_NOT(ins, fmap): src = ins.operands[0] fmap[src] = fmap(~src) + @__npc def i_EQZ_A(ins, fmap): dst, src = ins.operands - result = fmap(src==0) + result = fmap(src == 0) fmap[dst] = result.zeroextend(dst.size) + @__npc def i_NEZ_A(ins, fmap): dst, src = ins.operands - result = fmap(src!=0) + result = fmap(src != 0) fmap[dst] = result.zeroextend(dst.size) + @__npc def i_NE(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1!=src2) + result = fmap(src1 != src2) fmap[dst] = result.zeroextend(dst.size) + @__npc def i_GE(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1>=src2) + result = fmap(src1 >= src2) fmap[dst] = result.zeroextend(dst.size) + i_GE_A = i_GE + @__npc def i_GE_U(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(op(OP_GEU,src1,src2)) + result = fmap(op(OP_GEU, src1, src2)) fmap[dst] = result.zeroextend(dst.size) + @__npc def i_LT(ins, fmap): dst, src1, src2 = ins.operands - result = fmap(src1=src2)) + fmap[dst[0:1]] = fmap(dst[0:1] & (src1 >= src2)) + @__npc def i_OR_GE(ins, fmap): dst, src1, src2 = ins.operands - fmap[dst[0:1]] = fmap(dst[0:1]|(src1>=src2)) + fmap[dst[0:1]] = fmap(dst[0:1] | (src1 >= src2)) + @__npc def i_XOR_GE(ins, fmap): dst, src1, src2 = ins.operands - fmap[dst[0:1]] = fmap(dst[0:1]^(src1>=src2)) + fmap[dst[0:1]] = fmap(dst[0:1] ^ (src1 >= src2)) + @__npc def i_AND_LT(ins, fmap): dst, src1, src2 = ins.operands - fmap[dst[0:1]] = fmap(dst[0:1]&(src1 0: s.pop() @@ -54,4 +54,3 @@ def opers_adr(i): TriCore_full = Formatter(tricore_full_formats) TriCore_full.default = format_default - diff --git a/amoco/arch/tricore/spec.py b/amoco/arch/tricore/spec.py index ba884ea..cc1e98c 100644 --- a/amoco/arch/tricore/spec.py +++ b/amoco/arch/tricore/spec.py @@ -6,7 +6,14 @@ from amoco.arch.tricore import env -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_system, +) + +# ruff: noqa: F811 # ------------------------------------------------------- # from TriCore TC1.6.2 core architecture manual V1.2.2 @@ -17,25 +24,28 @@ ISPECS = [] + @ispec("32<[ disp1(16) disp2(8) {6d} ]", mnemonic="CALL") @ispec("32<[ disp1(16) disp2(8) {61} ]", mnemonic="FCALL") @ispec("32<[ disp1(16) disp2(8) {1d} ]", mnemonic="J") @ispec("32<[ disp1(16) disp2(8) {5d} ]", mnemonic="JL") def tricore_branch(obj, disp1, disp2): - v = env.cst(((disp2<<16)+disp1)<<1,24) - obj.operands = [disp.signextend(32)] + v = env.cst(((disp2 << 16) + disp1) << 1, 24) + obj.operands = [v.signextend(32)] obj.type = type_control_flow + @ispec("32<[ disp1(16) disp2(8) {ed} ]", mnemonic="CALLA") @ispec("32<[ disp1(16) disp2(8) {e1} ]", mnemonic="FCALLA") @ispec("32<[ disp1(16) disp2(8) {9d} ]", mnemonic="JA") @ispec("32<[ disp1(16) disp2(8) {dd} ]", mnemonic="JLA") def tricore_branch(obj, disp1, disp2): - v = env.cst((disp2<<16)+disp1,24) - addr = env.composer([env.bit0,v[0:20],env.cst(0,7),v[20:24]]) + v = env.cst((disp2 << 16) + disp1, 24) + addr = env.composer([env.bit0, v[0:20], env.cst(0, 7), v[20:24]]) obj.operands = [addr] obj.type = type_control_flow + @ispec("32<[ ---- {00} ---- ---- a(4) {2d} ]", mnemonic="CALLI") @ispec("32<[ ---- {01} ---- ---- a(4) {2d} ]", mnemonic="FCALLI") @ispec("32<[ ---- {03} ---- ---- a(4) {2d} ]", mnemonic="JI") @@ -45,21 +55,24 @@ def tricore_branchI(obj, a): obj.operands = [src] obj.type = type_control_flow + @ispec("16<[ disp(8) {5c} ]", mnemonic="CALL") @ispec("16<[ disp(8) {3c} ]", mnemonic="J") @ispec("16<[ disp(8) {ee} ]", mnemonic="JNZ") @ispec("16<[ disp(8) {6e} ]", mnemonic="JZ") def tricore_branch(obj, disp): - disp = env.cst(disp<<1,8) + disp = env.cst(disp << 1, 8) obj.operands = [disp.signextend(32)] obj.type = type_control_flow + @ispec("32<[ ---- 0000000 const9(9) ---- {ad} ]", mnemonic="BISR") @ispec("32<[ ---- 0000100 const9(9) ---- {ad} ]", mnemonic="SYSCALL") def tricore_system(obj, const9): - obj.operands = [env.cst(const9,9)] + obj.operands = [env.cst(const9, 9)] obj.type = type_system + @ispec("32<[ c(4) {1c} ---- b(4) ---- {0b} ]", mnemonic="ABS") @ispec("32<[ c(4) {5c} ---- b(4) ---- {0b} ]", mnemonic="ABS_B") @ispec("32<[ c(4) {7c} ---- b(4) ---- {0b} ]", mnemonic="ABS_H") @@ -72,6 +85,7 @@ def tricore_dd_arithmetic(obj, c, b): obj.operands = [dst, src] obj.type = type_data_processing + @ispec("32<[ c(4) {80} ---- b(4) ---- {0b} ]", mnemonic="MOV") def tricore_dd_arithmetic(obj, c, b): src = env.D[b] @@ -79,13 +93,16 @@ def tricore_dd_arithmetic(obj, c, b): obj.operands = [dst, src.signextend(64)] obj.type = type_data_processing + @ispec("32<[ c(4) {81} ---- b(4) a(4) {0b} ]", mnemonic="MOV") def tricore_dd_arithmetic(obj, c, b, a): + src1 = env.D[a] src2 = env.D[b] dst = env.E[c] - obj.operands = [dst, env.composer([src2,src1])] + obj.operands = [dst, env.composer([src2, src1])] obj.type = type_data_processing + @ispec("32<[ c(4) {0e} ---- b(4) a(4) {0b} ]", mnemonic="ABSDIF") @ispec("32<[ c(4) {4e} ---- b(4) a(4) {0b} ]", mnemonic="ABSDIF_B") @ispec("32<[ c(4) {6e} ---- b(4) a(4) {0b} ]", mnemonic="ABSDIF_H") @@ -178,6 +195,7 @@ def tricore_ddd_arithmetic(obj, c, b, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) {40} ---- b(4) a(4) {01} ]", mnemonic="EQ_A") @ispec("32<[ c(4) {43} ---- b(4) a(4) {01} ]", mnemonic="GE_A") @ispec("32<[ c(4) {42} ---- b(4) a(4) {01} ]", mnemonic="LT_A") @@ -189,15 +207,19 @@ def tricore_daa_arithmetic(obj, c, b, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing -@ispec("32<[ c(4) {63} ---- b(4) ---- {01} ]", mnemonic="MOV_A", _dst=env.A, _src=env.D) -@ispec("32<[ c(4) {00} ---- b(4) ---- {01} ]", mnemonic="MOV_AA", _dst=env.A, _src=env.A) -@ispec("32<[ c(4) {4c} ---- b(4) ---- {01} ]", mnemonic="MOV_D", _dst=env.D, _src=env.A) + +@ispec("32<[ c(4) {63} ---- b(4) ---- {01} ]", mnemonic="MOV_A", _dst=env.A, _src=env.D) +@ispec( + "32<[ c(4) {00} ---- b(4) ---- {01} ]", mnemonic="MOV_AA", _dst=env.A, _src=env.A +) +@ispec("32<[ c(4) {4c} ---- b(4) ---- {01} ]", mnemonic="MOV_D", _dst=env.D, _src=env.A) def tricore_daa_arithmetic(obj, c, b, _dst, _src): dst = _dst[c] src = _src[b] obj.operands = [dst, src] obj.type = type_data_processing + @ispec("32<[ c(4) {48} ---- ---- a(4) {01} ]", mnemonic="EQZ_A") @ispec("32<[ c(4) {49} ---- ---- a(4) {01} ]", mnemonic="NEZ_A") def tricore_da_arithmetic(obj, c, a): @@ -206,6 +228,7 @@ def tricore_da_arithmetic(obj, c, a): obj.operands = [dst, src1] obj.type = type_data_processing + @ispec("32<[ c(4) {01} --00 b(4) a(4) {4b} ]", mnemonic="BMERGE") def tricore_ddd_arithmetic(obj, c, b, a): src1 = env.D[a] @@ -214,6 +237,7 @@ def tricore_ddd_arithmetic(obj, c, b, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) {06} --00 b(4) a(4) {4b} ]", mnemonic="CRC32_B") @ispec("32<[ c(4) {03} --00 b(4) a(4) {4b} ]", mnemonic="CRC32B_W") @ispec("32<[ c(4) {03} --00 b(4) a(4) {4b} ]", mnemonic="CRC32L_W") @@ -224,6 +248,7 @@ def tricore_crc32(obj, c, b, a): obj.operands = [dst, src2, src1] obj.type = type_data_processing + @ispec("32<[ c(4) {20} --01 b(4) a(4) {4b} ]", mnemonic="DIV") @ispec("32<[ c(4) {21} --01 b(4) a(4) {4b} ]", mnemonic="DIV_U") @ispec("32<[ c(4) {5a} --00 b(4) a(4) {4b} ]", mnemonic="DVINIT_B") @@ -235,12 +260,13 @@ def tricore_crc32(obj, c, b, a): def tricore_edd_arithmetic(obj, c, b, a): src1 = env.D[a] src2 = env.D[b] - if c%2: + if c % 2: raise InstructionError(obj) dst = env.E[c] obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 100 ----- b(4) a(4) {17} ]", mnemonic="DEXTR") def tricore_dddc(obj, c, d, b, a): shift = env.D[d] @@ -250,10 +276,11 @@ def tricore_dddc(obj, c, d, b, a): obj.operands = [dst, src1, src2, shift] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 010 ----- ---- a(4) {17} ]", mnemonic="EXTR") @ispec("32<[ c(4) d(4) 011 ----- ---- a(4) {17} ]", mnemonic="EXTR_U") def tricore_extr(obj, c, d, a): - if d%2: + if d % 2: raise InstructionError(obj) width = env.E[d][32:37] src1 = env.D[a] @@ -261,9 +288,10 @@ def tricore_extr(obj, c, d, a): obj.operands = [dst, src1, width] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 000 0--00 ---- a(4) {6b} ]", mnemonic="PACK") def tricore_extr(obj, c, d, a): - if d%2: + if d % 2: raise InstructionError(obj) src1 = env.E[d] src2 = env.D[a] @@ -271,6 +299,7 @@ def tricore_extr(obj, c, d, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) {08} -- 00 ---- a(4) {4b} ]", mnemonic="UNPACK") def tricore_extr(obj, c, d, a): src = env.D[a] @@ -278,6 +307,7 @@ def tricore_extr(obj, c, d, a): obj.operands = [dst, src] obj.type = type_data_processing + @ispec("32<[ c(4) {02} -- 00 ---- a(4) {4b} ]", mnemonic="PARITY") @ispec("32<[ c(4) {22} -- 00 ---- a(4) {4b} ]", mnemonic="POPCNT_W") def tricore_extr(obj, c, d, a): @@ -286,120 +316,134 @@ def tricore_extr(obj, c, d, a): obj.operands = [dst, src] obj.type = type_data_processing + @ispec("32<[ c(4) pos(5) 00 ----- b(4) a(4) {77} ]", mnemonic="DEXTR") def tricore_dextr(obj, c, pos, b, a): src1 = env.D[a] src2 = env.D[b] dst = env.D[c] - obj.operands = [dst, src1, src2, env.cst(pos,5)] + obj.operands = [dst, src1, src2, env.cst(pos, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) pos(5) 10 width(5) ---- a(4) {37} ]", mnemonic="EXTR") @ispec("32<[ c(4) pos(5) 11 width(5) ---- a(4) {37} ]", mnemonic="EXTR_U") def tricore_extr(obj, c, pos, width, a): src1 = env.D[a] dst = env.D[c] - obj.operands = [dst, src1, env.cst(pos,5), env.cst(width,5)] + obj.operands = [dst, src1, env.cst(pos, 5), env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) pos(5) 01 width(5) const(4) ---- {b7} ]", mnemonic="IMASK") def tricore_imask(obj, c, pos, width, const): - if c%2: + if c % 2: raise InstructionError(obj) dst = env.E[c] - obj.operands = [dst, env.cst(const,4), env.cst(pos,5), env.cst(width,5)] + obj.operands = [dst, env.cst(const, 4), env.cst(pos, 5), env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 001 width(5) const(4) ---- {d7} ]", mnemonic="IMASK") def tricore_imask(obj, c, d, width, const): src2 = env.D[d] - if c%2: + if c % 2: raise InstructionError(obj) dst = env.E[c] - obj.operands = [dst, env.cst(const,4), src2, env.cst(width,5)] + obj.operands = [dst, env.cst(const, 4), src2, env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) pos(5) 01 width(5) b(4) ---- {37} ]", mnemonic="IMASK") def tricore_imask(obj, c, pos, width, b): src1 = env.D[b] - if c%2: + if c % 2: raise InstructionError(obj) dst = env.E[c] - obj.operands = [dst, src1, env.cst(pos,5), env.cst(width,5)] + obj.operands = [dst, src1, env.cst(pos, 5), env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 001 width(5) b(4) ---- {57} ]", mnemonic="IMASK") def tricore_imask(obj, c, d, width, b): src1 = env.D[b] src2 = env.D[d] - if c%2: + if c % 2: raise InstructionError(obj) dst = env.E[c] - obj.operands = [dst, src1, src2, env.cst(width,5)] + obj.operands = [dst, src1, src2, env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) pos(5) 00 width(5) const(4) a(4) {b7} ]", mnemonic="INSERT") def tricore_imask(obj, c, pos, width, const, a): dst = env.D[c] src1 = env.D[a] - obj.operands = [dst, src1, env.cst(const,4), env.cst(pos,5), env.cst(width,5)] + obj.operands = [dst, src1, env.cst(const, 4), env.cst(pos, 5), env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 000 ----- const(4) a(4) {97} ]", mnemonic="INSERT") def tricore_imask(obj, c, d, const, a): src1 = env.D[a] - if d%2: + if d % 2: raise InstructionError(obj) src3 = env.E[d] dst = env.D[c] - obj.operands = [dst, src1, env.cst(const,4), src3] + obj.operands = [dst, src1, env.cst(const, 4), src3] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 000 width(5) const(4) a(4) {d7} ]", mnemonic="INSERT") def tricore_imask(obj, c, d, width, const, a): src1 = env.D[a] src3 = env.D[d] dst = env.D[c] - obj.operands = [dst, src1, env.cst(const,4), src3] + obj.operands = [dst, src1, env.cst(const, 4), src3] obj.type = type_data_processing + @ispec("32<[ c(4) pos(5) 00 width(5) b(4) a(4) {37} ]", mnemonic="INSERT") def tricore_imask(obj, c, pos, width, b, a): dst = env.D[c] src1 = env.D[a] src2 = env.D[b] - obj.operands = [dst, src1, src2, env.cst(pos,5), env.cst(width,5)] + obj.operands = [dst, src1, src2, env.cst(pos, 5), env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 000 ----- b(4) a(4) {17} ]", mnemonic="INSERT") def tricore_imask(obj, c, d, b, a): src1 = env.D[a] src2 = env.D[b] - if d%2: + if d % 2: raise InstructionError(obj) src3 = env.E[d] dst = env.D[c] obj.operands = [dst, src1, src2, src3] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 000 width(5) b(4) a(4) {57} ]", mnemonic="INSERT") def tricore_imask(obj, c, d, width, b, a): src1 = env.D[a] src2 = env.D[b] src3 = env.D[d] dst = env.D[c] - obj.operands = [dst, src1, src2, src3, env.cst(width,5)] + obj.operands = [dst, src1, src2, src3, env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 010 width(5) ---- a(4) {57} ]", mnemonic="EXTR") @ispec("32<[ c(4) d(4) 011 width(5) ---- a(4) {57} ]", mnemonic="EXTR_U") def tricore_extr(obj, c, d, width, a): src2 = env.D[d] src1 = env.D[a] dst = env.D[c] - obj.operands = [dst, src1, src2, env.cst(width,5)] + obj.operands = [dst, src1, src2, env.cst(width, 5)] obj.type = type_data_processing + @ispec("32<[ c(4) {09} --00 ---- a(4) {4b} ]", mnemonic="BSPLIT") def tricore_edd_arithmetic(obj, c, a): src1 = env.D[a] @@ -407,12 +451,15 @@ def tricore_edd_arithmetic(obj, c, a): obj.operands = [dst, src1] obj.type = type_data_processing + @ispec("32<[ c(4) 0001110 ~const9(9) a(4) {8b} ]", mnemonic="ABSDIF") @ispec("32<[ c(4) 0001111 ~const9(9) a(4) {8b} ]", mnemonic="ABSDIFS") @ispec("32<[ c(4) 0000000 ~const9(9) a(4) {8b} ]", mnemonic="ADD") @ispec("32<[ c(4) 0000101 ~const9(9) a(4) {8b} ]", mnemonic="ADDC") @ispec("32<[ c(4) 0000010 ~const9(9) a(4) {8b} ]", mnemonic="ADDS") -@ispec("32<[ c(4) 0000011 ~const9(9) a(4) {8b} ]", mnemonic="ADDS_U") #const9 is signed +@ispec( + "32<[ c(4) 0000011 ~const9(9) a(4) {8b} ]", mnemonic="ADDS_U" +) # const9 is signed @ispec("32<[ c(4) 0000100 ~const9(9) a(4) {8b} ]", mnemonic="ADDX") @ispec("32<[ c(4) 0100000 ~const9(9) a(4) {8b} ]", mnemonic="AND_EQ") @ispec("32<[ c(4) 0100100 ~const9(9) a(4) {8b} ]", mnemonic="AND_GE") @@ -430,7 +477,9 @@ def tricore_edd_arithmetic(obj, c, a): @ispec("32<[ c(4) 0101001 ~const9(9) a(4) {8b} ]", mnemonic="OR_LT") @ispec("32<[ c(4) 0001000 ~const9(9) a(4) {8b} ]", mnemonic="RSUB") @ispec("32<[ c(4) 0001001 ~const9(9) a(4) {8b} ]", mnemonic="RSUBS") -@ispec("32<[ c(4) 0001011 ~const9(9) a(4) {8b} ]", mnemonic="RSUBS_U") #const9 is signed +@ispec( + "32<[ c(4) 0001011 ~const9(9) a(4) {8b} ]", mnemonic="RSUBS_U" +) # const9 is signed @ispec("32<[ c(4) 0000000 ~const9(9) a(4) {8f} ]", mnemonic="SH") @ispec("32<[ c(4) 1000000 ~const9(9) a(4) {8f} ]", mnemonic="SH_H") @ispec("32<[ c(4) 0110111 ~const9(9) a(4) {8b} ]", mnemonic="SH_EQ") @@ -446,15 +495,16 @@ def tricore_edd_arithmetic(obj, c, a): @ispec("32<[ c(4) 0110000 ~const9(9) a(4) {8b} ]", mnemonic="XOR_NE") def tricore_ddc_arithmetic(obj, c, const9, a): src1 = env.D[a] - if obj.mnemonic in ("SH","SHA","SHAS"): + if obj.mnemonic in ("SH", "SHA", "SHAS"): const9 = const9[0:6] - elif obj.mnemonic in ("SH_H","SHA_H"): + elif obj.mnemonic in ("SH_H", "SHA_H"): const9 = const9[0:5] - src2 = env.cst(const9.int(-1),32) + src2 = env.cst(const9.int(-1), 32) dst = env.D[c] obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) pos2(5) 00 pos1(5) b(4) a(4) {47} ]", mnemonic="AND_AND_T") @ispec("32<[ c(4) pos2(5) 11 pos1(5) b(4) a(4) {47} ]", mnemonic="AND_ANDN_T") @ispec("32<[ c(4) pos2(5) 10 pos1(5) b(4) a(4) {47} ]", mnemonic="AND_NOR_T") @@ -485,9 +535,10 @@ def tricore_ddd_arithmetic(obj, c, pos2, pos1, b, a): src1 = env.D[a] src2 = env.D[b] dst = env.D[c] - obj.operands = [dst, src1[pos1:pos1+1], src2[pos2:pos2+1]] + obj.operands = [dst, src1[pos1 : pos1 + 1], src2[pos2 : pos2 + 1]] obj.type = type_data_processing + @ispec("32<[ c(4) 0001000 const9(9) a(4) {8f} ]", mnemonic="AND") @ispec("32<[ c(4) 0100101 const9(9) a(4) {8b} ]", mnemonic="AND_GE_U") @ispec("32<[ c(4) 0100011 const9(9) a(4) {8b} ]", mnemonic="AND_LT_U") @@ -511,21 +562,23 @@ def tricore_ddd_arithmetic(obj, c, pos2, pos1, b, a): @ispec("32<[ c(4) 0010011 const9(9) a(4) {8b} ]", mnemonic="LT_U") def tricore_ddc_arithmetic(obj, c, const9, a): src1 = env.D[a] - src2 = env.cst(const9,32) + src2 = env.cst(const9, 32) dst = env.D[c] obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ ~const4(4) a(4) {c2} ]", mnemonic="ADD") @ispec("16<[ ~const4(4) a(4) {06} ]", mnemonic="SH") @ispec("16<[ ~const4(4) a(4) {86} ]", mnemonic="SHA") def tricore_ddc_arithmetic(obj, const4, a): dst = env.D[a] - src2 = env.cst(const4.int(-1),32) + src2 = env.cst(const4.int(-1), 32) src1 = env.D[a] obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ ~const4(4) a(4) {92} ]", mnemonic="ADD") @ispec("16<[ ~const4(4) a(4) {8a} ]", mnemonic="CADD") @ispec("16<[ ~const4(4) a(4) {ca} ]", mnemonic="CADDN") @@ -533,52 +586,57 @@ def tricore_ddc_arithmetic(obj, const4, a): @ispec("16<[ ~const4(4) a(4) {ea} ]", mnemonic="CMOVN") def tricore_ddc_arithmetic(obj, const4, a): dst = env.D[a] - src2 = env.cst(const4.int(-1),32) + src2 = env.cst(const4.int(-1), 32) src1 = env.D[15] obj.operands = [dst, src1, src2] if "CADD" in obj.mnemonic: obj.operands = [dst, src1, dst, src2] obj.type = type_data_processing + @ispec("16<[ ~const4(4) a(4) {9a} ]", mnemonic="ADD") @ispec("16<[ ~const4(4) a(4) {ba} ]", mnemonic="EQ") @ispec("16<[ ~const4(4) a(4) {fa} ]", mnemonic="LT") @ispec("16<[ ~const4(4) a(4) {82} ]", mnemonic="MOV") def tricore_ddc_arithmetic(obj, const4, a): dst = env.D[15] - src2 = env.cst(const4.int(-1),32) + src2 = env.cst(const4.int(-1), 32) src1 = env.D[a] obj.operands = [dst, src1, src2] - if obj.mnemonic=="MOV": - obj.operands = [src1,src2] + if obj.mnemonic == "MOV": + obj.operands = [src1, src2] obj.type = type_data_processing + @ispec("16<[ ~const4(4) a(4) {d2} ]", mnemonic="MOV") def tricore_ec_arithmetic(obj, const4, a): dst = env.E[a] - src = env.cst(const4.int(-1),64) + src = env.cst(const4.int(-1), 64) obj.operands = [dst, src] obj.type = type_data_processing + @ispec("16<[ const4(4) a(4) {a0} ]", mnemonic="MOV_A") def tricore_ec_arithmetic(obj, const4, a): dst = env.A[a] - src = env.cst(const4,32) + src = env.cst(const4, 32) obj.operands = [dst, src] obj.type = type_data_processing + @ispec("16<[ const8(8) {16} ]", mnemonic="AND") @ispec("16<[ const8(8) {da} ]", mnemonic="MOV") @ispec("16<[ const8(8) {96} ]", mnemonic="OR") def tricore_ddc_arithmetic(obj, const8): dst = env.D[15] - src2 = env.cst(const8,32) + src2 = env.cst(const8, 32) src1 = env.D[15] obj.operands = [dst, src1, src2] - if obj.mnemonic=="MOV": - obj.operands = [src1,src2] + if obj.mnemonic == "MOV": + obj.operands = [src1, src2] obj.type = type_data_processing + @ispec("16<[ b(4) a(4) {42} ]", mnemonic="ADD") @ispec("16<[ b(4) a(4) {26} ]", mnemonic="AND") @ispec("16<[ b(4) a(4) {a6} ]", mnemonic="OR") @@ -592,16 +650,18 @@ def tricore_dd_arithmetic(obj, b, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing -@ispec("16<[ b(4) a(4) {02} ]", mnemonic="MOV" , _dst=env.D, _src=env.D) -@ispec("16<[ b(4) a(4) {60} ]", mnemonic="MOV_A" , _dst=env.A, _src=env.D) -@ispec("16<[ b(4) a(4) {40} ]", mnemonic="MOV_AA" , _dst=env.A, _src=env.A) -@ispec("16<[ b(4) a(4) {80} ]", mnemonic="MOV_D" , _dst=env.D, _src=env.A) + +@ispec("16<[ b(4) a(4) {02} ]", mnemonic="MOV", _dst=env.D, _src=env.D) +@ispec("16<[ b(4) a(4) {60} ]", mnemonic="MOV_A", _dst=env.A, _src=env.D) +@ispec("16<[ b(4) a(4) {40} ]", mnemonic="MOV_AA", _dst=env.A, _src=env.A) +@ispec("16<[ b(4) a(4) {80} ]", mnemonic="MOV_D", _dst=env.D, _src=env.A) def tricore_mov(obj, b, a, _dst, _src): dst = _dst[a] src = _src[b] obj.operands = [dst, src] obj.type = type_data_processing + @ispec("16<[ b(4) a(4) {12} ]", mnemonic="ADD") @ispec("16<[ b(4) a(4) {2a} ]", mnemonic="CMOV") @ispec("16<[ b(4) a(4) {6a} ]", mnemonic="CMOVN") @@ -613,6 +673,7 @@ def tricore_dd_arithmetic(obj, b, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ b(4) a(4) {1a} ]", mnemonic="ADD") @ispec("16<[ b(4) a(4) {22} ]", mnemonic="ADDS") @ispec("16<[ b(4) a(4) {3a} ]", mnemonic="EQ") @@ -625,6 +686,7 @@ def tricore_dd_arithmetic(obj, b, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) {01} ---- b(4) a(4) {01} ]", mnemonic="ADD_A") @ispec("32<[ c(4) {02} ---- b(4) a(4) {01} ]", mnemonic="SUB_A") def tricore_aaa_arithmetic(obj, c, b, a): @@ -634,22 +696,25 @@ def tricore_aaa_arithmetic(obj, c, b, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ ~const4(4) a(4) {b0} ]", mnemonic="ADD_A") def tricore_aac_arithmetic(obj, const4, a): dst = env.A[a] - src2 = env.cst(const4.int(-1),32) + src2 = env.cst(const4.int(-1), 32) src1 = env.A[a] obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ const8(8) {20} ]", mnemonic="SUB_A") def tricore_aac_arithmetic(obj, const8, a): dst = env.A[10] - src2 = env.cst(const8,32) + src2 = env.cst(const8, 32) src1 = env.A[10] obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ b(4) a(4) {30} ]", mnemonic="ADD_A") def tricore_aa_arithmetic(obj, b, a): dst = env.A[a] @@ -658,32 +723,37 @@ def tricore_aa_arithmetic(obj, b, a): obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) ~const16(16) a(4) {1b} ]", mnemonic="ADDI") @ispec("32<[ c(4) ~const16(16) a(4) {9b} ]", mnemonic="ADDIH") def tricore_di_arithmetic(obj, c, const16, a): src1 = env.D[a] - src2 = env.cst(const16.int(-1),32) - if self.mnemonic=="ADDIH": src2=src2<<16 + src2 = env.cst(const16.int(-1), 32) + if obj.mnemonic == "ADDIH": + src2 = src2 << 16 dst = env.D[c] obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) ~const16(16) a(4) {11} ]", mnemonic="ADDIH_A") def tricore_ai_arithmetic(obj, c, const16, a): src1 = env.A[a] - src2 = env.cst(const16.int(-1),32)<<16 + src2 = env.cst(const16.int(-1), 32) << 16 dst = env.A[c] obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) {60} -- n(2) b(4) a(4) {01} ]", mnemonic="ADDSC_A") def tricore_aaa_arithmetic(obj, c, n, b, a): src1 = env.D[a] src2 = env.A[b] dst = env.A[c] - obj.operands = [dst, src2, src1, env.cst(n,2)] + obj.operands = [dst, src2, src1, env.cst(n, 2)] obj.type = type_data_processing + @ispec("32<[ c(4) {62} ---- b(4) a(4) {01} ]", mnemonic="ADDSC_AT") def tricore_aaa_arithmetic(obj, c, b, a): src1 = env.D[a] @@ -692,98 +762,280 @@ def tricore_aaa_arithmetic(obj, c, b, a): obj.operands = [dst, src2, src1] obj.type = type_data_processing + @ispec("16<[ b(4) a(4) n(2) 010000 ]", mnemonic="ADDSC_A") def tricore_aa_arithmetic(obj, b, a, n): dst = env.A[a] src1 = env.D[15] src2 = env.A[b] - obj.operands = [dst, src2, src1, env.cst(n,2)] - obj.type = type_data_processing - -@ispec("32<[ off2(4) 10 1110 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_I", mode="Short-offset") -@ispec("32<[ off2(4) 00 1110 off1(6) b(4) ---- {a9} ]", mnemonic="CACHEA_I", mode="Bit-reverse") -@ispec("32<[ off2(4) 01 1110 off1(6) b(4) ---- {a9} ]", mnemonic="CACHEA_I", mode="Circular") -@ispec("32<[ off2(4) 00 1110 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_I", mode="Post-increment") -@ispec("32<[ off2(4) 01 1110 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_I", mode="Pre-increment") -@ispec("32<[ off2(4) 10 1100 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_W", mode="Short-offset") -@ispec("32<[ off2(4) 00 1100 off1(6) b(4) ---- {a9} ]", mnemonic="CACHEA_W", mode="Bit-reverse") -@ispec("32<[ off2(4) 01 1100 off1(6) b(4) ---- {a9} ]", mnemonic="CACHEA_W", mode="Circular") -@ispec("32<[ off2(4) 00 1100 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_W", mode="Post-increment") -@ispec("32<[ off2(4) 01 1100 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_W", mode="Pre-increment") -@ispec("32<[ off2(4) 10 1101 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_WI", mode="Short-offset") -@ispec("32<[ off2(4) 00 1101 off1(6) b(4) ---- {a9} ]", mnemonic="CACHEA_WI", mode="Bit-reverse") -@ispec("32<[ off2(4) 01 1101 off1(6) b(4) ---- {a9} ]", mnemonic="CACHEA_WI", mode="Circular") -@ispec("32<[ off2(4) 00 1101 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_WI", mode="Post-increment") -@ispec("32<[ off2(4) 01 1101 off1(6) b(4) ---- {89} ]", mnemonic="CACHEA_WI", mode="Pre-increment") -@ispec("32<[ off2(4) 10 1011 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_W", mode="Short-offset") -@ispec("32<[ off2(4) 00 1011 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_W", mode="Post-increment") -@ispec("32<[ off2(4) 01 1011 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_W", mode="Pre-increment") -@ispec("32<[ off2(4) 10 1010 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_I", mode="Short-offset") -@ispec("32<[ off2(4) 00 1010 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_I", mode="Post-increment") -@ispec("32<[ off2(4) 01 1010 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_I", mode="Pre-increment") -@ispec("32<[ off2(4) 10 1111 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_WI", mode="Short-offset") -@ispec("32<[ off2(4) 00 1111 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_WI", mode="Post-increment") -@ispec("32<[ off2(4) 01 1111 off1(6) b(4) ---- {89} ]", mnemonic="CACHEI_WI", mode="Pre-increment") + obj.operands = [dst, src2, src1, env.cst(n, 2)] + obj.type = type_data_processing + + +@ispec( + "32<[ off2(4) 10 1110 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_I", + mode="Short-offset", +) +@ispec( + "32<[ off2(4) 00 1110 off1(6) b(4) ---- {a9} ]", + mnemonic="CACHEA_I", + mode="Bit-reverse", +) +@ispec( + "32<[ off2(4) 01 1110 off1(6) b(4) ---- {a9} ]", + mnemonic="CACHEA_I", + mode="Circular", +) +@ispec( + "32<[ off2(4) 00 1110 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_I", + mode="Post-increment", +) +@ispec( + "32<[ off2(4) 01 1110 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_I", + mode="Pre-increment", +) +@ispec( + "32<[ off2(4) 10 1100 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_W", + mode="Short-offset", +) +@ispec( + "32<[ off2(4) 00 1100 off1(6) b(4) ---- {a9} ]", + mnemonic="CACHEA_W", + mode="Bit-reverse", +) +@ispec( + "32<[ off2(4) 01 1100 off1(6) b(4) ---- {a9} ]", + mnemonic="CACHEA_W", + mode="Circular", +) +@ispec( + "32<[ off2(4) 00 1100 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_W", + mode="Post-increment", +) +@ispec( + "32<[ off2(4) 01 1100 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_W", + mode="Pre-increment", +) +@ispec( + "32<[ off2(4) 10 1101 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_WI", + mode="Short-offset", +) +@ispec( + "32<[ off2(4) 00 1101 off1(6) b(4) ---- {a9} ]", + mnemonic="CACHEA_WI", + mode="Bit-reverse", +) +@ispec( + "32<[ off2(4) 01 1101 off1(6) b(4) ---- {a9} ]", + mnemonic="CACHEA_WI", + mode="Circular", +) +@ispec( + "32<[ off2(4) 00 1101 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_WI", + mode="Post-increment", +) +@ispec( + "32<[ off2(4) 01 1101 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEA_WI", + mode="Pre-increment", +) +@ispec( + "32<[ off2(4) 10 1011 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_W", + mode="Short-offset", +) +@ispec( + "32<[ off2(4) 00 1011 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_W", + mode="Post-increment", +) +@ispec( + "32<[ off2(4) 01 1011 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_W", + mode="Pre-increment", +) +@ispec( + "32<[ off2(4) 10 1010 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_I", + mode="Short-offset", +) +@ispec( + "32<[ off2(4) 00 1010 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_I", + mode="Post-increment", +) +@ispec( + "32<[ off2(4) 01 1010 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_I", + mode="Pre-increment", +) +@ispec( + "32<[ off2(4) 10 1111 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_WI", + mode="Short-offset", +) +@ispec( + "32<[ off2(4) 00 1111 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_WI", + mode="Post-increment", +) +@ispec( + "32<[ off2(4) 01 1111 off1(6) b(4) ---- {89} ]", + mnemonic="CACHEI_WI", + mode="Pre-increment", +) def tricore_cache(obj, off2, off1, b): src2 = env.A[b] - src1 = env.cst((off2<<6)+off1,10) + src1 = env.cst((off2 << 6) + off1, 10) obj.operands = [src2, src1] obj.type = type_system -@ispec("32<[ off2(4) 10 0011 off1(6) b(4) a(4) {49} ]", mnemonic="CMPSWAP_W", mode="Short-offset") -@ispec("32<[ off2(4) 00 0011 off1(6) b(4) a(4) {69} ]", mnemonic="CMPSWAP_W", mode="Bit-reverse") -@ispec("32<[ off2(4) 01 0011 off1(6) b(4) a(4) {69} ]", mnemonic="CMPSWAP_W", mode="Circular") -@ispec("32<[ off2(4) 00 0011 off1(6) b(4) a(4) {49} ]", mnemonic="CMPSWAP_W", mode="Post-increment") -@ispec("32<[ off2(4) 01 0011 off1(6) b(4) a(4) {49} ]", mnemonic="CMPSWAP_W", mode="Pre-increment") -@ispec("32<[ off2(4) 10 0010 off1(6) b(4) a(4) {49} ]", mnemonic="SWAPMSK_W", mode="Short-offset") -@ispec("32<[ off2(4) 00 0010 off1(6) b(4) a(4) {69} ]", mnemonic="SWAPMSK_W", mode="Bit-reverse") -@ispec("32<[ off2(4) 01 0010 off1(6) b(4) a(4) {69} ]", mnemonic="SWAPMSK_W", mode="Circular") -@ispec("32<[ off2(4) 00 0010 off1(6) b(4) a(4) {49} ]", mnemonic="SWAPMSK_W", mode="Post-increment") -@ispec("32<[ off2(4) 01 0010 off1(6) b(4) a(4) {49} ]", mnemonic="SWAPMSK_W", mode="Pre-increment") + +@ispec( + "32<[ off2(4) 10 0011 off1(6) b(4) a(4) {49} ]", + mnemonic="CMPSWAP_W", + mode="Short-offset", +) +@ispec( + "32<[ off2(4) 00 0011 off1(6) b(4) a(4) {69} ]", + mnemonic="CMPSWAP_W", + mode="Bit-reverse", +) +@ispec( + "32<[ off2(4) 01 0011 off1(6) b(4) a(4) {69} ]", + mnemonic="CMPSWAP_W", + mode="Circular", +) +@ispec( + "32<[ off2(4) 00 0011 off1(6) b(4) a(4) {49} ]", + mnemonic="CMPSWAP_W", + mode="Post-increment", +) +@ispec( + "32<[ off2(4) 01 0011 off1(6) b(4) a(4) {49} ]", + mnemonic="CMPSWAP_W", + mode="Pre-increment", +) +@ispec( + "32<[ off2(4) 10 0010 off1(6) b(4) a(4) {49} ]", + mnemonic="SWAPMSK_W", + mode="Short-offset", +) +@ispec( + "32<[ off2(4) 00 0010 off1(6) b(4) a(4) {69} ]", + mnemonic="SWAPMSK_W", + mode="Bit-reverse", +) +@ispec( + "32<[ off2(4) 01 0010 off1(6) b(4) a(4) {69} ]", + mnemonic="SWAPMSK_W", + mode="Circular", +) +@ispec( + "32<[ off2(4) 00 0010 off1(6) b(4) a(4) {49} ]", + mnemonic="SWAPMSK_W", + mode="Post-increment", +) +@ispec( + "32<[ off2(4) 01 0010 off1(6) b(4) a(4) {49} ]", + mnemonic="SWAPMSK_W", + mode="Pre-increment", +) def tricore_swap(obj, off2, off1, b, a): - if a%2: + if a % 2: raise InstructionError(obj) dst = env.D[a] src1 = env.A[b] - src2 = env.cst((off2<<6)+off1,10) + src2 = env.cst((off2 << 6) + off1, 10) src3 = env.E[a] obj.operands = [dst, src1, src2, src3] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 000 ~const9(9) a(4) {ab} ]", mnemonic="CADD") @ispec("32<[ c(4) d(4) 001 ~const9(9) a(4) {ab} ]", mnemonic="CADDN") -@ispec("32<[ c(4) d(4) 001 ~const9(9) a(4) {13} ]", mnemonic="MADD", opt4="32+(32+K9)->32") -@ispec("32<[ c(4) d(4) 101 ~const9(9) a(4) {13} ]", mnemonic="MADDS", opt4="32+(32+K9)->32") -@ispec("32<[ c(4) d(4) 100 ~const9(9) a(4) {13} ]", mnemonic="MADDS_U", opt4="32+(32+K9)->32") -@ispec("32<[ c(4) d(4) 001 ~const9(9) a(4) {33} ]", mnemonic="MSUB", opt4="32+(32+K9)->32") -@ispec("32<[ c(4) d(4) 101 ~const9(9) a(4) {33} ]", mnemonic="MSUBS", opt4="32+(32+K9)->32") -@ispec("32<[ c(4) d(4) 100 ~const9(9) a(4) {33} ]", mnemonic="MSUBS_U", opt4="32+(32+K9)->32") +@ispec( + "32<[ c(4) d(4) 001 ~const9(9) a(4) {13} ]", mnemonic="MADD", opt4="32+(32+K9)->32" +) +@ispec( + "32<[ c(4) d(4) 101 ~const9(9) a(4) {13} ]", mnemonic="MADDS", opt4="32+(32+K9)->32" +) +@ispec( + "32<[ c(4) d(4) 100 ~const9(9) a(4) {13} ]", + mnemonic="MADDS_U", + opt4="32+(32+K9)->32", +) +@ispec( + "32<[ c(4) d(4) 001 ~const9(9) a(4) {33} ]", mnemonic="MSUB", opt4="32+(32+K9)->32" +) +@ispec( + "32<[ c(4) d(4) 101 ~const9(9) a(4) {33} ]", mnemonic="MSUBS", opt4="32+(32+K9)->32" +) +@ispec( + "32<[ c(4) d(4) 100 ~const9(9) a(4) {33} ]", + mnemonic="MSUBS_U", + opt4="32+(32+K9)->32", +) @ispec("32<[ c(4) d(4) 100 ~const9(9) a(4) {ab} ]", mnemonic="SEL") @ispec("32<[ c(4) d(4) 101 ~const9(9) a(4) {ab} ]", mnemonic="SELN") def tricore_cond_ddc(obj, c, d, const9, a): cond = env.D[d] src1 = env.D[a] - src2 = env.cst(const9.int(-1),32) + src2 = env.cst(const9.int(-1), 32) dst = env.D[c] obj.operands = [dst, cond, src1, src2] obj.type = type_data_processing -@ispec("32<[ c(4) d(4) 011 ~const9(9) a(4) {13} ]", mnemonic="MADD", opt4="64+(32+K9)->64") -@ispec("32<[ c(4) d(4) 111 ~const9(9) a(4) {13} ]", mnemonic="MADDS", opt4="64+(32+K9)->64") -@ispec("32<[ c(4) d(4) 010 ~const9(9) a(4) {13} ]", mnemonic="MADD_U", opt4="64+(32+K9)->64") -@ispec("32<[ c(4) d(4) 111 ~const9(9) a(4) {13} ]", mnemonic="MADDS_U", opt4="64+(32+K9)->64") -@ispec("32<[ c(4) d(4) 011 ~const9(9) a(4) {33} ]", mnemonic="MSUB", opt4="64+(32+K9)->64") -@ispec("32<[ c(4) d(4) 111 ~const9(9) a(4) {33} ]", mnemonic="MSUBS", opt4="64+(32+K9)->64") -@ispec("32<[ c(4) d(4) 010 ~const9(9) a(4) {33} ]", mnemonic="MSUB_U", opt4="64+(32+K9)->64") -@ispec("32<[ c(4) d(4) 111 ~const9(9) a(4) {33} ]", mnemonic="MSUBS_U", opt4="64+(32+K9)->64") + +@ispec( + "32<[ c(4) d(4) 011 ~const9(9) a(4) {13} ]", mnemonic="MADD", opt4="64+(32+K9)->64" +) +@ispec( + "32<[ c(4) d(4) 111 ~const9(9) a(4) {13} ]", mnemonic="MADDS", opt4="64+(32+K9)->64" +) +@ispec( + "32<[ c(4) d(4) 010 ~const9(9) a(4) {13} ]", + mnemonic="MADD_U", + opt4="64+(32+K9)->64", +) +@ispec( + "32<[ c(4) d(4) 111 ~const9(9) a(4) {13} ]", + mnemonic="MADDS_U", + opt4="64+(32+K9)->64", +) +@ispec( + "32<[ c(4) d(4) 011 ~const9(9) a(4) {33} ]", mnemonic="MSUB", opt4="64+(32+K9)->64" +) +@ispec( + "32<[ c(4) d(4) 111 ~const9(9) a(4) {33} ]", mnemonic="MSUBS", opt4="64+(32+K9)->64" +) +@ispec( + "32<[ c(4) d(4) 010 ~const9(9) a(4) {33} ]", + mnemonic="MSUB_U", + opt4="64+(32+K9)->64", +) +@ispec( + "32<[ c(4) d(4) 111 ~const9(9) a(4) {33} ]", + mnemonic="MSUBS_U", + opt4="64+(32+K9)->64", +) def tricore_cond_eec(obj, c, d, const9, a): cond = env.E[d] src1 = env.D[a] - src2 = env.cst(const9.int(-1),32) + src2 = env.cst(const9.int(-1), 32) dst = env.E[c] obj.operands = [dst, cond, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 011010 n(2) b(4) a(4) {83} ]", mnemonic="MADD_H", op4="LL") @ispec("32<[ c(4) d(4) 011001 n(2) b(4) a(4) {83} ]", mnemonic="MADD_H", op4="LU") @ispec("32<[ c(4) d(4) 011000 n(2) b(4) a(4) {83} ]", mnemonic="MADD_H", op4="UL") @@ -792,26 +1044,106 @@ def tricore_cond_eec(obj, c, d, const9, a): @ispec("32<[ c(4) d(4) 111001 n(2) b(4) a(4) {83} ]", mnemonic="MADDS_H", op4="LU") @ispec("32<[ c(4) d(4) 111000 n(2) b(4) a(4) {83} ]", mnemonic="MADDS_H", op4="UL") @ispec("32<[ c(4) d(4) 111011 n(2) b(4) a(4) {83} ]", mnemonic="MADDS_H", op4="UU") -@ispec("32<[ c(4) d(4) 000010 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="32+(32*32)Up->32") -@ispec("32<[ c(4) d(4) 011011 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="64+(32*32)->64") -@ispec("32<[ c(4) d(4) 000001 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="32+(16L*32)Up->32") -@ispec("32<[ c(4) d(4) 011001 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="64+(16L*32)->64") -@ispec("32<[ c(4) d(4) 000000 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="32+(16U*32)Up->32") -@ispec("32<[ c(4) d(4) 011000 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="64+(16U*32)->64") -@ispec("32<[ c(4) d(4) 000101 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="32+(16L*16L)->32") -@ispec("32<[ c(4) d(4) 011101 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="64+(16L*16L)->64") -@ispec("32<[ c(4) d(4) 000100 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="32+(16U*16U)->32") -@ispec("32<[ c(4) d(4) 011100 n(2) b(4) a(4) {43} ]", mnemonic="MADD_Q", op4="64+(16U*16U)->64") -@ispec("32<[ c(4) d(4) 100010 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="32+(32*32)Up->32") -@ispec("32<[ c(4) d(4) 111011 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="64+(32*32)->64") -@ispec("32<[ c(4) d(4) 100001 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="32+(16L*32)Up->32") -@ispec("32<[ c(4) d(4) 111001 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="64+(16L*32)->64") -@ispec("32<[ c(4) d(4) 100000 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="32+(16U*32)Up->32") -@ispec("32<[ c(4) d(4) 111000 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="64+(16U*32)->64") -@ispec("32<[ c(4) d(4) 100101 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="32+(16L*16L)->32") -@ispec("32<[ c(4) d(4) 111101 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="64+(16L*16L)->64") -@ispec("32<[ c(4) d(4) 100100 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="32+(16U*16U)->32") -@ispec("32<[ c(4) d(4) 111100 n(2) b(4) a(4) {43} ]", mnemonic="MADDS_Q", op4="64+(16U*16U)->64") +@ispec( + "32<[ c(4) d(4) 000010 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="32+(32*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 011011 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="64+(32*32)->64", +) +@ispec( + "32<[ c(4) d(4) 000001 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="32+(16L*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 011001 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="64+(16L*32)->64", +) +@ispec( + "32<[ c(4) d(4) 000000 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="32+(16U*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 011000 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="64+(16U*32)->64", +) +@ispec( + "32<[ c(4) d(4) 000101 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="32+(16L*16L)->32", +) +@ispec( + "32<[ c(4) d(4) 011101 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="64+(16L*16L)->64", +) +@ispec( + "32<[ c(4) d(4) 000100 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="32+(16U*16U)->32", +) +@ispec( + "32<[ c(4) d(4) 011100 n(2) b(4) a(4) {43} ]", + mnemonic="MADD_Q", + op4="64+(16U*16U)->64", +) +@ispec( + "32<[ c(4) d(4) 100010 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="32+(32*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 111011 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="64+(32*32)->64", +) +@ispec( + "32<[ c(4) d(4) 100001 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="32+(16L*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 111001 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="64+(16L*32)->64", +) +@ispec( + "32<[ c(4) d(4) 100000 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="32+(16U*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 111000 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="64+(16U*32)->64", +) +@ispec( + "32<[ c(4) d(4) 100101 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="32+(16L*16L)->32", +) +@ispec( + "32<[ c(4) d(4) 111101 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="64+(16L*16L)->64", +) +@ispec( + "32<[ c(4) d(4) 100100 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="32+(16U*16U)->32", +) +@ispec( + "32<[ c(4) d(4) 111100 n(2) b(4) a(4) {43} ]", + mnemonic="MADDS_Q", + op4="64+(16U*16U)->64", +) @ispec("32<[ c(4) d(4) 011010 n(2) b(4) a(4) {a3} ]", mnemonic="MSUB_H", op4="LL") @ispec("32<[ c(4) d(4) 011001 n(2) b(4) a(4) {a3} ]", mnemonic="MSUB_H", op4="LU") @ispec("32<[ c(4) d(4) 011000 n(2) b(4) a(4) {a3} ]", mnemonic="MSUB_H", op4="UL") @@ -820,41 +1152,130 @@ def tricore_cond_eec(obj, c, d, const9, a): @ispec("32<[ c(4) d(4) 111001 n(2) b(4) a(4) {a3} ]", mnemonic="MSUBS_H", op4="LU") @ispec("32<[ c(4) d(4) 111000 n(2) b(4) a(4) {a3} ]", mnemonic="MSUBS_H", op4="UL") @ispec("32<[ c(4) d(4) 111011 n(2) b(4) a(4) {a3} ]", mnemonic="MSUBS_H", op4="UU") -@ispec("32<[ c(4) d(4) 000010 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="32+(32*32)Up->32") -@ispec("32<[ c(4) d(4) 011011 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="64+(32*32)->64") -@ispec("32<[ c(4) d(4) 000001 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="32+(16L*32)Up->32") -@ispec("32<[ c(4) d(4) 011001 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="64+(16L*32)->64") -@ispec("32<[ c(4) d(4) 000000 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="32+(16U*32)Up->32") -@ispec("32<[ c(4) d(4) 011000 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="64+(16U*32)->64") -@ispec("32<[ c(4) d(4) 000101 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="32+(16L*16L)->32") -@ispec("32<[ c(4) d(4) 011101 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="64+(16L*16L)->64") -@ispec("32<[ c(4) d(4) 000100 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="32+(16U*16U)->32") -@ispec("32<[ c(4) d(4) 011100 n(2) b(4) a(4) {63} ]", mnemonic="MSUB_Q", op4="64+(16U*16U)->64") -@ispec("32<[ c(4) d(4) 100010 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="32+(32*32)Up->32") -@ispec("32<[ c(4) d(4) 111011 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="64+(32*32)->64") -@ispec("32<[ c(4) d(4) 100001 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="32+(16L*32)Up->32") -@ispec("32<[ c(4) d(4) 111001 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="64+(16L*32)->64") -@ispec("32<[ c(4) d(4) 100000 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="32+(16U*32)Up->32") -@ispec("32<[ c(4) d(4) 111000 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="64+(16U*32)->64") -@ispec("32<[ c(4) d(4) 100101 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="32+(16L*16L)->32") -@ispec("32<[ c(4) d(4) 111101 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="64+(16L*16L)->64") -@ispec("32<[ c(4) d(4) 100100 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="32+(16U*16U)->32") -@ispec("32<[ c(4) d(4) 111100 n(2) b(4) a(4) {63} ]", mnemonic="MSUBS_Q", op4="64+(16U*16U)->64") +@ispec( + "32<[ c(4) d(4) 000010 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="32+(32*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 011011 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="64+(32*32)->64", +) +@ispec( + "32<[ c(4) d(4) 000001 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="32+(16L*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 011001 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="64+(16L*32)->64", +) +@ispec( + "32<[ c(4) d(4) 000000 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="32+(16U*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 011000 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="64+(16U*32)->64", +) +@ispec( + "32<[ c(4) d(4) 000101 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="32+(16L*16L)->32", +) +@ispec( + "32<[ c(4) d(4) 011101 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="64+(16L*16L)->64", +) +@ispec( + "32<[ c(4) d(4) 000100 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="32+(16U*16U)->32", +) +@ispec( + "32<[ c(4) d(4) 011100 n(2) b(4) a(4) {63} ]", + mnemonic="MSUB_Q", + op4="64+(16U*16U)->64", +) +@ispec( + "32<[ c(4) d(4) 100010 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="32+(32*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 111011 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="64+(32*32)->64", +) +@ispec( + "32<[ c(4) d(4) 100001 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="32+(16L*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 111001 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="64+(16L*32)->64", +) +@ispec( + "32<[ c(4) d(4) 100000 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="32+(16U*32)Up->32", +) +@ispec( + "32<[ c(4) d(4) 111000 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="64+(16U*32)->64", +) +@ispec( + "32<[ c(4) d(4) 100101 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="32+(16L*16L)->32", +) +@ispec( + "32<[ c(4) d(4) 111101 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="64+(16L*16L)->64", +) +@ispec( + "32<[ c(4) d(4) 100100 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="32+(16U*16U)->32", +) +@ispec( + "32<[ c(4) d(4) 111100 n(2) b(4) a(4) {63} ]", + mnemonic="MSUBS_Q", + op4="64+(16U*16U)->64", +) def tricore_cond_eec(obj, c, d, n, b, a): cond = env.E[d] src1 = env.D[a] src2 = env.D[b] dst = env.E[c] - obj.operands = [dst, cond, src1, src2, env.cst(n,2)] + obj.operands = [dst, cond, src1, src2, env.cst(n, 2)] obj.type = type_data_processing + @ispec("32<[ c(4) d(4) 0000 ---- b(4) a(4) {2b} ]", mnemonic="CADD") @ispec("32<[ c(4) d(4) 0001 ---- b(4) a(4) {2b} ]", mnemonic="CADDN") @ispec("32<[ c(4) d(4) 0010 ---- b(4) a(4) {2b} ]", mnemonic="CSUB") @ispec("32<[ c(4) d(4) 0011 ---- b(4) a(4) {2b} ]", mnemonic="CSUBN") -@ispec("32<[ c(4) d(4) {0a} b(4) a(4) {03} ]", mnemonic="MADD", opt4="32+(32*32)->32") -@ispec("32<[ c(4) d(4) {8a} b(4) a(4) {03} ]", mnemonic="MADDS", opt4="32+(32*32)->32") -@ispec("32<[ c(4) d(4) {88} b(4) a(4) {03} ]", mnemonic="MADDS_U", opt4="32+(32*32)->32") +@ispec( + "32<[ c(4) d(4) {0a} b(4) a(4) {03} ]", mnemonic="MADD", opt4="32+(32*32)->32" +) +@ispec( + "32<[ c(4) d(4) {8a} b(4) a(4) {03} ]", mnemonic="MADDS", opt4="32+(32*32)->32" +) +@ispec( + "32<[ c(4) d(4) {88} b(4) a(4) {03} ]", + mnemonic="MADDS_U", + opt4="32+(32*32)->32", +) @ispec("32<[ c(4) d(4) 0100 ---- b(4) a(4) {2b} ]", mnemonic="SEL") @ispec("32<[ c(4) d(4) 0101 ---- b(4) a(4) {2b} ]", mnemonic="SELN") def tricore_cond_ddd(obj, c, d, b, a): @@ -865,10 +1286,23 @@ def tricore_cond_ddd(obj, c, d, b, a): obj.operands = [dst, cond, src1, src2] obj.type = type_data_processing -@ispec("32<[ c(4) d(4) {6a} b(4) a(4) {03} ]", mnemonic="MADD", opt4="64+(32*32)->64") -@ispec("32<[ c(4) d(4) {ea} b(4) a(4) {03} ]", mnemonic="MADDS", opt4="64+(32*32)->64") -@ispec("32<[ c(4) d(4) {68} b(4) a(4) {03} ]", mnemonic="MADD_U", opt4="64+(32*32)->64") -@ispec("32<[ c(4) d(4) {e8} b(4) a(4) {03} ]", mnemonic="MADDS_U", opt4="64+(32*32)->64") + +@ispec( + "32<[ c(4) d(4) {6a} b(4) a(4) {03} ]", mnemonic="MADD", opt4="64+(32*32)->64" +) +@ispec( + "32<[ c(4) d(4) {ea} b(4) a(4) {03} ]", mnemonic="MADDS", opt4="64+(32*32)->64" +) +@ispec( + "32<[ c(4) d(4) {68} b(4) a(4) {03} ]", + mnemonic="MADD_U", + opt4="64+(32*32)->64", +) +@ispec( + "32<[ c(4) d(4) {e8} b(4) a(4) {03} ]", + mnemonic="MADDS_U", + opt4="64+(32*32)->64", +) def tricore_cond_ddd(obj, c, d, b, a): cond = env.E[d] src1 = env.D[a] @@ -877,6 +1311,7 @@ def tricore_cond_ddd(obj, c, d, b, a): obj.operands = [dst, cond, src1, src2] obj.type = type_data_processing + @ispec("32<[ c(4) {1c} ---- ---- a(4) {0f} ]", mnemonic="CLO") @ispec("32<[ c(4) {7d} ---- ---- a(4) {0f} ]", mnemonic="CLO_H") @ispec("32<[ c(4) {1d} ---- ---- a(4) {0f} ]", mnemonic="CLS") @@ -893,12 +1328,14 @@ def tricore_dd_arithmetic(obj, c, a): obj.operands = [dst, src] obj.type = type_data_processing + @ispec("16<[ 1010 ---- {00} ]", mnemonic="DEBUG") @ispec("16<[ 0000 ---- {00} ]", mnemonic="NOP") def tricore_system(obj): obj.operands = [] obj.type = type_system + @ispec("16<[ 0111 ---- {00} ]", mnemonic="FRET") @ispec("16<[ 1001 ---- {00} ]", mnemonic="RET") @ispec("16<[ 1000 ---- {00} ]", mnemonic="RFE") @@ -906,6 +1343,7 @@ def tricore_ret(obj): obj.operands = [] obj.type = type_control_flow + @ispec("32<[ ---- 000100 ---------- ---- {0d} ]", mnemonic="DEBUG") @ispec("32<[ ---- 001101 ---------- ---- {0d} ]", mnemonic="DISABLE") @ispec("32<[ ---- 010010 ---------- ---- {0d} ]", mnemonic="DSYNC") @@ -922,6 +1360,7 @@ def tricore_system(obj): obj.operands = [] obj.type = type_system + @ispec("32<[ ---- 000011 ---------- ---- {0d} ]", mnemonic="FRET") @ispec("32<[ ---- 000110 ---------- ---- {0d} ]", mnemonic="RET") @ispec("32<[ ---- 000111 ---------- ---- {0d} ]", mnemonic="RFE") @@ -930,12 +1369,14 @@ def tricore_ret(obj): obj.operands = [] obj.type = type_control_flow + @ispec("32<[ ---- 001111 ---------- a(4) {0d} ]", mnemonic="DISABLE") @ispec("32<[ ---- 001110 ---------- a(4) {0d} ]", mnemonic="RESTORE") def tricore_system(obj, a): obj.operands = [env.D[a]] obj.type = type_system + @ispec("32<[ c(4) d(4) 1101 -- 00 b(4) ---- {6b} ]", mnemonic="DVADJ") @ispec("32<[ c(4) d(4) 1111 -- 00 b(4) ---- {6b} ]", mnemonic="DVSTEP") @ispec("32<[ c(4) d(4) 1110 -- 00 b(4) ---- {6b} ]", mnemonic="DVSTEP_U") @@ -944,7 +1385,7 @@ def tricore_system(obj, a): @ispec("32<[ c(4) d(4) 1000 -- 00 b(4) ---- {6b} ]", mnemonic="IXMIN") @ispec("32<[ c(4) d(4) 1001 -- 00 b(4) ---- {6b} ]", mnemonic="IXMIN_U") def tricore_eee(obj, c, d, b): - if d%2 or b%2 or c%2: + if d % 2 or b % 2 or c % 2: raise InstructionError(obj) src1 = env.E[d] src2 = env.E[b] @@ -952,17 +1393,19 @@ def tricore_eee(obj, c, d, b): obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ ~const4(4) disp(4) {1e} ]", mnemonic="JEQ", _off=0) @ispec("16<[ ~const4(4) disp(4) {9e} ]", mnemonic="JEQ", _off=16) @ispec("16<[ ~const4(4) disp(4) {5e} ]", mnemonic="JNE", _off=0) @ispec("16<[ ~const4(4) disp(4) {de} ]", mnemonic="JNE", _off=16) def tricore_jcc(obj, const4, disp, _off): dst = env.D[15] - src1 = env.cst(const4.int(-1),32) - src2 = env.cst(disp,32)+_off + src1 = env.cst(const4.int(-1), 32) + src2 = env.cst(disp, 32) + _off obj.operands = [dst, src1, src2] obj.type = type_control_flow + @ispec("16<[ b(4) disp(4) {3e} ]", mnemonic="JEQ", _off=0) @ispec("16<[ b(4) disp(4) {be} ]", mnemonic="JEQ", _off=16) @ispec("16<[ b(4) disp(4) {7e} ]", mnemonic="JNE", _off=0) @@ -970,10 +1413,11 @@ def tricore_jcc(obj, const4, disp, _off): def tricore_jcc(obj, b, disp, _off): dst = env.D[15] src1 = env.D[b] - src2 = env.cst(disp,32)+_off + src2 = env.cst(disp, 32) + _off obj.operands = [dst, src1, src2] obj.type = type_control_flow + @ispec("16<[ b(4) disp(4) {ce} ]", mnemonic="JGEZ") @ispec("16<[ b(4) disp(4) {4e} ]", mnemonic="JGTZ") @ispec("16<[ b(4) disp(4) {8e} ]", mnemonic="JLEZ") @@ -982,10 +1426,11 @@ def tricore_jcc(obj, b, disp, _off): @ispec("16<[ b(4) disp(4) {76} ]", mnemonic="JZ") def tricore_jcc(obj, b, disp): src1 = env.D[b] - src2 = env.cst(disp,32) + src2 = env.cst(disp, 32) obj.operands = [src1, src2] obj.type = type_control_flow + @ispec("32<[ 0 ~disp(15) const(4) a(4) {df} ]", mnemonic="JEQ") @ispec("32<[ 1 ~disp(15) const(4) a(4) {df} ]", mnemonic="JNE") @ispec("32<[ 0 ~disp(15) const(4) a(4) {ff} ]", mnemonic="JGE") @@ -996,10 +1441,11 @@ def tricore_jcc(obj, b, disp): @ispec("32<[ 0 ~disp(15) const(4) a(4) {9f} ]", mnemonic="JNEI") def tricore_jcc(obj, disp, const, a): src1 = env.D[a] - src2 = env.cst(const,4) - obj.operands = [src1, src2, env.cst(disp.int(-1),32)] + src2 = env.cst(const, 4) + obj.operands = [src1, src2, env.cst(disp.int(-1), 32)] obj.type = type_control_flow + @ispec("32<[ 0 ~disp(15) b(4) a(4) {5f} ]", mnemonic="JEQ") @ispec("32<[ 1 ~disp(15) b(4) a(4) {5f} ]", mnemonic="JNE") @ispec("32<[ 0 ~disp(15) b(4) a(4) {7f} ]", mnemonic="JGE") @@ -1011,56 +1457,62 @@ def tricore_jcc(obj, disp, const, a): def tricore_jcc(obj, disp, b, a): src1 = env.D[a] src2 = env.D[b] - obj.operands = [src1, src2, env.cst(disp.int(-1),32)] + obj.operands = [src1, src2, env.cst(disp.int(-1), 32)] obj.type = type_control_flow + @ispec("32<[ 0 ~disp(15) b(4) a(4) {7d} ]", mnemonic="JEQ_A") @ispec("32<[ 1 ~disp(15) b(4) a(4) {7d} ]", mnemonic="JNE_A") def tricore_jcc(obj, disp, b, a): src1 = env.A[a] src2 = env.A[b] - obj.operands = [src1, src2, env.cst(disp.int(-1),32)] + obj.operands = [src1, src2, env.cst(disp.int(-1), 32)] obj.type = type_control_flow + @ispec("32<[ 1 ~disp(15) ---- a(4) {bd} ]", mnemonic="JNZ_A") @ispec("32<[ 0 ~disp(15) ---- a(4) {bd} ]", mnemonic="JZ_A") def tricore_jcc(obj, disp, a): src1 = env.A[a] - src2 = env.A[b] - obj.operands = [src1, src2, env.cst(disp.int(-1),32)] + obj.operands = [src1, env.cst(disp.int(-1), 32)] obj.type = type_control_flow + @ispec("32<[ 0 ~disp(15) b(4) ---- {fd} ]", mnemonic="LOOP") @ispec("32<[ 1 ~disp(15) b(4) ---- {fd} ]", mnemonic="LOOPU") def tricore_jcc(obj, disp, b): src1 = env.A[b] - src2 = env.cst(disp.int(-1)*2,32) + src2 = env.cst(disp.int(-1) * 2, 32) obj.operands = [src1, src2] - if obj.mnemonic=="LOOPU": + if obj.mnemonic == "LOOPU": obj.operands = [src2] obj.type = type_control_flow + @ispec("16<[ b(4) disp(4) {7c} ]", mnemonic="JNZ_A") @ispec("16<[ b(4) disp(4) {bc} ]", mnemonic="JZ_A") def tricore_jcc(obj, b, disp): src1 = env.A[b] - src2 = env.cst(disp,32) + src2 = env.cst(disp, 32) obj.operands = [src1, src2] obj.type = type_control_flow + @ispec("16<[ b(4) #disp(4) {fc} ]", mnemonic="LOOP") def tricore_jcc(obj, b, disp): src1 = env.A[b] - src2 = env.cst(int(("1"*27)+disp+"0",2),32) + src2 = env.cst(int(("1" * 27) + disp + "0", 2), 32) obj.operands = [src1, src2] obj.type = type_control_flow + @ispec("16<[ 0000 a(4) {dc} ]", mnemonic="JI") def tricore_ji(obj, a): src = env.A[a] obj.operands = [src] obj.type = type_control_flow + @ispec("16<[ 0000 a(4) {46} ]", mnemonic="NOT") @ispec("16<[ 0101 a(4) {32} ]", mnemonic="RSUB") @ispec("16<[ 0000 a(4) {32} ]", mnemonic="SAT_B") @@ -1072,274 +1524,803 @@ def tricore_a(obj, a): obj.operands = [src] obj.type = type_data_processing + @ispec("16<[ n(4) disp(4) {ae} ]", mnemonic="JNZ_T") @ispec("16<[ n(4) disp(4) {2e} ]", mnemonic="JZ_T") def tricore_ji(obj, n, disp): - obj.operands = [env.D[15][n:n+1], env.cst(disp,32)] + obj.operands = [env.D[15][n : n + 1], env.cst(disp, 32)] obj.type = type_control_flow + @ispec("32<[ 1 ~disp(15) n(4) a(4) h 1101111 ]", mnemonic="JNZ_T") @ispec("32<[ 0 ~disp(15) n(4) a(4) h 1101111 ]", mnemonic="JZ_T") def tricore_jcc(obj, disp, n, a, h): - i = n+(h<<4) - src = env.D[a][i:i+1] - obj.operands = [src, env.cst(disp.int(-1),32)] + i = n + (h << 4) + src = env.D[a][i : i + 1] + obj.operands = [src, env.cst(disp.int(-1), 32)] obj.type = type_control_flow -@ispec("32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {85} ]", mnemonic="LD_A", mode="Absolute") -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {05} ]", mnemonic="LD_B", mode="Absolute") -@ispec("32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {05} ]", mnemonic="LD_BU", mode="Absolute") -@ispec("32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {85} ]", mnemonic="LD_D", mode="Absolute") -@ispec("32<[ ~off2(4) 11 ~off3(4) ~off1(6) ~off4(4) a(4) {85} ]", mnemonic="LD_DA", mode="Absolute") -@ispec("32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {05} ]", mnemonic="LD_H", mode="Absolute") -@ispec("32<[ ~off2(4) 11 ~off3(4) ~off1(6) ~off4(4) a(4) {05} ]", mnemonic="LD_HU", mode="Absolute") -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {45} ]", mnemonic="LD_Q", mode="Absolute") -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {85} ]", mnemonic="LD_W", mode="Absolute") -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {c5} ]", mnemonic="LEA", mode="Absolute") + +@ispec( + "32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {85} ]", + mnemonic="LD_A", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {05} ]", + mnemonic="LD_B", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {05} ]", + mnemonic="LD_BU", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {85} ]", + mnemonic="LD_D", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 11 ~off3(4) ~off1(6) ~off4(4) a(4) {85} ]", + mnemonic="LD_DA", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {05} ]", + mnemonic="LD_H", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 11 ~off3(4) ~off1(6) ~off4(4) a(4) {05} ]", + mnemonic="LD_HU", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {45} ]", + mnemonic="LD_Q", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {85} ]", + mnemonic="LD_W", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {c5} ]", + mnemonic="LEA", + mode="Absolute", +) def tricore_ld(obj, off2, off3, off1, off4, a): dst = env.D[a] - if obj.mnemonic in ("LD_A", "LEA") : dst = env.A[a] - if obj.mnemonic in ("LD_D","LDMST") : dst = env.E[a] - if obj.mnemonic=="LD_DA": dst = env.P[a] - src = off1//off2//off3 - obj.operands = [dst, env.composer([env.cst(src.int(),28),env.cst(off4,4)])] - obj.type = type_data_processing - -@ispec("32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {c5} ]", mnemonic="LHA", mode="Absolute") + if obj.mnemonic in ("LD_A", "LEA"): + dst = env.A[a] + if obj.mnemonic in ("LD_D", "LDMST"): + dst = env.E[a] + if obj.mnemonic == "LD_DA": + dst = env.P[a] + src = off1 // off2 // off3 + obj.operands = [dst, env.composer([env.cst(src.int(), 28), env.cst(off4, 4)])] + obj.type = type_data_processing + + +@ispec( + "32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {c5} ]", + mnemonic="LHA", + mode="Absolute", +) def tricore_ld(obj, off2, off3, off1, off4, a): dst = env.A[a] - src = off1//off2//off3//off4 - obj.operands = [dst, env.composer([env.cst(0,14),env.cst(src.int(),18)])] - obj.type = type_data_processing - -@ispec("32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {a5} ]", mnemonic="ST_A", mode="Absolute") -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {25} ]", mnemonic="ST_B", mode="Absolute") -@ispec("32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {a5} ]", mnemonic="ST_D", mode="Absolute") -@ispec("32<[ ~off2(4) 11 ~off3(4) ~off1(6) ~off4(4) a(4) {a5} ]", mnemonic="ST_DA", mode="Absolute") -@ispec("32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {25} ]", mnemonic="ST_H", mode="Absolute") -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {65} ]", mnemonic="ST_Q", mode="Absolute") -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {a5} ]", mnemonic="ST_W", mode="Absolute") -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {e5} ]", mnemonic="SWAP_W", mode="Absolute") -@ispec("32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {e5} ]", mnemonic="LDMST", mode="Absolute") + src = off1 // off2 // off3 // off4 + obj.operands = [dst, env.composer([env.cst(0, 14), env.cst(src.int(), 18)])] + obj.type = type_data_processing + + +@ispec( + "32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {a5} ]", + mnemonic="ST_A", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {25} ]", + mnemonic="ST_B", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {a5} ]", + mnemonic="ST_D", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 11 ~off3(4) ~off1(6) ~off4(4) a(4) {a5} ]", + mnemonic="ST_DA", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {25} ]", + mnemonic="ST_H", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {65} ]", + mnemonic="ST_Q", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {a5} ]", + mnemonic="ST_W", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) a(4) {e5} ]", + mnemonic="SWAP_W", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 01 ~off3(4) ~off1(6) ~off4(4) a(4) {e5} ]", + mnemonic="LDMST", + mode="Absolute", +) def tricore_st(obj, off2, off3, off1, off4, a): src = env.D[a] - if obj.mnemonic in ("ST_A",) : src = env.A[a] - if obj.mnemonic in ("ST_D","LDMST") : src = env.E[a] - if obj.mnemonic=="ST_DA": src = env.P[a] - addr = off1//off2//off3 - obj.operands = [env.composer([env.cst(addr.int(),28),env.cst(off4,4)]), src] - obj.type = type_data_processing - -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) b bpos(3) {d5} ]", mnemonic="ST_T", mode="Absolute") + if obj.mnemonic in ("ST_A",): + src = env.A[a] + if obj.mnemonic in ("ST_D", "LDMST"): + src = env.E[a] + if obj.mnemonic == "ST_DA": + src = env.P[a] + addr = off1 // off2 // off3 + obj.operands = [env.composer([env.cst(addr.int(), 28), env.cst(off4, 4)]), src] + obj.type = type_data_processing + + +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) b bpos(3) {d5} ]", + mnemonic="ST_T", + mode="Absolute", +) def tricore_st(obj, off2, off3, off1, off4, b, bpos): - obj.operands = [env.composer([env.cst(src.int(),28),env.cst(off4,4)]), env.cst(bpos,3), env.cst(b,1)] + src = off1 // off2 // off3 + obj.operands = [ + env.composer([env.cst(src.int(), 28), env.cst(off4, 4)]), + env.cst(bpos, 3), + env.cst(b, 1), + ] obj.type = type_data_processing -@ispec("32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) ---- {15} ]", mnemonic="STLCX", mode="Absolute") + +@ispec( + "32<[ ~off2(4) 00 ~off3(4) ~off1(6) ~off4(4) ---- {15} ]", + mnemonic="STLCX", + mode="Absolute", +) def tricore_st(obj, off2, off3, off1, off4): - obj.operands = [env.composer([env.cst(src.int(),28),env.cst(off4,4)])] + src = off1 // off2 // off3 + obj.operands = [env.composer([env.cst(src.int(), 28), env.cst(off4, 4)])] obj.type = type_data_processing -@ispec("32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {15} ]", mnemonic="LDLCX", mode="Absolute") -@ispec("32<[ ~off2(4) 11 ~off3(4) ~off1(6) ~off4(4) a(4) {15} ]", mnemonic="LDUCX", mode="Absolute") + +@ispec( + "32<[ ~off2(4) 10 ~off3(4) ~off1(6) ~off4(4) a(4) {15} ]", + mnemonic="LDLCX", + mode="Absolute", +) +@ispec( + "32<[ ~off2(4) 11 ~off3(4) ~off1(6) ~off4(4) a(4) {15} ]", + mnemonic="LDUCX", + mode="Absolute", +) def tricore_ld(obj, off2, off3, off1, off4, a): - src = off1//off2//off3 - obj.operands = [env.composer([env.cst(src.int(),28),env.cst(off4,4)])] - obj.type = type_data_processing - -@ispec("32<[ ~off2(4) 10 0110 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_A", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0110 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_A", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0110 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_A", mode="Circular") -@ispec("32<[ ~off2(4) 00 0110 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_A", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0110 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_A", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0000 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_B", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0000 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_B", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0000 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_B", mode="Circular") -@ispec("32<[ ~off2(4) 00 0000 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_B", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0000 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_B", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0001 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_BU", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0001 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_BU", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0001 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_BU", mode="Circular") -@ispec("32<[ ~off2(4) 00 0001 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_BU", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0001 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_BU", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0101 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_D", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0101 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_D", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0101 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_D", mode="Circular") -@ispec("32<[ ~off2(4) 00 0101 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_D", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0101 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_D", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0111 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_DA", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0111 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_DA", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0111 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_DA", mode="Circular") -@ispec("32<[ ~off2(4) 00 0111 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_DA", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0111 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_DA", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0010 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_H", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0010 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_H", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0010 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_H", mode="Circular") -@ispec("32<[ ~off2(4) 00 0010 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_H", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0010 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_H", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0011 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_HU", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0011 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_HU", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0011 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_HU", mode="Circular") -@ispec("32<[ ~off2(4) 00 0011 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_HU", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0011 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_HU", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 1000 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_Q", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_Q", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_Q", mode="Circular") -@ispec("32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_Q", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_Q", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0100 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_W", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0100 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_W", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0100 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_W", mode="Circular") -@ispec("32<[ ~off2(4) 00 0100 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_W", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0100 ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_W", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 1000 ~off1(6) b(4) a(4) {49} ]", mnemonic="LEA", mode="Short-offset") + src = off1 // off2 // off3 + obj.operands = [env.composer([env.cst(src.int(), 28), env.cst(off4, 4)])] + obj.type = type_data_processing + + +@ispec( + "32<[ ~off2(4) 10 0110 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_A", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0110 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_A", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0110 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_A", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0110 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_A", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0110 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_A", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0000 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_B", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0000 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_B", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0000 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_B", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0000 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_B", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0000 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_B", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0001 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_BU", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0001 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_BU", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0001 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_BU", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0001 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_BU", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0001 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_BU", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0101 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_D", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0101 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_D", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0101 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_D", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0101 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_D", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0101 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_D", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0111 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_DA", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0111 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_DA", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0111 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_DA", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0111 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_DA", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0111 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_DA", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0010 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_H", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0010 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_H", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0010 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_H", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0010 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_H", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0010 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_H", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0011 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_HU", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0011 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_HU", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0011 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_HU", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0011 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_HU", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0011 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_HU", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 1000 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_Q", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_Q", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_Q", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_Q", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_Q", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0100 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_W", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0100 ~off1(6) b(4) a(4) {29} ]", + mnemonic="LD_W", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0100 ~off1(6) b(4) a(4) {29} ]", mnemonic="LD_W", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0100 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_W", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0100 ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_W", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 1000 ~off1(6) b(4) a(4) {49} ]", + mnemonic="LEA", + mode="Short-offset", +) def tricore_ld(obj, off2, off1, b, a): dst = env.D[a] - if obj.mnemonic=="LD_A" : dst = env.A[a] - elif obj.mnemonic=="LEA" : dst = env.A[a] - elif obj.mnemonic=="LD_D" : dst = env.E[a] - elif obj.mnemonic=="LDMST" : dst = env.E[a] - elif obj.mnemonic=="LD_DA" : dst = env.P[a] + if obj.mnemonic == "LD_A": + dst = env.A[a] + elif obj.mnemonic == "LEA": + dst = env.A[a] + elif obj.mnemonic == "LD_D": + dst = env.E[a] + elif obj.mnemonic == "LDMST": + dst = env.E[a] + elif obj.mnemonic == "LD_DA": + dst = env.P[a] obj.b = b src1 = env.A[b] - off10 = off1//off2 - src2 = env.cst(off10.int(-1),10) + off10 = off1 // off2 + src2 = env.cst(off10.int(-1), 10) obj.operands = [dst, src1, src2] if obj.mode == "Bit-Reverse": obj.operands.pop() obj.type = type_data_processing -@ispec("32<[ ~off2(4) 10 0110 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_A", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0110 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_A", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0110 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_A", mode="Circular") -@ispec("32<[ ~off2(4) 00 0110 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_A", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0110 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_A", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0000 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_B", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0000 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_B", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0000 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_B", mode="Circular") -@ispec("32<[ ~off2(4) 00 0000 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_B", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0000 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_B", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0101 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_D", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0101 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_D", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0101 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_D", mode="Circular") -@ispec("32<[ ~off2(4) 00 0101 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_D", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0101 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_D", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0111 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_DA", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0111 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_DA", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0111 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_DA", mode="Circular") -@ispec("32<[ ~off2(4) 00 0111 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_DA", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0111 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_DA", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0010 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_H", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0010 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_H", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0010 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_H", mode="Circular") -@ispec("32<[ ~off2(4) 00 0010 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_H", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0010 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_H", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 1000 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_Q", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_Q", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_Q", mode="Circular") -@ispec("32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_Q", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_Q", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0100 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_W", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0100 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_W", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0100 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_W", mode="Circular") -@ispec("32<[ ~off2(4) 00 0100 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_W", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0100 ~off1(6) b(4) a(4) {89} ]", mnemonic="ST_W", mode="Pre-increment") -@ispec("32<[ ~off2(4) 10 0001 ~off1(6) b(4) a(4) {49} ]", mnemonic="LDMST", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 0001 ~off1(6) b(4) a(4) {69} ]", mnemonic="LDMST", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 0001 ~off1(6) b(4) a(4) {69} ]", mnemonic="LDMST", mode="Circular") -@ispec("32<[ ~off2(4) 00 0001 ~off1(6) b(4) a(4) {49} ]", mnemonic="LDMST", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 0001 ~off1(6) b(4) a(4) {49} ]", mnemonic="LDMST", mode="Pre-increment") + +@ispec( + "32<[ ~off2(4) 10 0110 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_A", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0110 ~off1(6) b(4) a(4) {a9} ]", + mnemonic="ST_A", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0110 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_A", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0110 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_A", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0110 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_A", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0000 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_B", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0000 ~off1(6) b(4) a(4) {a9} ]", + mnemonic="ST_B", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0000 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_B", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0000 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_B", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0000 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_B", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0101 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_D", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0101 ~off1(6) b(4) a(4) {a9} ]", + mnemonic="ST_D", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0101 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_D", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0101 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_D", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0101 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_D", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0111 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_DA", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0111 ~off1(6) b(4) a(4) {a9} ]", + mnemonic="ST_DA", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0111 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_DA", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0111 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_DA", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0111 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_DA", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0010 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_H", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0010 ~off1(6) b(4) a(4) {a9} ]", + mnemonic="ST_H", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0010 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_H", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0010 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_H", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0010 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_H", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 1000 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_Q", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {a9} ]", + mnemonic="ST_Q", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_Q", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_Q", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_Q", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0100 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_W", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0100 ~off1(6) b(4) a(4) {a9} ]", + mnemonic="ST_W", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0100 ~off1(6) b(4) a(4) {a9} ]", mnemonic="ST_W", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0100 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_W", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0100 ~off1(6) b(4) a(4) {89} ]", + mnemonic="ST_W", + mode="Pre-increment", +) +@ispec( + "32<[ ~off2(4) 10 0001 ~off1(6) b(4) a(4) {49} ]", + mnemonic="LDMST", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 0001 ~off1(6) b(4) a(4) {69} ]", + mnemonic="LDMST", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 0001 ~off1(6) b(4) a(4) {69} ]", mnemonic="LDMST", mode="Circular" +) +@ispec( + "32<[ ~off2(4) 00 0001 ~off1(6) b(4) a(4) {49} ]", + mnemonic="LDMST", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 0001 ~off1(6) b(4) a(4) {49} ]", + mnemonic="LDMST", + mode="Pre-increment", +) def tricore_st(obj, off2, off1, b, a): dst = env.D[a] - if obj.mnemonic=="ST_A" : dst = env.A[a] - elif obj.mnemonic=="ST_D" : dst = env.E[a] - elif obj.mnemonic=="ST_DA" : dst = env.P[a] - elif obj.mnemonic=="LDMST" : dst = env.E[a] + if obj.mnemonic == "ST_A": + dst = env.A[a] + elif obj.mnemonic == "ST_D": + dst = env.E[a] + elif obj.mnemonic == "ST_DA": + dst = env.P[a] + elif obj.mnemonic == "LDMST": + dst = env.E[a] obj.b = b src1 = env.A[b] - off10 = off1//off2 - src2 = env.cst(off10.int(-1),10) + off10 = off1 // off2 + src2 = env.cst(off10.int(-1), 10) obj.operands = [src1, src2, dst] if obj.mode == "Bit-Reverse": obj.operands.pop() obj.type = type_data_processing -@ispec("32<[ ~off2(4) 10 1000 ~off1(6) b(4) a(4) {49} ]", mnemonic="SWAP_W", mode="Short-offset") -@ispec("32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {69} ]", mnemonic="SWAP_W", mode="Bit-reverse") -@ispec("32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {69} ]", mnemonic="SWAP_W", mode="Circular") -@ispec("32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {49} ]", mnemonic="SWAP_W", mode="Post-increment") -@ispec("32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {49} ]", mnemonic="SWAP_W", mode="Pre-increment") + +@ispec( + "32<[ ~off2(4) 10 1000 ~off1(6) b(4) a(4) {49} ]", + mnemonic="SWAP_W", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {69} ]", + mnemonic="SWAP_W", + mode="Bit-reverse", +) +@ispec( + "32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {69} ]", + mnemonic="SWAP_W", + mode="Circular", +) +@ispec( + "32<[ ~off2(4) 00 1000 ~off1(6) b(4) a(4) {49} ]", + mnemonic="SWAP_W", + mode="Post-increment", +) +@ispec( + "32<[ ~off2(4) 01 1000 ~off1(6) b(4) a(4) {49} ]", + mnemonic="SWAP_W", + mode="Pre-increment", +) def tricore_ld(obj, off2, off1, b, a): dst = env.D[a] src1 = env.P[b] - off10 = off1//off2 - src2 = env.cst(off10.int(-1),10) + off10 = off1 // off2 + src2 = env.cst(off10.int(-1), 10) obj.operands = [src1, src2, dst] obj.type = type_data_processing -@ispec("32<[ ~off2(4) 10 0100 ~off1(6) b(4) ---- {49} ]", mnemonic="LDLCX", mode="Short-offset") -@ispec("32<[ ~off2(4) 10 0101 ~off1(6) b(4) ---- {49} ]", mnemonic="LDUCX", mode="Short-offset") -@ispec("32<[ ~off2(4) 10 0110 ~off1(6) b(4) ---- {49} ]", mnemonic="STLCX", mode="Short-offset") -@ispec("32<[ ~off2(4) 10 0111 ~off1(6) b(4) ---- {49} ]", mnemonic="STUCX", mode="Short-offset") +@ispec( + "32<[ ~off2(4) 10 0100 ~off1(6) b(4) ---- {49} ]", + mnemonic="LDLCX", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 10 0101 ~off1(6) b(4) ---- {49} ]", + mnemonic="LDUCX", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 10 0110 ~off1(6) b(4) ---- {49} ]", + mnemonic="STLCX", + mode="Short-offset", +) +@ispec( + "32<[ ~off2(4) 10 0111 ~off1(6) b(4) ---- {49} ]", + mnemonic="STUCX", + mode="Short-offset", +) def tricore_ld(obj, off2, off1, b): src1 = env.A[b] - off10 = off1//off2 - src2 = env.cst(off10.int(-1),10) + off10 = off1 // off2 + src2 = env.cst(off10.int(-1), 10) obj.operands = [src1, src2] obj.type = type_data_processing -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {99} ]", mnemonic="LD_A", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {79} ]", mnemonic="LD_B", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {39} ]", mnemonic="LD_BU", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {09} ]", mnemonic="LD_H", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {b9} ]", mnemonic="LD_HU", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {19} ]", mnemonic="LD_W", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {d9} ]", mnemonic="LEA", mode="Long-offset") + +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {99} ]", + mnemonic="LD_A", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {79} ]", + mnemonic="LD_B", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {39} ]", + mnemonic="LD_BU", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {09} ]", + mnemonic="LD_H", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {b9} ]", + mnemonic="LD_HU", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {19} ]", + mnemonic="LD_W", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {d9} ]", + mnemonic="LEA", + mode="Long-offset", +) def tricore_ld(obj, off2, off3, off1, b, a): dst = env.D[a] - if obj.mnemonic in ("LD_A", "LEA"): dst = env.A[a] - if obj.mnemonic=="LD_D": dst = env.E[a] + if obj.mnemonic in ("LD_A", "LEA"): + dst = env.A[a] + if obj.mnemonic == "LD_D": + dst = env.E[a] src1 = env.A[b] - off16 = off1//off2//off3 - src2 = env.cst(off16.int(-1),32) + off16 = off1 // off2 // off3 + src2 = env.cst(off16.int(-1), 32) obj.operands = [dst, src1, src2] obj.type = type_data_processing -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {b5} ]", mnemonic="ST_A", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {e9} ]", mnemonic="ST_B", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {f9} ]", mnemonic="ST_H", mode="Long-offset") -@ispec("32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {59} ]", mnemonic="ST_W", mode="Long-offset") + +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {b5} ]", + mnemonic="ST_A", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {e9} ]", + mnemonic="ST_B", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {f9} ]", + mnemonic="ST_H", + mode="Long-offset", +) +@ispec( + "32<[ ~off2(4) ~off3(6) ~off1(6) b(4) a(4) {59} ]", + mnemonic="ST_W", + mode="Long-offset", +) def tricore_st(obj, off2, off3, off1, b, a): dst = env.D[a] - if obj.mnemonic=="ST_A": dst = env.A[a] - if obj.mnemonic=="ST_D": dst = env.E[a] + if obj.mnemonic == "ST_A": + dst = env.A[a] + if obj.mnemonic == "ST_D": + dst = env.E[a] src1 = env.A[b] - off16 = off1//off2//off3 - src2 = env.cst(off16.int(-1),32) + off16 = off1 // off2 // off3 + src2 = env.cst(off16.int(-1), 32) obj.operands = [src1, src2, dst] obj.type = type_data_processing + @ispec("16<[ const(8) {d8} ]", mnemonic="LD_A", mode="SC") @ispec("16<[ const(8) {58} ]", mnemonic="LD_W", mode="SC") def tricore_ld(obj, const): dst = env.D[15] - if obj.mnemonic=="LD_A": dst=env.A[15] + if obj.mnemonic == "LD_A": + dst = env.A[15] src1 = env.A[10] - src2 = env.cst(4*const,32) + src2 = env.cst(4 * const, 32) obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ const(8) {f8} ]", mnemonic="ST_A", mode="SC") @ispec("16<[ const(8) {78} ]", mnemonic="ST_W", mode="SC") def tricore_st(obj, const): dst = env.D[15] - if obj.mnemonic=="ST_A": dst=env.A[15] + if obj.mnemonic == "ST_A": + dst = env.A[15] src1 = env.A[10] - src2 = env.cst(4*const,32) + src2 = env.cst(4 * const, 32) obj.operands = [src1, src2, dst] obj.type = type_data_processing + @ispec("16<[ b(4) c(4) {d4} ]", mnemonic="LD_A", mode="SLR") @ispec("16<[ b(4) c(4) {c4} ]", mnemonic="LD_A", mode="Post-increment") @ispec("16<[ b(4) c(4) {14} ]", mnemonic="LD_BU", mode="SLR") @@ -1350,13 +2331,16 @@ def tricore_st(obj, const): @ispec("16<[ b(4) c(4) {44} ]", mnemonic="LD_W", mode="Post-increment") def tricore_ld(obj, b, c): dst = env.D[c] - if obj.mnemonic=="LD_A": dst = env.A[c] - if obj.mnemonic=="LD_D": dst = env.E[c] + if obj.mnemonic == "LD_A": + dst = env.A[c] + if obj.mnemonic == "LD_D": + dst = env.E[c] src1 = env.A[b] - src2 = env.cst(0,32) + src2 = env.cst(0, 32) obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ b(4) c(4) {f4} ]", mnemonic="ST_A", mode="SSR") @ispec("16<[ b(4) c(4) {e4} ]", mnemonic="ST_A", mode="Post-increment") @ispec("16<[ b(4) c(4) {b4} ]", mnemonic="ST_H", mode="SSR") @@ -1365,101 +2349,113 @@ def tricore_ld(obj, b, c): @ispec("16<[ b(4) c(4) {64} ]", mnemonic="ST_W", mode="Post-increment") def tricore_st(obj, b, c): dst = env.D[c] - if obj.mnemonic=="ST_A": dst = env.A[c] - if obj.mnemonic=="ST_D": dst = env.E[c] + if obj.mnemonic == "ST_A": + dst = env.A[c] + if obj.mnemonic == "ST_D": + dst = env.E[c] src1 = env.A[b] - src2 = env.cst(0,32) + src2 = env.cst(0, 32) obj.operands = [src1, src2, dst] obj.type = type_data_processing + @ispec("16<[ off(4) c(4) {c8} ]", mnemonic="LD_A", mode="SLRO") @ispec("16<[ off(4) c(4) {08} ]", mnemonic="LD_BU", mode="SLRO") @ispec("16<[ off(4) c(4) {88} ]", mnemonic="LD_H", mode="SLRO") @ispec("16<[ off(4) c(4) {48} ]", mnemonic="LD_W", mode="SLRO") def tricore_ld(obj, off, c): - dst = env.A[c] if obj.mnemonic=="LD_A" else env.D[c] + dst = env.A[c] if obj.mnemonic == "LD_A" else env.D[c] src1 = env.A[15] - src2 = env.cst(4*off,32) + src2 = env.cst(4 * off, 32) obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ off(4) c(4) {e8} ]", mnemonic="ST_A", mode="SSRO") @ispec("16<[ off(4) c(4) {a8} ]", mnemonic="ST_H", mode="SSRO") @ispec("16<[ off(4) c(4) {68} ]", mnemonic="ST_W", mode="SSRO") def tricore_st(obj, off, c): - dst = env.A[c] if obj.mnemonic=="ST_A" else env.D[c] + dst = env.A[c] if obj.mnemonic == "ST_A" else env.D[c] src1 = env.A[15] - src2 = env.cst(4*off,32) + src2 = env.cst(4 * off, 32) obj.operands = [src1, src2, dst] obj.type = type_data_processing + @ispec("16<[ b(4) off(4) {cc} ]", mnemonic="LD_A", mode="SRO") @ispec("16<[ b(4) off(4) {0c} ]", mnemonic="LD_BU", mode="SRO") @ispec("16<[ b(4) off(4) {8c} ]", mnemonic="LD_H", mode="SRO") @ispec("16<[ b(4) off(4) {4c} ]", mnemonic="LD_W", mode="SRO") def tricore_ld(obj, b, off): - dst = env.A[15] if obj.mnemonic=="LD_A" else env.D[15] + dst = env.A[15] if obj.mnemonic == "LD_A" else env.D[15] src1 = env.A[b] - src2 = env.cst(4*off,32) + src2 = env.cst(4 * off, 32) obj.operands = [dst, src1, src2] obj.type = type_data_processing + @ispec("16<[ b(4) off(4) {ec} ]", mnemonic="ST_A", mode="SRO") @ispec("16<[ b(4) off(4) {ac} ]", mnemonic="ST_H", mode="SRO") @ispec("16<[ b(4) off(4) {6c} ]", mnemonic="ST_W", mode="SRO") def tricore_st(obj, b, off): - dst = env.A[15] if obj.mnemonic=="ST_A" else env.D[15] + dst = env.A[15] if obj.mnemonic == "ST_A" else env.D[15] src1 = env.A[b] - src2 = env.cst(4*off,32) + src2 = env.cst(4 * off, 32) obj.operands = [src1, src2, dst] obj.type = type_data_processing + @ispec("32<[ c(4) const16(16) ---- {4d} ]", mnemonic="MFCR") def tricore_mfcr(obj, c, const16): - src = env.cst(const16,16) + src = env.cst(const16, 16) dst = env.D[c] obj.operands = [dst, src] obj.type = type_system + @ispec("32<[ ---- const16(16) a(4) {cd} ]", mnemonic="MTCR") def tricore_mtcr(obj, const16, a): - src1 = env.cst(const16,16) + src1 = env.cst(const16, 16) src2 = env.D[a] obj.operands = [src1, src2] obj.type = type_system + @ispec("32<[ c(4) const16(16) ---- {bb} ]", mnemonic="MOV_U") def tricore_mov(obj, c, const16): - src = env.cst(const16,32) + src = env.cst(const16, 32) dst = env.D[c] obj.operands = [dst, src] obj.type = type_data_processing + @ispec("32<[ c(4) ~const16(16) ---- {3b} ]", mnemonic="MOV") def tricore_mov(obj, c, const16): - src = env.cst(const16.int(-1),32) + src = env.cst(const16.int(-1), 32) dst = env.D[c] obj.operands = [dst, src] obj.type = type_data_processing + @ispec("32<[ c(4) const16(16) ---- {7b} ]", mnemonic="MOVH") def tricore_mov(obj, c, const16): - src = env.cst(const16,16) + src = env.cst(const16, 16) dst = env.D[c] obj.operands = [dst, src] obj.type = type_data_processing + @ispec("32<[ c(4) const16(16) ---- {91} ]", mnemonic="MOVH_A") def tricore_mov(obj, c, const16): - src = env.cst(const16,16) + src = env.cst(const16, 16) dst = env.A[c] obj.operands = [dst, src] obj.type = type_data_processing + @ispec("32<[ c(4) ~const16(16) ---- {fb} ]", mnemonic="MOV") def tricore_mov(obj, c, const16): - src = env.cst(const16.int(-1),64) + src = env.cst(const16.int(-1), 64) dst = env.E[c] obj.operands = [dst, src] obj.type = type_data_processing - diff --git a/amoco/arch/tricore/utils.py b/amoco/arch/tricore/utils.py index 60c9665..f18629d 100644 --- a/amoco/arch/tricore/utils.py +++ b/amoco/arch/tricore/utils.py @@ -1,35 +1,40 @@ # -*- coding: utf-8 -*- +from amoco.cas.expressions import composer, cst, tst -def byte_select(x,s): - return x.bytes(s,s+1) -def reflect(x,n): - L = [] - for b in range(n): - L.append(x[b:b+1]) +def byte_select(x, s): + return x.bytes(s, s + 1) + + +def reflect(x, n): + L = [x[b : b + 1] for b in range(n)] return composer(L) + def reverse16(x): - return reflect(x,16) + return reflect(x, 16) + def reverse_and_invert(x): - L = [] - for b in range(32): - L.append(~(x[b:b+1])) + L = [~(x[b : b + 1]) for b in range(32)] return composer(L) + def cdc_decrement(): pass + def round16(x): - return composer([cst(0,16),(x+0x8000)[16:32]]) + return composer([cst(0, 16), (x + 0x8000)[16:32]]) + + +def ssov(x, y): + max_pos = cst((1 << (y - 1)) - 1, y) + max_neg = cst(1, y) << (y - 1) + return tst(x > max_pos, max_pos, tst(x < max_neg, max_neg, x)) -def ssov(x,y): - max_pos = cst((1<<(y-1))-1,y) - max_neg = cst(1,y)<<(y-1) - return tst(x>max_pos,max_pos,tst(xmax_pos,max_pos,tst(x<0,cst(0,x.size),x)) +def suov(x, y): + max_pos = cst((1 << y) - 1, y) + return tst(x > max_pos, max_pos, tst(x < 0, cst(0, x.size), x)) diff --git a/amoco/arch/v850/asm.py b/amoco/arch/v850/asm.py index 2d5e449..d82dad3 100644 --- a/amoco/arch/v850/asm.py +++ b/amoco/arch/v850/asm.py @@ -4,8 +4,12 @@ # Copyright (C) 2018 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from amoco.arch.v850.env import * -from amoco.cas.utils import * +from amoco.arch.v850.env import sp, pc, CONDITION, Z, S, CY, OV, SAT, R, NP, EP +from amoco.arch.v850.env import CTPC, CTPSW, PSW, CTBP, EIPC, EIPSW, FEPC, FEPSW +from amoco.arch.v850.env import mem, ext, cst, tst, composer +from amoco.arch.v850.env import ID, bit0, bit1 +from amoco.cas.utils import AddWithCarry, SubWithBorrow + # ------------------------------------------------------------------------------ # low level functions : @@ -164,7 +168,7 @@ def i_MAC(i, fmap): r4 = i.misc["reg4"] r3 = i.misc["reg3"] off = fmap(composer([src3, R[r3 + 1]])) - r = fmap(src1 ** src2) + off + r = fmap(src1**src2) + off fmap[dst] = r[0:32] fmap[R[r4 + 1]] = r[32:64] @@ -177,7 +181,7 @@ def i_MUL(i, fmap): src1, src2, dst = i.operands if src1._is_cst: src1 = src1.signextend(32) - r = src1 ** src2 + r = src1**src2 fmap[src2] = r[0:32] fmap[dst] = r[32:64] @@ -201,7 +205,7 @@ def i_MULU(i, fmap): src1, src2, dst = i.operands if src1._is_cst: src1 = src1.zeroextend(32) - r = src1 ** src2 + r = src1**src2 fmap[src2] = r[0:32] fmap[dst] = r[32:64] @@ -283,7 +287,7 @@ def i_SUB(i, fmap): @_pc -def i_SUB(i, fmap): +def i_SUBI(i, fmap): src, dst = i.operands r, c, o = SubWithBorrow(fmap(src), fmap(dst)) fmap[Z] = r == 0 @@ -411,7 +415,7 @@ def i_CAXI(i, fmap): fmap[CY] = c fmap[OV] = o fmap[msrc] = tst(r == 0, fmap(dst), r) - fmap[dst] = adr + fmap[dst] = r @_pc @@ -557,7 +561,7 @@ def i_SBSF(i, fmap): fmap[S] = r < 0 fmap[CY] = c fmap[OV] = o - strue = r - cst(1, x.size) + strue = r - cst(1, r.size) sfalse = r fmap[dst] = tst(fmap(cond), strue, sfalse) diff --git a/amoco/arch/v850/cpu_v850e2s.py b/amoco/arch/v850/cpu_v850e2s.py index 5c2a7e2..dc9c660 100644 --- a/amoco/arch/v850/cpu_v850e2s.py +++ b/amoco/arch/v850/cpu_v850e2s.py @@ -1,15 +1,12 @@ # -*- coding: utf-8 -*- -from amoco.arch.v850.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.v850 import env +from amoco.arch.v850 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_v850 = type("instruction_v850", (instruction,), {}) -instruction_v850.set_uarch(uarch) from amoco.arch.v850.formats import v850_full @@ -20,10 +17,4 @@ disassemble = disassembler([spec], iclass=instruction_v850) - -def PC(state=None): - return pc - - -def get_data_endian(): - return 1 +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/v850/env.py b/amoco/arch/v850/env.py index 85c097c..d534de1 100644 --- a/amoco/arch/v850/env.py +++ b/amoco/arch/v850/env.py @@ -5,7 +5,9 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc, cst, bit1 +from amoco.cas.expressions import is_reg_pc, is_reg_stack, is_reg_flags +from amoco.cas.expressions import * # noqa: F403 # registers : # ----------- @@ -106,3 +108,5 @@ CONDITION_LE: ("le", ((S ^ OV) | Z) == 1), CONDITION_GT: ("gt", ((S ^ OV) | Z) == 0), } + +internals = {} diff --git a/amoco/arch/v850/formats.py b/amoco/arch/v850/formats.py index aeec47b..e79731d 100644 --- a/amoco/arch/v850/formats.py +++ b/amoco/arch/v850/formats.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from .env import * +from .env import pc, CONDITION from amoco.arch.core import Formatter from amoco.ui.render import Token, TokenListJoin @@ -83,7 +83,7 @@ def opcst(pos): def subc(i, pos=pos): o = i.operands[pos] assert o._is_cst - if o.sf == False: + if not o.sf: return [(Token.Constant, "0x%x" % o)] return [(Token.Constant, "%+d" % o)] diff --git a/amoco/arch/v850/spec_v850e2s.py b/amoco/arch/v850/spec_v850e2s.py index 68d1d9c..46b85dc 100644 --- a/amoco/arch/v850/spec_v850e2s.py +++ b/amoco/arch/v850/spec_v850e2s.py @@ -11,9 +11,16 @@ logger = Log(__name__) logger.debug("loading module") -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_system, +) from amoco.arch.v850 import env +# ruff: noqa: F811 + ISPECS = [] @@ -241,7 +248,7 @@ def v850_ld_st(obj, d, reg2, b, reg1, _size): @ispec("32<[ ~disp(16) 11 ~bnum(3) 111110 reg1(5) ]", mnemonic="TST1") def v850_bitwise(obj, disp, bnum, reg1): src = env.mem(env.R[reg1], 8, disp=disp.int(-1)) - obj.operands = [cst(bnum.int(), 3), src] + obj.operands = [env.cst(bnum.int(), 3), src] obj.type = type_data_processing @@ -328,8 +335,8 @@ def v850_ext3(obj, reg3, reg2, reg1): @ispec("32<[ reg4(4) 0011111 reg3(4) 0 reg2(5) 111111 reg1(5) ]", mnemonic="MACU") def v850_mac(obj, reg4, reg3, reg2, reg1): dst, src3, src2, src1 = env.R[reg4 << 1], env.R[reg3 << 1], env.R[reg2], env.R[reg1] - i.misc["reg4"] = reg4 << 1 - i.misc["reg3"] = reg3 << 1 + obj.misc["reg4"] = reg4 << 1 + obj.misc["reg3"] = reg3 << 1 obj.operands = [src1, src2, src3, dst] obj.type = type_data_processing @@ -433,6 +440,8 @@ def v850_prepare(obj, imm32, lh, ff, imm, lo): op3 = env.cst((imm & 0xFFFF) << 16, 32) elif ff == 0b11: op3 = env.cst(imm, 32) + else: + raise ValueError(ff) obj.operands = [L, env.cst(imm, 5), op3] obj.type = type_data_processing diff --git a/amoco/arch/w65c02/asm.py b/amoco/arch/w65c02/asm.py index dfce22f..ecd3e8f 100644 --- a/amoco/arch/w65c02/asm.py +++ b/amoco/arch/w65c02/asm.py @@ -4,512 +4,619 @@ # Copyright (C) 2017 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * -from amoco.cas.utils import * +from .env import sp, sp_, pc, mem, tst, cst, bit0, bit1 +from .env import C, A, A_, B, I, S, Z, V, N, D, P, Y, X +from .env import IRQ_VECTOR +from amoco.cas.utils import Sign + # ------------------------------------------------------------------------------ # helpers and decorators : def _push8(fmap, _x): - assert _x.size==8 + assert _x.size == 8 fmap[mem(sp_, 8)] = _x fmap[sp] = fmap(sp - 1) def _pop8(fmap, _l): - assert _l.size==8 + assert _l.size == 8 fmap[sp] = fmap(sp + 1) fmap[_l] = fmap(mem(sp_, 8)) + def _push16(fmap, _x): - assert _x.size==16 + assert _x.size == 16 fmap[sp] = fmap(sp - 1) fmap[mem(sp_, 16)] = _x fmap[sp] = fmap(sp - 1) + def _pop16(fmap, _l): - assert _l.size==16 + assert _l.size == 16 fmap[sp] = fmap(sp + 1) fmap[_l] = fmap(mem(sp_, 16)) fmap[sp] = fmap(sp + 1) + def __npc(i_xxx): def npc(ins, fmap): fmap[pc] = fmap(pc) + ins.length i_xxx(ins, fmap) + return npc -def overflow(res,a,v): - return ((res^a) & (res^v))[7:8] -def get_op_16(i,fmap): +def overflow(res, a, v): + return ((res ^ a) & (res ^ v))[7:8] + + +def get_op_16(i, fmap): return fmap(i.operands[0]).zeroextend(16) + # i_xxx is the translation of W65C02(S) instruction xxx. # ------------------------------------------------------------------------------ + @__npc -def i_ADC(i,fmap): +def i_ADC(i, fmap): c = fmap(C).zeroextend(16) a = fmap(A_) - v = get_op_16(i,fmap) - res = a+v+c - fmap[Z] = res==0 - fmap[V] = overflow(res,a,v) + v = get_op_16(i, fmap) + res = a + v + c + fmap[Z] = res == 0 + fmap[V] = overflow(res, a, v) fmap[N] = Sign(res) - c = ~D&((res&0xff00)!=0) + c = ~D & ((res & 0xFF00) != 0) a = fmap(A) - cond = tst(a[0:4]>9, a+6, a)[4:8]>9 - fmap[C] = tst(D&cond,bit1,c) + cond = tst(a[0:4] > 9, a + 6, a)[4:8] > 9 + fmap[C] = tst(D & cond, bit1, c) fmap[A] = res[0:8] + @__npc -def i_AND(i,fmap): - res = fmap(i.operands[0]&A) +def i_AND(i, fmap): + res = fmap(i.operands[0] & A) fmap[N] = res[7:8] - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[A] = res + @__npc -def i_ASL(i,fmap): +def i_ASL(i, fmap): dst = i.operands[0] - res = get_op_16(i,fmap)<<1 - fmap[C] = res[8:16]>0 + res = get_op_16(i, fmap) << 1 + fmap[C] = res[8:16] > 0 fmap[N] = res[7:8] - fmap[Z] = res[0:8]==0 + fmap[Z] = res[0:8] == 0 fmap[dst] = res[0:8] + @__npc -def i_BCC(i,fmap): +def i_BCC(i, fmap): reladdr = i.operands[0] - fmap[pc] = fmap(tst(C==bit0,pc+reladdr,pc)) + fmap[pc] = fmap(tst(C == bit0, pc + reladdr, pc)) + @__npc -def i_BCS(i,fmap): +def i_BCS(i, fmap): reladdr = i.operands[0] - fmap[pc] = fmap(tst(C==bit1,pc+reladdr,pc)) + fmap[pc] = fmap(tst(C == bit1, pc + reladdr, pc)) + @__npc -def i_BEQ(i,fmap): +def i_BEQ(i, fmap): reladdr = i.operands[0] - fmap[pc] = fmap(tst(Z==bit1,pc+reladdr,pc)) + fmap[pc] = fmap(tst(Z == bit1, pc + reladdr, pc)) + @__npc -def i_BIT(i,fmap): +def i_BIT(i, fmap): val = fmap(i.operands[0]) fmap[V] = val[6:7] fmap[N] = Sign(val) - fmap[Z] = (fmap(A)&val)==0 + fmap[Z] = (fmap(A) & val) == 0 + @__npc -def i_BMI(i,fmap): +def i_BMI(i, fmap): reladdr = i.operands[0] - fmap[pc] = fmap(tst(N==bit1,pc+reladdr,pc)) + fmap[pc] = fmap(tst(N == bit1, pc + reladdr, pc)) + @__npc -def i_BNE(i,fmap): +def i_BNE(i, fmap): reladdr = i.operands[0] - fmap[pc] = fmap(tst(Z==bit0,pc+reladdr,pc)) + fmap[pc] = fmap(tst(Z == bit0, pc + reladdr, pc)) + @__npc -def i_BPL(i,fmap): +def i_BPL(i, fmap): reladdr = i.operands[0] - fmap[pc] = fmap(tst(N==bit0,pc+reladdr,pc)) + fmap[pc] = fmap(tst(N == bit0, pc + reladdr, pc)) + @__npc -def i_BRA(i,fmap): +def i_BRA(i, fmap): reladdr = i.operands[0] - fmap[pc] = pc+reladdr + fmap[pc] = pc + reladdr + -def i_BRK(i,fmap): - _push16(fmap,fmap[pc]+1) - _push8(fmap,fmap(P|0x10)) +def i_BRK(i, fmap): + _push16(fmap, fmap[pc] + 1) + _push8(fmap, fmap(P | 0x10)) fmap[D] = bit0 fmap[B] = bit1 - fmap[pc] = fmap(mem(IRQ_VECTOR,16)) + fmap[pc] = fmap(mem(IRQ_VECTOR, 16)) + @__npc -def i_BVC(i,fmap): +def i_BVC(i, fmap): reladdr = i.operands[0] - fmap[pc] = fmap(tst(V==bit0,pc+reladdr,pc)) + fmap[pc] = fmap(tst(V == bit0, pc + reladdr, pc)) + @__npc -def i_BVS(i,fmap): +def i_BVS(i, fmap): reladdr = i.operands[0] - fmap[pc] = fmap(tst(V==bit1,pc+reladdr,pc)) + fmap[pc] = fmap(tst(V == bit1, pc + reladdr, pc)) + @__npc -def i_CLC(i,fmap): +def i_CLC(i, fmap): fmap[C] = bit0 + @__npc -def i_CLD(i,fmap): +def i_CLD(i, fmap): fmap[D] = bit0 + @__npc -def i_CLI(i,fmap): +def i_CLI(i, fmap): fmap[I] = bit0 + @__npc -def i_CLV(i,fmap): +def i_CLV(i, fmap): fmap[V] = bit0 + @__npc -def i_CMP(i,fmap): - v = get_op_16(i,fmap) +def i_CMP(i, fmap): + v = get_op_16(i, fmap) a = fmap(A) fmap[S] = (a.zeroextend(16) - v)[7:8] - fmap[C] = (a>=v[0:8]) - fmap[Z] = (a==v[0:8]) + fmap[C] = a >= v[0:8] + fmap[Z] = a == v[0:8] + @__npc -def i_CPX(i,fmap): - v = get_op_16(i,fmap) +def i_CPX(i, fmap): + v = get_op_16(i, fmap) a = fmap(X) fmap[S] = (a.zeroextend(16) - v)[7:8] - fmap[C] = (a>=v[0:8]) - fmap[Z] = (a==v[0:8]) + fmap[C] = a >= v[0:8] + fmap[Z] = a == v[0:8] + @__npc -def i_CPY(i,fmap): - v = get_op_16(i,fmap) +def i_CPY(i, fmap): + v = get_op_16(i, fmap) a = fmap(Y) fmap[S] = (a.zeroextend(16) - v)[7:8] - fmap[C] = (a>=v[0:8]) - fmap[Z] = (a==v[0:8]) + fmap[C] = a >= v[0:8] + fmap[Z] = a == v[0:8] + @__npc -def i_DEC(i,fmap): +def i_DEC(i, fmap): dst = src = i.operands[0] val = fmap(src) - res = val-1 + res = val - 1 fmap[dst] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_DEX(i,fmap): +def i_DEX(i, fmap): dst = src = X val = fmap(src) - res = val-1 + res = val - 1 fmap[dst] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_DEY(i,fmap): +def i_DEY(i, fmap): dst = src = Y val = fmap(src) - res = val-1 + res = val - 1 fmap[dst] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_EOR(i,fmap): +def i_EOR(i, fmap): val = fmap(i.operands[0]) - res = val^fmap(A_) - fmap[Z] = res==0 + res = val ^ fmap(A_) + fmap[Z] = res == 0 fmap[N] = Sign(res) fmap[A] = res + @__npc -def i_INC(i,fmap): +def i_INC(i, fmap): dst = src = i.operands[0] val = fmap(src) - res = val+1 + res = val + 1 fmap[dst] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_INX(i,fmap): +def i_INX(i, fmap): dst = src = X val = fmap(src) - res = val+1 + res = val + 1 fmap[dst] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_INY(i,fmap): +def i_INY(i, fmap): dst = src = X val = fmap(src) - res = val+1 + res = val + 1 fmap[dst] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) -def i_JMP(i,fmap): + +def i_JMP(i, fmap): fmap[pc] = fmap(i.operands[0]) + @__npc -def i_JSR(i,fmap): - _push16(fmap,fmap(pc-1)) # not an error ;) +def i_JSR(i, fmap): + _push16(fmap, fmap(pc - 1)) # not an error ;) fmap[pc] = fmap(i.operands[0]) + @__npc -def i_LDA(i,fmap): +def i_LDA(i, fmap): res = fmap(i.operands[0]) fmap[A] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_LDX(i,fmap): +def i_LDX(i, fmap): res = fmap(i.operands[0]) fmap[X] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_LDY(i,fmap): +def i_LDY(i, fmap): res = fmap(i.operands[0]) fmap[Y] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_LSR(i,fmap): +def i_LSR(i, fmap): dst = src = i.operands[0] val = fmap(src) fmap[C] = val[0:1] - res = val>>1 + res = val >> 1 fmap[dst] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_NOP(i,fmap): +def i_NOP(i, fmap): pass + @__npc -def i_ORA(i,fmap): - res = fmap(A|i.operands[0]) - fmap[Z] = res==0 +def i_ORA(i, fmap): + res = fmap(A | i.operands[0]) + fmap[Z] = res == 0 fmap[N] = Sign(res) fmap[A] = res + @__npc -def i_PHA(i,fmap): - _push8(fmap,fmap(A)) +def i_PHA(i, fmap): + _push8(fmap, fmap(A)) + @__npc -def i_PHP(i,fmap): - _push8(fmap,fmap(P|0x10)) +def i_PHP(i, fmap): + _push8(fmap, fmap(P | 0x10)) + @__npc -def i_PHY(i,fmap): - _push8(fmap,fmap(Y)) +def i_PHY(i, fmap): + _push8(fmap, fmap(Y)) + @__npc -def i_PHX(i,fmap): - _push8(fmap,fmap(X)) +def i_PHX(i, fmap): + _push8(fmap, fmap(X)) + @__npc -def i_PLA(i,fmap): - _pop8(fmap,A) +def i_PLA(i, fmap): + _pop8(fmap, A) a = fmap(A) - fmap[Z] = a==0 + fmap[Z] = a == 0 fmap[N] = Sign(a) + @__npc -def i_PLP(i,fmap): - _pop8(fmap,P) - fmap[P] = fmap(P)|0x20 +def i_PLP(i, fmap): + _pop8(fmap, P) + fmap[P] = fmap(P) | 0x20 + @__npc -def i_PLX(i,fmap): - _pop8(fmap,X) +def i_PLX(i, fmap): + _pop8(fmap, X) + @__npc -def i_PLY(i,fmap): - _pop8(fmap,Y) +def i_PLY(i, fmap): + _pop8(fmap, Y) + @__npc -def i_ROL(i,fmap): +def i_ROL(i, fmap): dst = i.operands[0] - val = get_op_16(i,fmap)<<1 - res = val|(fmap(C).zeroextend(16)) + val = get_op_16(i, fmap) << 1 + res = val | (fmap(C).zeroextend(16)) fmap[dst] = res[0:8] fmap[C] = val[8:9] - fmap[Z] = res[0:8]==0 + fmap[Z] = res[0:8] == 0 fmap[N] = Sign(res) + @__npc -def i_ROR(i,fmap): +def i_ROR(i, fmap): dst = i.operands[0] - val = get_op_16(i,fmap) - res = (val>>1)|(fmap(C).zeroextend(16)<<7) + val = get_op_16(i, fmap) + res = (val >> 1) | (fmap(C).zeroextend(16) << 7) fmap[dst] = res[0:8] fmap[C] = val[0:1] - fmap[Z] = res[0:8]==0 + fmap[Z] = res[0:8] == 0 fmap[N] = Sign(res) -def i_RTI(i,fmap): - _pop8(fmap,P) - _pop16(fmap,pc) -def i_RTS(i,fmap): - _pop16(fmap,pc) - fmap[pc] = fmap(pc)+1 +def i_RTI(i, fmap): + _pop8(fmap, P) + _pop16(fmap, pc) + + +def i_RTS(i, fmap): + _pop16(fmap, pc) + fmap[pc] = fmap(pc) + 1 + @__npc -def i_SBC(i,fmap): +def i_SBC(i, fmap): c = fmap(C).zeroextend(16) a = fmap(A_) - v = get_op_16(i,fmap)^0x00ff - res = a+v+c - fmap[Z] = res==0 - fmap[V] = overflow(res,a,v) + v = get_op_16(i, fmap) ^ 0x00FF + res = a + v + c + fmap[Z] = res == 0 + fmap[V] = overflow(res, a, v) fmap[N] = Sign(res) - c = ~D&((res&0xff00)!=0) - a = fmap(A)-0x66 - cond = tst(a[0:4]>9, a+6, a)[4:8]>9 - fmap[C] = tst(D&cond,bit1,c) + c = ~D & ((res & 0xFF00) != 0) + a = fmap(A) - 0x66 + cond = tst(a[0:4] > 9, a + 6, a)[4:8] > 9 + fmap[C] = tst(D & cond, bit1, c) fmap[A] = res[0:8] + @__npc -def i_SEC(i,fmap): +def i_SEC(i, fmap): fmap[C] = bit1 + @__npc -def i_SED(i,fmap): +def i_SED(i, fmap): fmap[D] = bit1 + @__npc -def i_SEI(i,fmap): +def i_SEI(i, fmap): fmap[I] = bit1 + @__npc -def i_STA(i,fmap): +def i_STA(i, fmap): fmap[i.operands[0]] = fmap(A) + @__npc -def i_STX(i,fmap): +def i_STX(i, fmap): fmap[i.operands[0]] = fmap(X) + @__npc -def i_STY(i,fmap): +def i_STY(i, fmap): fmap[i.operands[0]] = fmap(Y) + @__npc -def i_STZ(i,fmap): - fmap[i.operands[0]] = cst(0,8) +def i_STZ(i, fmap): + fmap[i.operands[0]] = cst(0, 8) + @__npc -def i_TAX(i,fmap): +def i_TAX(i, fmap): res = fmap(A) fmap[X] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_TAY(i,fmap): +def i_TAY(i, fmap): res = fmap(A) fmap[Y] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_TRB(i,fmap): +def i_TRB(i, fmap): raise NotImplementedError + @__npc -def i_TSB(i,fmap): +def i_TSB(i, fmap): raise NotImplementedError + @__npc -def i_TSX(i,fmap): +def i_TSX(i, fmap): res = fmap(sp) fmap[X] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_TXA(i,fmap): +def i_TXA(i, fmap): res = fmap(X) fmap[A] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) + @__npc -def i_TXS(i,fmap): +def i_TXS(i, fmap): res = fmap(X) fmap[sp] = res # no update of Z & N + @__npc -def i_TYA(i,fmap): +def i_TYA(i, fmap): res = fmap(Y) fmap[A] = res - fmap[Z] = res==0 + fmap[Z] = res == 0 fmap[N] = Sign(res) -def bbrx(n,i,fmap): + +def bbrx(n, i, fmap): cond = i.operands[0] reladdr = i.operands[1] - fmap[pc] = fmap(tst(cond[0:1]==bit0,pc+reladdr,pc)) + fmap[pc] = fmap(tst(cond[0:1] == bit0, pc + reladdr, pc)) + @__npc -def i_BBR0(i,fmap): - bbrx(0,i,fmap) +def i_BBR0(i, fmap): + bbrx(0, i, fmap) + + @__npc -def i_BBR1(i,fmap): - bbrx(1,i,fmap) +def i_BBR1(i, fmap): + bbrx(1, i, fmap) + + @__npc -def i_BBR2(i,fmap): - bbrx(2,i,fmap) +def i_BBR2(i, fmap): + bbrx(2, i, fmap) + + @__npc -def i_BBR3(i,fmap): - bbrx(3,i,fmap) +def i_BBR3(i, fmap): + bbrx(3, i, fmap) + + @__npc -def i_BBR4(i,fmap): - bbrx(4,i,fmap) +def i_BBR4(i, fmap): + bbrx(4, i, fmap) + + @__npc -def i_BBR5(i,fmap): - bbrx(5,i,fmap) +def i_BBR5(i, fmap): + bbrx(5, i, fmap) + + @__npc -def i_BBR6(i,fmap): - bbrx(6,i,fmap) +def i_BBR6(i, fmap): + bbrx(6, i, fmap) + + @__npc -def i_BBR7(i,fmap): - bbrx(7,i,fmap) +def i_BBR7(i, fmap): + bbrx(7, i, fmap) -def bbsx(n,i,fmap): - cond = mem(i.operands[0],8) + +def bbsx(n, i, fmap): + cond = mem(i.operands[0], 8) reladdr = i.operands[1] - fmap[pc] = fmap(tst(cond[0:1]==bit1,pc+reladdr,pc)) + fmap[pc] = fmap(tst(cond[0:1] == bit1, pc + reladdr, pc)) + @__npc -def i_BBS0(i,fmap): - bbsx(0,i,fmap) +def i_BBS0(i, fmap): + bbsx(0, i, fmap) + + @__npc -def i_BBS1(i,fmap): - bbsx(1,i,fmap) +def i_BBS1(i, fmap): + bbsx(1, i, fmap) + + @__npc -def i_BBS2(i,fmap): - bbsx(2,i,fmap) +def i_BBS2(i, fmap): + bbsx(2, i, fmap) + + @__npc -def i_BBS3(i,fmap): - bbsx(3,i,fmap) +def i_BBS3(i, fmap): + bbsx(3, i, fmap) + + @__npc -def i_BBS4(i,fmap): - bbsx(4,i,fmap) +def i_BBS4(i, fmap): + bbsx(4, i, fmap) + + @__npc -def i_BBS5(i,fmap): - bbsx(5,i,fmap) +def i_BBS5(i, fmap): + bbsx(5, i, fmap) + + @__npc -def i_BBS6(i,fmap): - bbsx(6,i,fmap) +def i_BBS6(i, fmap): + bbsx(6, i, fmap) + + @__npc -def i_BBS7(i,fmap): - bbsx(7,i,fmap) +def i_BBS7(i, fmap): + bbsx(7, i, fmap) + @__npc -def i_WAI(i,fmap): +def i_WAI(i, fmap): raise NotImplementedError + @__npc -def i_STP(i,fmap): +def i_STP(i, fmap): raise NotImplementedError - diff --git a/amoco/arch/w65c02/cpu.py b/amoco/arch/w65c02/cpu.py index f28da8e..bff83d4 100644 --- a/amoco/arch/w65c02/cpu.py +++ b/amoco/arch/w65c02/cpu.py @@ -1,15 +1,12 @@ # -*- coding: utf-8 -*- -from amoco.arch.w65c02.asm import * - -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.w65c02 import env +from amoco.arch.w65c02 import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_w65c02 = type("instruction_w65c02", (instruction,), {}) -instruction_w65c02.set_uarch(uarch) from amoco.arch.w65c02.formats import w65c02_full @@ -20,10 +17,4 @@ disassemble = disassembler([spec], iclass=instruction_w65c02) - -def PC(state=None): - return pc - - -def get_data_endian(): - return 1 # LE +cpu = CPU(env, asm, disassemble, env.pc) diff --git a/amoco/arch/w65c02/env.py b/amoco/arch/w65c02/env.py index 8488b6b..f11573b 100644 --- a/amoco/arch/w65c02/env.py +++ b/amoco/arch/w65c02/env.py @@ -5,7 +5,10 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc +from amoco.cas.expressions import is_reg_pc, is_reg_stack, is_reg_flags + +from amoco.cas.expressions import * # noqa: F403 # registers : @@ -15,31 +18,32 @@ X = reg("X", 8) Y = reg("Y", 8) -sp_ = reg("sp",16) -sp = slc(sp_,0,8,"SP") -P = reg("P",8) +sp_ = reg("sp", 16) +sp = slc(sp_, 0, 8, "SP") +P = reg("P", 8) -pc = reg("PC",16) +pc = reg("PC", 16) -pcl = slc(pc,0,8,"PCL") -pch = slc(pc,8,8,"PCH") +pcl = slc(pc, 0, 8, "PCL") +pch = slc(pc, 8, 8, "PCH") -C = slc(P,0,1,"C") # carry -Z = slc(P,1,1,"Z") # zero -I = slc(P,2,1,"I") # interrupt enable/disable(1) -D = slc(P,3,1,"D") # decimal mode -B = slc(P,4,1,"B") # brk command -V = slc(P,6,1,"V") # overflow -N = slc(P,7,1,"N") # negative +C = slc(P, 0, 1, "C") # carry +Z = slc(P, 1, 1, "Z") # zero +I = slc(P, 2, 1, "I") # interrupt enable/disable(1) +D = slc(P, 3, 1, "D") # decimal mode +B = slc(P, 4, 1, "B") # brk command +V = slc(P, 6, 1, "V") # overflow +N = slc(P, 7, 1, "N") # negative is_reg_pc(pc) is_reg_stack(sp_) is_reg_flags(P) -registers = [A,X,Y,sp_,P,pc] +registers = [A, X, Y, sp_, P, pc] A_ = A.zeroextend(16) X_ = A.zeroextend(16) Y_ = A.zeroextend(16) +internals = {} diff --git a/amoco/arch/w65c02/formats.py b/amoco/arch/w65c02/formats.py index 7c3e5b2..845bb67 100644 --- a/amoco/arch/w65c02/formats.py +++ b/amoco/arch/w65c02/formats.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- -from .env import * -from amoco.cas.expressions import regtype -from amoco.arch.core import Formatter, Token +from amoco.arch.core import Formatter +from amoco.ui.render import Token def mnemo(i): @@ -51,4 +50,3 @@ def opers_pcr(i): w65c02_full = Formatter(w65c02_full_formats) w65c02_full.default = format_default - diff --git a/amoco/arch/w65c02/spec.py b/amoco/arch/w65c02/spec.py index ab601ef..13dc200 100644 --- a/amoco/arch/w65c02/spec.py +++ b/amoco/arch/w65c02/spec.py @@ -6,7 +6,14 @@ from amoco.arch.w65c02 import env -from amoco.arch.core import * +from amoco.arch.core import ispec +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_system, +) + +# ruff: noqa: F811 # ------------------------------------------------------- # W65C02(S) instruction decoders @@ -14,6 +21,7 @@ ISPECS = [] + # absolute addressing: a # -------------------- @ispec("24<[a(16) {0c}]", mnemonic="TSB") @@ -42,23 +50,25 @@ @ispec("24<[a(16) {ed}]", mnemonic="SBC") @ispec("24<[a(16) {ee}]", mnemonic="INC") def w65c02_absolute(obj, a): - adr = env.cst(a,16) - if obj.mnemonic in ("JMP","JSR"): + adr = env.cst(a, 16) + if obj.mnemonic in ("JMP", "JSR"): obj.operands = [adr] obj.type = type_control_flow - obj.misc['ref'] = adr + obj.misc["ref"] = adr else: - obj.operands = [env.mem(adr,8)] + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # absolute indexed indirect : (a,x) # --------------------------------- @ispec("24<[a(16) {7c}]", mnemonic="JMP") def w65c02_aiix(obj, a): - adr = env.cst(a,16) + env.X_ - obj.operands = [env.mem(adr,16)] + adr = env.cst(a, 16) + env.X_ + obj.operands = [env.mem(adr, 16)] obj.type = type_control_flow + # absolute indexed with X : a,x # ----------------------------- @ispec("24<[a(16) {1d}]", mnemonic="ORA") @@ -79,10 +89,11 @@ def w65c02_aiix(obj, a): @ispec("24<[a(16) {fd}]", mnemonic="SBC") @ispec("24<[a(16) {fe}]", mnemonic="INC") def w65c02_aix(obj, a): - adr = env.cst(a,16) + env.X_ - obj.operands = [env.mem(adr,8)] + adr = env.cst(a, 16) + env.X_ + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # absolute indexed with Y : a,y # ------------------------- @ispec("24<[a(16) {19}]", mnemonic="ORA") @@ -95,18 +106,20 @@ def w65c02_aix(obj, a): @ispec("24<[a(16) {d9}]", mnemonic="CMP") @ispec("24<[a(16) {f9}]", mnemonic="SBC") def w65c02_aiy(obj, a): - adr = env.cst(a,16) + env.Y_ - obj.operands = [env.mem(adr,8)] + adr = env.cst(a, 16) + env.Y_ + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # absolute indirect: (a) # ------------------ @ispec("24<[a(16) {6c}]", mnemonic="JMP") def w65c02_ai(obj, a): - adr = env.cst(a,16) - obj.operands = [env.mem(adr,16)] + adr = env.cst(a, 16) + obj.operands = [env.mem(adr, 16)] obj.type = type_control_flow + # accumulator addressing : A # ------------------------ @ispec("8<[{0a}]", mnemonic="ASL") @@ -120,6 +133,7 @@ def w65c02_A(obj): obj.operands = [env.A] obj.type = type_data_processing + # immediate addressing: # # --------------------- @ispec("16<[c(8) {09}]", mnemonic="ORA") @@ -135,9 +149,10 @@ def w65c02_A(obj): @ispec("16<[c(8) {e0}]", mnemonic="CPX") @ispec("16<[c(8) {e9}]", mnemonic="SBC") def w65c02_immediate(obj, c): - obj.operands = [env.cst(c,8)] + obj.operands = [env.cst(c, 8)] obj.type = type_data_processing + # implied addressing : i # -------------------- @ispec("8<[{18}]", mnemonic="CLC", type=type_data_processing) @@ -163,6 +178,7 @@ def w65c02_immediate(obj, c): def w65c02_implied(obj): obj.operands = [] + # program counter relative: r # ------------------------- @ispec("16<[a(8) {10}]", mnemonic="BPL") @@ -175,11 +191,12 @@ def w65c02_implied(obj): @ispec("16<[a(8) {d0}]", mnemonic="BNE") @ispec("16<[a(8) {f0}]", mnemonic="BEQ") def w65c02_pcr(obj, a): - offset = env.cst(a,8).signextend(16) + offset = env.cst(a, 8).signextend(16) obj.operands = [offset] obj.misc["pc_ref"] = offset obj.type = type_control_flow + @ispec("24<[a(8) b(8) {0f}]", mnemonic="BBR0") @ispec("24<[a(8) b(8) {1f}]", mnemonic="BBR1") @ispec("24<[a(8) b(8) {2f}]", mnemonic="BBR2") @@ -197,12 +214,13 @@ def w65c02_pcr(obj, a): @ispec("24<[a(8) b(8) {ef}]", mnemonic="BBS6") @ispec("24<[a(8) b(8) {ff}]", mnemonic="BBS7") def w65c02_bb(obj, a, b): - offset = env.cst(a,8).signextend(16) - cond = env.cst(b,8) - obj.operands = [cond,offset] + offset = env.cst(a, 8).signextend(16) + cond = env.cst(b, 8) + obj.operands = [cond, offset] obj.misc["pc_ref"] = offset obj.type = type_control_flow + # stack addressing: s # ----------------- @ispec("8<[{00}]", mnemonic="BRK", type=type_control_flow) @@ -219,6 +237,7 @@ def w65c02_bb(obj, a, b): def w65c02_stack(obj): obj.operands = [] + # zero page addressing: zp # --------------------- @ispec("16<[a(8) {04}]", mnemonic="TSB") @@ -262,10 +281,11 @@ def w65c02_stack(obj): @ispec("16<[a(8) {e7}]", mnemonic="SMB6") @ispec("16<[a(8) {f7}]", mnemonic="SMB7") def w65c02_zp(obj, a): - adr = env.cst(a,16) - obj.operands = [env.mem(adr,8)] + adr = env.cst(a, 16) + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # zero page indexed indirect addressing: (zp,x) # -------------------------------------- @ispec("16<[a(8) {01}]", mnemonic="ORA") @@ -277,11 +297,12 @@ def w65c02_zp(obj, a): @ispec("16<[a(8) {c1}]", mnemonic="CMP") @ispec("16<[a(8) {e1}]", mnemonic="SBC") def w65c02_zpii(obj, a): - off = env.cst(a,16) + env.X_ - adr = env.mem(off,8).zeroextend(16) - obj.operands = [env.mem(adr,8)] + off = env.cst(a, 16) + env.X_ + adr = env.mem(off, 8).zeroextend(16) + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # zero page indexed with X : zp,x # -------------------------- @ispec("16<[a(8) {15}]", mnemonic="ORA") @@ -303,19 +324,21 @@ def w65c02_zpii(obj, a): @ispec("16<[a(8) {f5}]", mnemonic="SBC") @ispec("16<[a(8) {f6}]", mnemonic="INC") def w65c02_zpx(obj, a): - adr = env.cst(a,16) + env.X_ - obj.operands = [env.mem(adr,8)] + adr = env.cst(a, 16) + env.X_ + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # zero page indexed with Y : zp,y # -------------------------- @ispec("16<[a(8) {96}]", mnemonic="STX") @ispec("16<[a(8) {b6}]", mnemonic="LDX") def w65c02_zpy(obj, a): - adr = env.cst(a,16) + env.Y_ - obj.operands = [env.mem(adr,8)] + adr = env.cst(a, 16) + env.Y_ + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # zero page indirect: (zp) # ------------------- @ispec("16<[a(8) {12}]", mnemonic="ORA") @@ -327,10 +350,11 @@ def w65c02_zpy(obj, a): @ispec("16<[a(8) {d2}]", mnemonic="CMP") @ispec("16<[a(8) {f2}]", mnemonic="SBC") def w65c02_zpi(obj, a): - adr = env.mem(env.cst(a,16),16) - obj.operands = [env.mem(adr,8)] + adr = env.mem(env.cst(a, 16), 16) + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # zero page indirect indexed with Y: (zp),y # ---------------------------------- @ispec("16<[a(8) {11}]", mnemonic="ORA") @@ -342,10 +366,11 @@ def w65c02_zpi(obj, a): @ispec("16<[a(8) {d1}]", mnemonic="CMP") @ispec("16<[a(8) {f1}]", mnemonic="SBC") def w65c02_zpiy(obj, a): - adr = env.mem(env.cst(a,16),16) + env.Y_ - obj.operands = [env.mem(adr,8)] + adr = env.mem(env.cst(a, 16), 16) + env.Y_ + obj.operands = [env.mem(adr, 8)] obj.type = type_data_processing + # no-op (ignored): # ---------------- @ispec("8<[{02}]", mnemonic="NOP") @@ -395,4 +420,3 @@ def w65c02_zpiy(obj, a): def w65c02_nop(obj): obj.operands = [] obj.type = type_data_processing - diff --git a/amoco/arch/wasm/asm.py b/amoco/arch/wasm/asm.py index 6ba7177..afda4cf 100644 --- a/amoco/arch/wasm/asm.py +++ b/amoco/arch/wasm/asm.py @@ -4,7 +4,9 @@ # Copyright (C) 2021 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from amoco.arch.wasm.env import * +from amoco.arch.wasm.env import sp, stack_elt, op_ptr +from amoco.arch.wasm.env import WORD, mem, tst + # ------------------------------------------------------------------------------ # low level functions : @@ -156,12 +158,6 @@ def i_DW_OP_abs(i, fmap): _push_(fmap, result) -@__pc -def i_DW_OP_abs(i, fmap): - x = _pop_(fmap) - _push_(fmap, -x) - - @__pc def i_DW_OP_not(i, fmap): x = _pop_(fmap) diff --git a/amoco/arch/wasm/cpu.py b/amoco/arch/wasm/cpu.py index 1b1049f..b859e6f 100644 --- a/amoco/arch/wasm/cpu.py +++ b/amoco/arch/wasm/cpu.py @@ -1,14 +1,12 @@ # -*- coding: utf-8 -*- -from amoco.arch.wasm.asm import * - -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) +from amoco.arch.wasm import env +from amoco.arch.wasm import asm # import specifications: -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_wasm = type("instruction_wasm", (instruction,), {}) -instruction_wasm.set_uarch(uarch) from amoco.arch.wasm.formats import DW_full @@ -26,10 +24,4 @@ # If an instruction needs more bytes in must rely on the xdata API (see arch.core.) disassemble.maxlen = 16 - -def PC(state=None): - return op_ptr - - -def get_data_endian(): - return 1 +cpu = CPU(env, asm, disassemble, env.op_ptr) diff --git a/amoco/arch/wasm/env.py b/amoco/arch/wasm/env.py index 8cfe8c7..efe27fa 100644 --- a/amoco/arch/wasm/env.py +++ b/amoco/arch/wasm/env.py @@ -5,7 +5,10 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, sym +from amoco.cas.expressions import is_reg_pc, is_reg_stack + +from amoco.cas.expressions import * # noqa: F403 # symbols from libgcc/unwind-dw2.c : # ----------------------------------- @@ -22,24 +25,26 @@ registers = [op_ptr, sp, stack_elt] -i32 = sym("i32",0x7f,8) -i64 = sym("i64",0x7e,8) -f32 = sym("f32",0x7d,8) -f64 = sym("f64",0x7c,8) +i32 = sym("i32", 0x7F, 8) +i64 = sym("i64", 0x7E, 8) +f32 = sym("f32", 0x7D, 8) +f64 = sym("f64", 0x7C, 8) numtype = { - 0x7f:i32, - 0x7e:i64, - 0x7d:f32, - 0x7c:f64, + 0x7F: i32, + 0x7E: i64, + 0x7D: f32, + 0x7C: f64, } -funcref = sym("funcref",0x70,8) -externref = sym("externref",0x6f,8) +funcref = sym("funcref", 0x70, 8) +externref = sym("externref", 0x6F, 8) reftype = { - 0x70:funcref, - 0x6f:externref, + 0x70: funcref, + 0x6F: externref, } valtype = dict(numtype).update(reftype) + +internals = {} diff --git a/amoco/arch/wasm/formats.py b/amoco/arch/wasm/formats.py index 32395eb..f7d9ac3 100644 --- a/amoco/arch/wasm/formats.py +++ b/amoco/arch/wasm/formats.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- -from .env import * from amoco.arch.core import Formatter -from amoco.ui.render import Token, TokenListJoin +from amoco.ui.render import Token def mnemo(i): diff --git a/amoco/arch/wasm/spec.py b/amoco/arch/wasm/spec.py index 891be27..1248019 100644 --- a/amoco/arch/wasm/spec.py +++ b/amoco/arch/wasm/spec.py @@ -11,16 +11,19 @@ logger = Log(__name__) logger.debug("loading module") -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError +from amoco.arch.core import type_data_processing, type_control_flow, pack from amoco.arch.wasm import env from amoco.system.utils import read_leb128, read_uleb128, read_sleb128 +# ruff: noqa: F811 + ISPECS = [] @ispec("8>[ {00} ]", mnemonic="unreachable") @ispec("8>[ {01} ]", mnemonic="nop") -@ispec("8>[ {d1} ]", mnemonic="ref",action="is_null") +@ispec("8>[ {d1} ]", mnemonic="ref", action="is_null") @ispec("8>[ {1a} ]", mnemonic="drop") @ispec("8>[ {1b} ]", mnemonic="select") @ispec("8>[ {45} ]", mntype="i32", mnemonic="eqz") @@ -155,6 +158,7 @@ def dw_op_0(obj): obj.operands = [] obj.type = type_data_processing + @ispec("8>[ {0b} ]", mnemonic="end") @ispec("8>[ {0f} ]", mnemonic="return") @ispec("8>[ {05} ]", mnemonic="else") @@ -162,34 +166,38 @@ def dw_op_0(obj): obj.operands = [] obj.type = type_control_flow -@ispec("16>[ {d0} t(8) ]", mnemonic="ref",action="null") -def dw_reftype(obj,t): + +@ispec("16>[ {d0} t(8) ]", mnemonic="ref", action="null") +def dw_reftype(obj, t): if t in env.reftype: obj.operands = [env.reftype[t]] else: raise InstructionError(obj) obj.type = type_data_processing -@ispec("16>[ {3f} {00} ]", mnemonic="memory",action="size") -@ispec("16>[ {40} {00} ]", mnemonic="memory",action="grow") + +@ispec("16>[ {3f} {00} ]", mnemonic="memory", action="size") +@ispec("16>[ {40} {00} ]", mnemonic="memory", action="grow") def dw_memory(obj): obj.operands = [] obj.type = type_data_processing -def xdata_select(obj,**kargs): - addr = kargs['address'] - code = kargs['code'] + +def xdata_select(obj, **kargs): + addr = kargs["address"] + code = kargs["code"] obj.t = [] - addr = addr+len(obj.bytes) + addr = addr + len(obj.bytes) off = 0 for l in range(obj.x): - n, sz = read_leb128(code,1,addr+off) + n, sz = read_leb128(code, 1, addr + off) obj.t.append(n) off += sz obj.operands[0] = obj.t - obj.bytes += code[addr:addr+off] + obj.bytes += code[addr : addr + off] + -@ispec("*>[ {d2} ~data(*) ]", mnemonic="ref",action="func") +@ispec("*>[ {d2} ~data(*) ]", mnemonic="ref", action="func") @ispec("*>[ {1c} ~data(*) ] &", mnemonic="select") @ispec("*>[ {20} ~data(*) ]", mnemonic="local", action="get") @ispec("*>[ {21} ~data(*) ]", mnemonic="local", action="set") @@ -200,78 +208,81 @@ def xdata_select(obj,**kargs): @ispec("*>[ {26} ~data(*) ]", mnemonic="table", action="set") def dw_uleb128(obj, data): data = pack(data) - obj.x,blen = read_uleb128(data) + obj.x, blen = read_uleb128(data) obj.bytes += data[0:blen] obj.operands = [obj.x] obj.type = type_data_processing - if obj.mnemonic=="select": + if obj.mnemonic == "select": obj.xdata = xdata_select + @ispec("*>[ {41} ~data(*) ]", mnemonic="i32") @ispec("*>[ {42} ~data(*) ]", mnemonic="i64") @ispec("*>[ {43} ~data(*) ]", mnemonic="f32") @ispec("*>[ {44} ~data(*) ]", mnemonic="f64") def dw_uleb128(obj, data): data = pack(data) - obj.n,blen = read_uleb128(data) + obj.n, blen = read_uleb128(data) obj.bytes += data[0:blen] obj.operands = [obj.n] obj.action = "const" obj.type = type_data_processing + @ispec("*>[ {fc} ~data(*) ]", mnemonic="table") def dw_table(obj, data): data = pack(data) - v,blen = read_uleb128(data) + v, blen = read_uleb128(data) obj.bytes += data[0:blen] obj.type = type_data_processing - if v>17: + if v > 17: raise InstructionError(obj) - if v<8: - obj.mntype = "i32" if v<4 else "i64" - post = "f32" if v in (0,2,4,5) else "f64" - su = "_s" if v%2==0 else "_u" - obj.mnemonic = "trunc_sat_"+post+su - if v==10: + if v < 8: + obj.mntype = "i32" if v < 4 else "i64" + post = "f32" if v in (0, 2, 4, 5) else "f64" + su = "_s" if v % 2 == 0 else "_u" + obj.mnemonic = "trunc_sat_" + post + su + if v == 10: obj.mnemonic = "memory" obj.action = "copy" - if data[blen:blen+2]!=b'\x00\x00': + if data[blen : blen + 2] != b"\x00\x00": raise InstructionError(obj) - obj.bytes += data[blen:blen+2] + obj.bytes += data[blen : blen + 2] return - elif v==11: + elif v == 11: obj.mnemonic = "memory" obj.action = "fill" - if data[blen:blen+1]!=b'\x00': + if data[blen : blen + 1] != b"\x00": raise InstructionError(obj) - obj.bytes += data[blen:blen+1] + obj.bytes += data[blen : blen + 1] return data = data[blen:] - obj.x,blen1 = read_leb128(data,1,0) + obj.x, blen1 = read_leb128(data, 1, 0) obj.bytes += data[0:blen1] - if v==8: + if v == 8: obj.mnemonic = "memory" obj.action = "init" - if data[blen1:blen1+1]!=b'\x00': + if data[blen1 : blen1 + 1] != b"\x00": raise InstructionError(obj) - obj.bytes += data[blen1:blen1+1] - elif v==9: + obj.bytes += data[blen1 : blen1 + 1] + elif v == 9: obj.mnemonic = "data" obj.action = "drop" - elif v==12: + elif v == 12: obj.y = obj.x - obj.x,blen2 = read_leb128(data,1,blen1) - obj.bytes += data[blen1:blen1+blen2] + obj.x, blen2 = read_leb128(data, 1, blen1) + obj.bytes += data[blen1 : blen1 + blen2] obj.action = "init" - elif v==13: + elif v == 13: obj.mnemonic = "elem" obj.action = "drop" - elif v==14: - obj.y,blen2 = read_leb128(data,1,blen1) - obj.bytes += data[blen1:blen1+blen2] + elif v == 14: + obj.y, blen2 = read_leb128(data, 1, blen1) + obj.bytes += data[blen1 : blen1 + blen2] obj.action = "copy" else: - obj.action = {15:"grow",16:"size",17:"fill"}[v] + obj.action = {15: "grow", 16: "size", 17: "fill"}[v] + @ispec("*>[ {02} ~data(*) ]", mnemonic="block") @ispec("*>[ {03} ~data(*) ]", mnemonic="loop") @@ -286,59 +297,64 @@ def dw_op_block(obj, data): obj.bt = env.valtype[bt] obj.bytes += data[0:1] else: - obj.bt,blen = read_sleb128(data) + obj.bt, blen = read_sleb128(data) obj.bytes += data[0:blen] obj.operands = [obj.bt] obj.type = type_control_flow -def xdata_br_table(obj,**kargs): - addr = kargs['address'] - code = kargs['code'] + +def xdata_br_table(obj, **kargs): + addr = kargs["address"] + code = kargs["code"] obj.labels = [] addr += len(obj.bytes) off = 0 for l in range(obj.l): - n, sz = read_leb128(code,1,addr+off) + n, sz = read_leb128(code, 1, addr + off) obj.labels.append(n) off += sz - n, sz = read_leb128(code,1,addr+off) + n, sz = read_leb128(code, 1, addr + off) obj.default = n off += sz - obj.bytes += code[addr:addr+off] + obj.bytes += code[addr : addr + off] + @ispec("*>[ {0c} ~data(*) ]", mnemonic="br") @ispec("*>[ {0d} ~data(*) ]", mnemonic="br_if") @ispec("*>[ {0e} ~data(*) ] &", mnemonic="br_table") def dw_op_br(obj, data): data = pack(data) - obj.l,blen = read_uleb128(data) + obj.l, blen = read_uleb128(data) obj.bytes += data[0:blen] obj.operands = [obj.l] obj.type = type_control_flow - if obj.mnemonic=="br_table": + if obj.mnemonic == "br_table": obj.xdata = xdata_br_table -def xdata_call_indirect(obj,**kargs): - addr = kargs['address'] - code = kargs['code'] + +def xdata_call_indirect(obj, **kargs): + addr = kargs["address"] + code = kargs["code"] off = 0 - n, sz = read_leb128(code,1,addr+off) + n, sz = read_leb128(code, 1, addr + off) obj.y = n obj.operands.append(obj.y) off += sz - obj.bytes += code[addr:addr+off] + obj.bytes += code[addr : addr + off] + @ispec("*>[ {10} ~data(*) ]", mnemonic="call") @ispec("*>[ {11} ~data(*) ] &", mnemonic="call_indirect") def dw_op_call(obj, data): data = pack(data) - obj.x,blen = read_uleb128(data) + obj.x, blen = read_uleb128(data) obj.bytes += data[0:blen] obj.operands = [obj.x] obj.type = type_control_flow - if obj.mnemonic=="call_indirect": + if obj.mnemonic == "call_indirect": obj.xdata = xdata_call_indirect + @ispec("*>[ {28} ~data(*) ]", mnemonic="i32", action="load") @ispec("*>[ {29} ~data(*) ]", mnemonic="i64", action="load") @ispec("*>[ {2a} ~data(*) ]", mnemonic="f32", action="load") @@ -364,8 +380,8 @@ def dw_op_call(obj, data): @ispec("*>[ {3e} ~data(*) ]", mnemonic="i64", action="store32") def dw_memarg(obj, data): data = pack(data) - obj.a,blen1 = read_leb128(data,1,0) - obj.bytes += data[0:blen] - obj.o,blen2 = read_leb128(data,1,blen1) - obj.bytes += data[blen:blen1+blen2] + obj.a, blen1 = read_leb128(data, 1, 0) + obj.bytes += data[0:blen1] + obj.o, blen2 = read_leb128(data, 1, blen1) + obj.bytes += data[blen1 : blen1 + blen2] obj.type = type_data_processing diff --git a/amoco/arch/x64/asm.py b/amoco/arch/x64/asm.py index 7394555..1d7fcc1 100644 --- a/amoco/arch/x64/asm.py +++ b/amoco/arch/x64/asm.py @@ -4,13 +4,21 @@ # Copyright (C) 2006-2011 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * -from amoco.cas.utils import * +from .env import rsp, rbp, rip, rbx, rcx, rdx, rax, rsi, rdi, rflags +from .env import ebx, ecx, edx, eax, esi, edi +from .env import cx, dx, ax, al, ah +from .env import ss, cs, cr, r11 +from .env import cf, zf, of, af, pf, sf, df, bit0, bit1 +from .env import composer, tst, cst, top, mem, ext +from amoco.cas.utils import AddWithCarry, SubWithBorrow, ROL, ROR +from amoco.cas.utils import ROLWithCarry, RORWithCarry from amoco.logger import Log logger = Log(__name__) logger.debug("loading module") + + # ------------------------------------------------------------------------------ # utils : def push(fmap, x): @@ -459,7 +467,7 @@ def i_POP(i, fmap): def i_CALL(i, fmap): pc = fmap[rip] + i.length - fmap[rip] = pc # needed because op0 can depend on rip + fmap[rip] = pc # needed because op0 can depend on rip push(fmap, pc) op1 = fmap(i.operands[0]) op1 = op1.signextend(pc.size) @@ -875,14 +883,13 @@ def i_LEA(i, fmap): fmap[rip] = fmap[rip] + i.length op1 = i.operands[0] op2 = i.operands[1] - adr = op2.addr(fmap) - if op1.size == 32: - adr = adr[0:32].zeroextend(64) - op1 = op1.x - elif op1.size == 16: - adr = adr[0:16] - else: - adr = adr.zeroextend(64) + # "effective" address is agnostic of segmentation/pagination + # so we don't want to compute op2.addr(fmap) + adr = fmap(op2.a.base + op2.a.disp) + if op1.size > adr.size: + adr = adr.zeroextend(op1.size) + elif op1.size < adr.size: + adr = adr[0 : op1.size] fmap[op1] = adr @@ -1161,11 +1168,11 @@ def i_IMUL(i, fmap): if len(i.operands) == 1: src = i.operands[0] m, d = {8: (al, ah), 16: (ax, dx), 32: (eax, edx), 64: (rax, rdx)}[src.size] - r = fmap(m ** src) + r = fmap(m**src) elif len(i.operands) == 2: dst, src = i.operands m = d = dst - r = fmap(dst ** src) + r = fmap(dst**src) else: dst, src, imm = i.operands m = d = dst @@ -1184,7 +1191,7 @@ def i_MUL(i, fmap): fmap[rip] = fmap[rip] + i.length src = i.operands[0] m, d = {8: (al, ah), 16: (ax, dx), 32: (eax, edx), 64: (rax, rdx)}[src.size] - r = fmap(m ** src) + r = fmap(m**src) lo = r[0 : src.size] hi = r[src.size : r.size] fmap[cf] = hi != 0 @@ -1367,7 +1374,7 @@ def i_TZCNT(i, fmap): def i_BT(i, fmap): logger.warning("%s semantic is not defined" % i.mnemonic) fmap[rip] = fmap[rip] + i.length - #dst, src = i.operands + # dst, src = i.operands fmap[cf] = top(1) @@ -1820,6 +1827,6 @@ def i_XLATB(i, fmap): _b = fmap(mem(rbx + al.zeroextend(64), 8)) fmap[al] = _b + i_ENDBR32 = i_NOP i_ENDBR64 = i_NOP - diff --git a/amoco/arch/x64/cpu_x64.py b/amoco/arch/x64/cpu_x64.py index 7222cbb..f3a25d7 100644 --- a/amoco/arch/x64/cpu_x64.py +++ b/amoco/arch/x64/cpu_x64.py @@ -1,14 +1,11 @@ # -*- coding: utf-8 -*- -from amoco.arch.x64.asm import * +from amoco.arch.x64 import env +from amoco.arch.x64 import asm -# expose "microarchitecture" (instructions semantics) -uarch = dict(filter(lambda kv: kv[0].startswith("i_"), locals().items())) - -from amoco.arch.core import instruction, disassembler +from amoco.arch.core import instruction, disassembler, CPU instruction_x64 = type("instruction_x64", (instruction,), {}) -instruction_x64.set_uarch(uarch) from amoco.arch.x64.formats import IA32e_Intel, IA32e_ATT instruction_x64.set_formatter(IA32e_Intel) @@ -19,12 +16,18 @@ disassemble.maxlen = 15 -def PC(state=None): - return rip if state is None else state(ptr(rip,seg=cs)) +class CPU_ia32e(CPU): + def getPC(self, state=None): + return env.rip if state is None else state(env.ptr(env.rip, seg=env.cs)) + + def push(self, m, x): + asm.push(m, x) + + def pop(self, m, x): + asm.pop(m, x) -def get_data_endian(): - return 1 +cpu = CPU_ia32e(env, asm, disassemble) def configure(**kargs): diff --git a/amoco/arch/x64/env.py b/amoco/arch/x64/env.py index b01072b..b310080 100644 --- a/amoco/arch/x64/env.py +++ b/amoco/arch/x64/env.py @@ -5,7 +5,9 @@ # published under GPLv2 license # import expressions: -from amoco.cas.expressions import * +from amoco.cas.expressions import reg, slc +from amoco.cas.expressions import is_reg_pc, is_reg_flags, is_reg_other, is_reg_stack +from amoco.cas.expressions import * # noqa: F403 # 64bits registers : # ------------------- @@ -116,6 +118,7 @@ r15w = slc(r15, 0, 16, "r15w") r15l = slc(r15, 0, 8, "r15l") + # return R/M register (see ModR/M Byte encoding) : def getreg(i, size=32): return { @@ -217,8 +220,29 @@ def dr(num): internals = {"mode": 64} -registers = [rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi, - r8,r9,r10,r11,r12,r13,r14,r15, - rip, - eflags, - cs,ss,ds,es,fs,gs] +registers = [ + rax, + rcx, + rdx, + rbx, + rsp, + rbp, + rsi, + rdi, + r8, + r9, + r10, + r11, + r12, + r13, + r14, + r15, + rip, + eflags, + cs, + ss, + ds, + es, + fs, + gs, +] diff --git a/amoco/arch/x64/formats.py b/amoco/arch/x64/formats.py index e5b5060..bb8d047 100644 --- a/amoco/arch/x64/formats.py +++ b/amoco/arch/x64/formats.py @@ -39,12 +39,14 @@ def opers(i): s = [] for op in i.operands: if op._is_mem: - if i.misc['rip_rel']: - op = i.misc['rip_rel'] + if i.misc["rip_rel"]: + op = i.misc["rip_rel"] elif op.a.base._is_reg and op.a.base.etype & regtype.PC: if i.address is not None: - op = op.__class__(i.address+i.length+op.a.disp,op.size,seg=op.a.seg) - i.misc['rip_rel'] = op + op = op.__class__( + i.address + i.length + op.a.disp, op.size, seg=op.a.seg + ) + i.misc["rip_rel"] = op s.append((Token.Memory, deref(op))) elif op._is_cst: if i.misc["imm_ref"] is not None: diff --git a/amoco/arch/x64/spec_fpu.py b/amoco/arch/x64/spec_fpu.py index 76511e9..fbcde64 100644 --- a/amoco/arch/x64/spec_fpu.py +++ b/amoco/arch/x64/spec_fpu.py @@ -6,7 +6,11 @@ # spec_xxx files are providers for instruction objects. -from .utils import * +from . import env +from .utils import ispec_ia32, getModRM, InstructionError +from amoco.arch.core import type_data_processing, type_cpu_state + +# ruff: noqa: F811 # ------------------------------------------------------ # amoco x86 FPU (x87) instruction specs: diff --git a/amoco/arch/x64/spec_ia32e.py b/amoco/arch/x64/spec_ia32e.py index 2248741..6b3ac77 100644 --- a/amoco/arch/x64/spec_ia32e.py +++ b/amoco/arch/x64/spec_ia32e.py @@ -6,7 +6,25 @@ # spec_xxx files are providers for instruction objects. -from .utils import * +from . import env +from amoco.logger import Log + +logger = Log(__name__) + +from amoco.arch.core import pack +from amoco.arch.core import ( + type_data_processing, + type_control_flow, + type_system, + type_cpu_state, + type_undefined, + type_other, +) + +# ruff: noqa: F405 +# ruff: noqa: F811 + +from .utils import * # noqa: F403 # ------------------------------------------------------ # amoco IA32e instruction specs: @@ -24,7 +42,7 @@ def setpfx(obj, pfx, n): obj.misc.update((pfx,)) if obj.misc["pfx"] is None: obj.misc["pfx"] = [None] * 4 - if obj.misc["pfx"][n] != None: + if obj.misc["pfx"][n] is not None: logger.verbose("pfx %s grp %s redefined" % (pfx[0], n)) obj.misc["pfx"][n] = pfx[0] @@ -68,31 +86,51 @@ def prefix_REX(obj, B, X, R, W, _pfx): raise InstructionError(obj) obj.misc["REX"] = (W, R, X, B) + def precond_rep(obj): return obj.misc["rep"] + + def precond_norep(obj): return not obj.misc["rep"] + + def precond_opdsz(obj): return obj.misc["opdsz"] + + def precond_noopdsz(obj): return not obj.misc["opdsz"] + + def precond_opdsz_16(obj): size = obj.misc["opdsz"] - return size==16 + return size == 16 + + def precond_repne(obj): - return (obj.misc["repne"] and obj.misc["pfx"][0] == "repne") + return obj.misc["repne"] and obj.misc["pfx"][0] == "repne" + + def precond_norepne(obj): return not (obj.misc["repne"] and obj.misc["pfx"][0] == "repne") + + def precond_REX(obj): return obj.misc["REX"] + + def precond_W1(obj): - W=0 + W = 0 if obj.misc["REX"]: W, R, X, B = obj.misc["REX"] - return W==1 + return W == 1 + + def precond_32bits(obj): size = obj.misc["adrsz"] or 64 - return size==32 + return size == 32 + # IA32e opcodes: # ------------------------------------------------------ @@ -101,11 +139,14 @@ def precond_32bits(obj): # ------------- -@ispec_ia32(" 8>[ {90} ]", mnemonic="NOP", type=type_data_processing,__obj=precond_norep) -@ispec_ia32(" 8>[ {90} ]", mnemonic="PAUSE", type=type_cpu_state,__obj=precond_rep) +@ispec_ia32( + " 8>[ {90} ]", mnemonic="NOP", type=type_data_processing, __obj=precond_norep +) +@ispec_ia32(" 8>[ {90} ]", mnemonic="PAUSE", type=type_cpu_state, __obj=precond_rep) def ia32_nop(obj): pass + @ispec_ia32(" 8>[ {9b} ]", mnemonic="WAIT", type=type_other) @ispec_ia32(" 8>[ {c9} ]", mnemonic="LEAVE", type=type_data_processing) @ispec_ia32(" 8>[ {c3} ]", mnemonic="RET", type=type_control_flow) @@ -148,12 +189,28 @@ def ia32_nooperand(obj): @ispec_ia32(" 8>[ {cf} ]", mnemonic="IRETD", type=type_other) @ispec_ia32(" 8>[ {98} ]", mnemonic="CWDE", type=type_data_processing) @ispec_ia32(" 8>[ {99} ]", mnemonic="CDQ", type=type_data_processing) -@ispec_ia32(" 8>[ {cf} ]", mnemonic="IRET", type=type_other,__obj=precond_opdsz) -@ispec_ia32(" 8>[ {98} ]", mnemonic="CBW", type=type_data_processing,__obj=precond_opdsz) -@ispec_ia32(" 8>[ {99} ]", mnemonic="CWD", type=type_data_processing,__obj=precond_opdsz) -@ispec_ia32(" 8>[ {cf} ]", mnemonic="IRETQ", type=type_other,__obj=precond_W1) -@ispec_ia32(" 8>[ {98} ]", mnemonic="CDQE", type=type_data_processing,__obj=precond_REX) -@ispec_ia32(" 8>[ {99} ]", mnemonic="CQO", type=type_data_processing,__obj=precond_REX) +@ispec_ia32( + " 8>[ {cf} ]", mnemonic="IRET", type=type_other, __obj=precond_opdsz +) +@ispec_ia32( + " 8>[ {98} ]", + mnemonic="CBW", + type=type_data_processing, + __obj=precond_opdsz, +) +@ispec_ia32( + " 8>[ {99} ]", + mnemonic="CWD", + type=type_data_processing, + __obj=precond_opdsz, +) +@ispec_ia32(" 8>[ {cf} ]", mnemonic="IRETQ", type=type_other, __obj=precond_W1) +@ispec_ia32( + " 8>[ {98} ]", mnemonic="CDQE", type=type_data_processing, __obj=precond_REX +) +@ispec_ia32( + " 8>[ {99} ]", mnemonic="CQO", type=type_data_processing, __obj=precond_REX +) def ia32_nooperand(obj): if obj.misc["opdsz"]: if obj.mnemonic == "CWDE": @@ -178,28 +235,44 @@ def ia32_nooperand(obj): @ispec_ia32(" 8>[ {6d} ]", mnemonic="INSD", type=type_system) @ispec_ia32(" 8>[ {a4} ]", mnemonic="MOVSB", type=type_data_processing) @ispec_ia32(" 8>[ {a5} ]", mnemonic="MOVSD", type=type_data_processing) -@ispec_ia32(" 8>[ {a5} ]", mnemonic="MOVSQ", type=type_data_processing,__obj=precond_W1) -@ispec_ia32(" 8>[ {a5} ]", mnemonic="MOVSW", type=type_data_processing,__obj=precond_opdsz_16) +@ispec_ia32( + " 8>[ {a5} ]", mnemonic="MOVSQ", type=type_data_processing, __obj=precond_W1 +) +@ispec_ia32( + " 8>[ {a5} ]", mnemonic="MOVSW", type=type_data_processing, __obj=precond_opdsz_16 +) @ispec_ia32(" 8>[ {6e} ]", mnemonic="OUTSB", type=type_other) @ispec_ia32(" 8>[ {6f} ]", mnemonic="OUTSD", type=type_other) -@ispec_ia32(" 8>[ {6f} ]", mnemonic="OUTSQ", type=type_other,__obj=precond_W1) -@ispec_ia32(" 8>[ {6f} ]", mnemonic="OUTSW", type=type_other,__obj=precond_opdsz_16) +@ispec_ia32(" 8>[ {6f} ]", mnemonic="OUTSQ", type=type_other, __obj=precond_W1) +@ispec_ia32(" 8>[ {6f} ]", mnemonic="OUTSW", type=type_other, __obj=precond_opdsz_16) @ispec_ia32(" 8>[ {ac} ]", mnemonic="LODSB", type=type_other) @ispec_ia32(" 8>[ {ad} ]", mnemonic="LODSD", type=type_other) -@ispec_ia32(" 8>[ {ad} ]", mnemonic="LODSQ", type=type_other,__obj=precond_W1) -@ispec_ia32(" 8>[ {ad} ]", mnemonic="LODSW", type=type_other,__obj=precond_opdsz_16) +@ispec_ia32(" 8>[ {ad} ]", mnemonic="LODSQ", type=type_other, __obj=precond_W1) +@ispec_ia32(" 8>[ {ad} ]", mnemonic="LODSW", type=type_other, __obj=precond_opdsz_16) @ispec_ia32(" 8>[ {aa} ]", mnemonic="STOSB", type=type_data_processing) @ispec_ia32(" 8>[ {ab} ]", mnemonic="STOSD", type=type_data_processing) -@ispec_ia32(" 8>[ {ab} ]", mnemonic="STOSQ", type=type_data_processing,__obj=precond_W1) -@ispec_ia32(" 8>[ {ab} ]", mnemonic="STOSW", type=type_data_processing,__obj=precond_opdsz_16) +@ispec_ia32( + " 8>[ {ab} ]", mnemonic="STOSQ", type=type_data_processing, __obj=precond_W1 +) +@ispec_ia32( + " 8>[ {ab} ]", mnemonic="STOSW", type=type_data_processing, __obj=precond_opdsz_16 +) @ispec_ia32(" 8>[ {a6} ]", mnemonic="CMPSB", type=type_data_processing) @ispec_ia32(" 8>[ {a7} ]", mnemonic="CMPSD", type=type_data_processing) -@ispec_ia32(" 8>[ {a7} ]", mnemonic="CMPSQ", type=type_data_processing,__obj=precond_W1) -@ispec_ia32(" 8>[ {a7} ]", mnemonic="CMPSW", type=type_data_processing,__obj=precond_opdsz_16) +@ispec_ia32( + " 8>[ {a7} ]", mnemonic="CMPSQ", type=type_data_processing, __obj=precond_W1 +) +@ispec_ia32( + " 8>[ {a7} ]", mnemonic="CMPSW", type=type_data_processing, __obj=precond_opdsz_16 +) @ispec_ia32(" 8>[ {ae} ]", mnemonic="SCASB", type=type_data_processing) @ispec_ia32(" 8>[ {af} ]", mnemonic="SCASD", type=type_data_processing) -@ispec_ia32(" 8>[ {af} ]", mnemonic="SCASQ", type=type_data_processing,__obj=precond_W1) -@ispec_ia32(" 8>[ {af} ]", mnemonic="SCASW", type=type_data_processing,__obj=precond_opdsz_16) +@ispec_ia32( + " 8>[ {af} ]", mnemonic="SCASQ", type=type_data_processing, __obj=precond_W1 +) +@ispec_ia32( + " 8>[ {af} ]", mnemonic="SCASW", type=type_data_processing, __obj=precond_opdsz_16 +) def ia32_strings(obj): if obj.misc["rep"]: obj.type = type_control_flow @@ -214,6 +287,7 @@ def ia32_strings(obj): # 1 operand # ---------- + # imm8: @ispec_ia32("16>[ {cd} ib(8) ]", mnemonic="INT", type=type_control_flow) def ia32_imm8(obj, ib): @@ -236,7 +310,9 @@ def ia32_imm_rel(obj, ib): @ispec_ia32("16>[ {e3} cb(8) ]", mnemonic="JRCXZ", type=type_control_flow) -@ispec_ia32("16>[ {e3} cb(8) ]", mnemonic="JECXZ", type=type_control_flow, __obj=precond_32bits) +@ispec_ia32( + "16>[ {e3} cb(8) ]", mnemonic="JECXZ", type=type_control_flow, __obj=precond_32bits +) def ia32_cb8(obj, cb): size = obj.misc["adrsz"] or 64 if size == 32: @@ -280,6 +356,7 @@ def ia32_imm_rel(obj, data): # explicit register: + # r16/32 @ispec_ia32("*>[ reg(3) 0 1010 ]", mnemonic="PUSH") # 50 +rd @ispec_ia32("*>[ reg(3) 1 1010 ]", mnemonic="POP") # 58 +rd @@ -317,6 +394,7 @@ def ia32_push_pop(obj, _seg): # r/m operand: + # r/m8 @ispec_ia32("*>[ {fe} /0 ]", mnemonic="INC", type=type_data_processing) @ispec_ia32("*>[ {fe} /1 ]", mnemonic="DEC", type=type_data_processing) @@ -370,8 +448,8 @@ def ia32_rm64(obj, Mod, RM, data): op1, data = getModRM(obj, Mod, RM, data, REX) obj.operands = [op1] obj.misc["absolute"] = True - if obj.misc['segreg'] is env.ds: - setpfx(obj, ('notrack',True), 0) + if obj.misc["segreg"] is env.ds: + setpfx(obj, ("notrack", True), 0) obj.type = type_control_flow @@ -430,6 +508,7 @@ def ia32_imm_rel(obj, cc, data): # 2 operands # ---------- + # implicit ax/eax, r16/32 @ispec_ia32("8>[ rd(3) 0 1001 ]", mnemonic="XCHG") # 9x def ia32_xchg(obj, rd): @@ -818,11 +897,11 @@ def ia32_reg_32(obj, Mod, RM, REG, data): @ispec_ia32("*>[ {8b} /r ]", mnemonic="MOV") @ispec_ia32("*>[ {8d} /r ]", mnemonic="LEA") @ispec_ia32("*>[ {0f}{bc} /r ]", mnemonic="BSF") -@ispec_ia32("*>[ {0f}{bd} /r ]", mnemonic="BSR",__obj=precond_norep) -@ispec_ia32("*>[ {0f}{bd} /r ]", mnemonic="LZCNT",__obj=precond_rep) +@ispec_ia32("*>[ {0f}{bd} /r ]", mnemonic="BSR", __obj=precond_norep) +@ispec_ia32("*>[ {0f}{bd} /r ]", mnemonic="LZCNT", __obj=precond_rep) @ispec_ia32("*>[ {0f}{af} /r ]", mnemonic="IMUL") @ispec_ia32("*>[ {0f}{03} /r ]", mnemonic="LSL") -@ispec_ia32("*>[ {0f}{b8} /r ]", mnemonic="POPCNT",__obj=precond_norep) +@ispec_ia32("*>[ {0f}{b8} /r ]", mnemonic="POPCNT", __obj=precond_norep) def ia32_reg_32_inv(obj, Mod, RM, REG, data): op2, data = getModRM(obj, Mod, RM, data) op1 = getregR(obj, REG, op2.size) @@ -889,6 +968,7 @@ def ia32_SETcc(obj, cc, Mod, RM, REG, data): # 3 operands: # ----------- + # r16/32, r/m16/32, sign extended imm8 @ispec_ia32("*>[ {6b} /r ]", mnemonic="IMUL") def ia32_reg_rm_8(obj, Mod, RM, REG, data): @@ -947,7 +1027,7 @@ def ia32_movnti(obj, Mod, RM, REG, data): @ispec_ia32("*>[ {0f}{c7} /1 ]", mnemonic="CMPXCHG8B") -@ispec_ia32("*>[ {0f}{c7} /1 ]", mnemonic="CMPXCHG16B",__obj=precond_W1) +@ispec_ia32("*>[ {0f}{c7} /1 ]", mnemonic="CMPXCHG16B", __obj=precond_W1) def ia32_cmpxchg(obj, Mod, RM, data): op2, data = getModRM(obj, Mod, RM, data) if not op2._is_mem: @@ -971,9 +1051,15 @@ def ia32_longnop(obj, Mod, RM, data): @ispec_ia32("*>[ {0f}{ae} /2 ]", mnemonic="LDMXCSR", type=type_cpu_state) @ispec_ia32("*>[ {0f}{ae} /3 ]", mnemonic="STMXCSR", type=type_cpu_state) @ispec_ia32("*>[ {0f}{ae} /4 ]", mnemonic="XSAVE", type=type_cpu_state) -@ispec("*>[ {0f}{ae} RM(3) 101 Mod(2) ~data(*) ]", mnemonic="XRSTOR", type=type_cpu_state) -@ispec("*>[ {0f}{ae} RM(3) 011 Mod(2) ~data(*) ]", mnemonic="XSAVEOPT", type=type_cpu_state) -@ispec("*>[ {0f}{ae} RM(3) 111 Mod(2) ~data(*) ]", mnemonic="CLFLUSH", type=type_cpu_state) +@ispec( + "*>[ {0f}{ae} RM(3) 101 Mod(2) ~data(*) ]", mnemonic="XRSTOR", type=type_cpu_state +) +@ispec( + "*>[ {0f}{ae} RM(3) 011 Mod(2) ~data(*) ]", mnemonic="XSAVEOPT", type=type_cpu_state +) +@ispec( + "*>[ {0f}{ae} RM(3) 111 Mod(2) ~data(*) ]", mnemonic="CLFLUSH", type=type_cpu_state +) def ia32_xxx(obj, Mod, RM, data): op1, data = getModRM(obj, Mod, RM, data) if Mod == 0b11 and obj.mnemonic in ("XRSTOR", "XSAVEOPT", "CLFLUSH"): @@ -983,9 +1069,22 @@ def ia32_xxx(obj, Mod, RM, data): if obj.mnemonic == "CLFLUSH": obj.misc["opdsz"] = 8 -@ispec("*>[ {0f}{ae} RM(3) 101 11=Mod(2) ~data(*) ]", mnemonic="LFENCE", type=type_cpu_state) -@ispec("*>[ {0f}{ae} RM(3) 011 11=Mod(2) ~data(*) ]", mnemonic="MFENCE", type=type_cpu_state) -@ispec("*>[ {0f}{ae} RM(3) 111 11=Mod(2) ~data(*) ]", mnemonic="SFENCE", type=type_cpu_state) + +@ispec( + "*>[ {0f}{ae} RM(3) 101 11=Mod(2) ~data(*) ]", + mnemonic="LFENCE", + type=type_cpu_state, +) +@ispec( + "*>[ {0f}{ae} RM(3) 011 11=Mod(2) ~data(*) ]", + mnemonic="MFENCE", + type=type_cpu_state, +) +@ispec( + "*>[ {0f}{ae} RM(3) 111 11=Mod(2) ~data(*) ]", + mnemonic="SFENCE", + type=type_cpu_state, +) def ia32_xfence(obj, Mod, RM, data): obj.operands = [] @@ -1022,6 +1121,7 @@ def ia32_mov_dr(obj, Mod, REG, RM, data): # IN/OUT: + # implicit al/ax/eax register: @ispec_ia32("8>[ {ec} ]", mnemonic="IN") @ispec_ia32("8>[ {ee} ]", mnemonic="OUT") @@ -1075,7 +1175,7 @@ def ia32_movx(obj, Mod, RM, REG, data, _flg8): # MOVBE & CRC32: -@ispec_ia32("*>[ {0f}{38} s 000 1111 /r ]", mnemonic="MOVBE",__obj=precond_norepne) +@ispec_ia32("*>[ {0f}{38} s 000 1111 /r ]", mnemonic="MOVBE", __obj=precond_norepne) def ia32_movbe_crc32(obj, s, Mod, RM, REG, data): op1, data = getModRM(obj, Mod, RM, data) if not op1._is_mem: @@ -1084,7 +1184,10 @@ def ia32_movbe_crc32(obj, s, Mod, RM, REG, data): obj.operands = [op1, op2] if s else [op2, op1] obj.type = type_data_processing -@ispec_ia32("*>[ {0f}{38} s 000 1111 /r ]", mnemonic="CRC32", __obj=precond_repne) # (f2) 0f 38 f0/f1 + +@ispec_ia32( + "*>[ {0f}{38} s 000 1111 /r ]", mnemonic="CRC32", __obj=precond_repne +) # (f2) 0f 38 f0/f1 def ia32_movbe_crc32(obj, s, Mod, RM, REG, data): op1 = env.getreg(REG, 32) if s == 0: @@ -1093,6 +1196,7 @@ def ia32_movbe_crc32(obj, s, Mod, RM, REG, data): obj.operands = [op1, op2] obj.type = type_data_processing + # ENDBR (added by Intel in 2017 to protect against ROP) @ispec_ia32("32>[ {f3}{0f}{1e}{fb} ]", mnemonic="ENDBR32") @ispec_ia32("32>[ {f3}{0f}{1e}{fa} ]", mnemonic="ENDBR64") diff --git a/amoco/arch/x64/spec_sse.py b/amoco/arch/x64/spec_sse.py index a76eff9..b2d8d00 100644 --- a/amoco/arch/x64/spec_sse.py +++ b/amoco/arch/x64/spec_sse.py @@ -6,7 +6,18 @@ # spec_xxx files are providers for instruction objects. -from .utils import * +from . import env +from amoco.logger import Log + +logger = Log(__name__) + +from amoco.arch.core import pack +from amoco.arch.core import type_data_processing + +# ruff: noqa: F405 +# ruff: noqa: F811 + +from .utils import * # noqa: F403 # ------------------------------------------------------ # amoco SSE instruction specs: @@ -17,6 +28,7 @@ # NO pfx: # ------- + # (PACKED SINGLE) # xmm, xmm/m128 @ispec_ia32("*>[ {0f}{10} /r ]", mnemonic="MOVUPS") @@ -105,6 +117,7 @@ def sse_ps(obj, Mod, REG, RM, data): # (SCALAR SINGLE) + # xmm, xmm/m32 @ispec_ia32("*>[ {0f}{2e} /r ]", mnemonic="UCOMISS") @ispec_ia32("*>[ {0f}{2f} /r ]", mnemonic="COMISS") @@ -135,6 +148,7 @@ def sse_ps(obj, Mod, REG, RM, data): # moves: + # mmx, r/m32 no prefix # r/m32, mmx no prefix @ispec_ia32("*>[ {0f}{6e} /r ]", mnemonic="MOVD", _inv=False) @@ -420,6 +434,7 @@ def sse_pd(obj, Mod, REG, RM, data, _inv): # F2 prefixed: # ------------ + # xmm, xmm/m128 @ispec_ia32("*>[ {0f}{7c} /r ]", mnemonic="HADDPS") @ispec_ia32("*>[ {0f}{7d} /r ]", mnemonic="HSUBPS") @@ -551,6 +566,7 @@ def sse_sd(obj, Mod, REG, RM, data): # F3 prefixed: # ------------ + # (SCALAR SINGLE) # xmm, xmm/m32 @ispec_ia32("*>[ {0f}{10} /r ]", mnemonic="MOVSS") @@ -689,6 +705,7 @@ def sse_sd(obj, Mod, REG, RM, data): # Note that thos specs MUST APPEAR AFTER f2/f3 prefixes which have priority over 66, # so that 66-related specs will be matched after identical f2/f3 specs + # (PACKED DOUBLE) # xmm, xmm/m128 @ispec_ia32("*>[ {0f}{10} /r ]", mnemonic="MOVUPD") @@ -1034,6 +1051,7 @@ def sse_pd(obj, Mod, RM, data): # moves: + # xmm, xmm/m32 with 66 prefix # xmm/m32, xmm with 66 prefix @ispec_ia32("*>[ {0f}{6e} /r ]", mnemonic="MOVD", _inv=False) diff --git a/amoco/arch/x64/utils.py b/amoco/arch/x64/utils.py index d95fa0d..070cb09 100644 --- a/amoco/arch/x64/utils.py +++ b/amoco/arch/x64/utils.py @@ -8,7 +8,8 @@ from amoco.arch.x64 import env -from amoco.arch.core import * +from amoco.arch.core import ispec, InstructionError, Bits, pack + # for ia32 arch we want some specialized 'modrm' format # so we redefine ispec decorator here to allow /0-/7 and /r @@ -103,7 +104,7 @@ def getModRM(obj, Mod, RM, data, REX=None): b = env.getreg((B << 3) + sib[0:3].int(), adrsz) i = env.getreg((X << 3) + sib[3:6].int(), adrsz) ss = 1 << (sib[6:8].int()) - s = i * ss if not i.ref in ("rsp", "esp", "sp") else 0 + s = i * ss if i.ref not in ("rsp", "esp", "sp") else 0 else: s = 0 if adrsz != 16: diff --git a/amoco/arch/x86/asm.py b/amoco/arch/x86/asm.py index 393206a..2860f3d 100644 --- a/amoco/arch/x86/asm.py +++ b/amoco/arch/x86/asm.py @@ -4,15 +4,17 @@ # Copyright (C) 2006-2011 Axel Tillequin (bdcht3@gmail.com) # published under GPLv2 license -from .env import * -from .structs import * +# ruff: noqa: F405 +from .env import * # noqa: F403 from amoco.arch.x86 import hw -from amoco.cas.utils import * +from amoco.cas.utils import AddWithCarry, SubWithBorrow from amoco.logger import Log logger = Log(__name__) logger.debug("loading module") + + # ------------------------------------------------------------------------------ # utils : def push(fmap, x): @@ -22,7 +24,7 @@ def push(fmap, x): def pop(fmap, l, sz=0): v = fmap(mem(esp, l.size, seg=ss)) - nb = (sz//8) or l.length + nb = (sz // 8) or l.length fmap[esp] = fmap(esp + nb) fmap[l] = v @@ -51,6 +53,7 @@ def halfborrow(x, y, c=None): s, carry, o = SubWithBorrow(x[0:4], y[0:4], c) return carry + # ------------------------------------------------------------------------------ def i_AAA(i, fmap): fmap[eip] = fmap[eip] + i.length @@ -129,7 +132,7 @@ def i_AAM(i, fmap): def i_XLATB(i, fmap): fmap[eip] = fmap[eip] + i.length _table = bx if i.misc["opdsz"] == 16 else ebx - fmap[al] = fmap(mem(_table + al.zeroextend(_table.size), 8,seg=ds)) + fmap[al] = fmap(mem(_table + al.zeroextend(_table.size), 8, seg=ds)) # ------------------------------------------------------------------------------ @@ -154,23 +157,25 @@ def i_WAIT(i, fmap): def i_MWAIT(i, fmap): fmap[eip] = fmap[eip] + i.length + def i_ENTER(i, fmap): fmap[eip] = fmap[eip] + i.length - AllocSize = i.operands[0].v # required size in bytes (imm16) + AllocSize = i.operands[0].v # required size in bytes (imm16) NestingLevel = i.operands[1].v % 32 - opdsz = i.misc["opdsz"] or internals['mode'] - _bp = ebp if opdsz==32 else bp - _sp = esp if opdsz==32 else sp - push(fmap,fmap(_bp)) + opdsz = i.misc["opdsz"] or internals["mode"] + _bp = ebp if opdsz == 32 else bp + _sp = esp if opdsz == 32 else sp + push(fmap, fmap(_bp)) frame = fmap(_sp) - if NestingLevel>1: + if NestingLevel > 1: for _ in range(NestingLevel): - fmap[_bp] = fmap(_bp)-_bp.length - push(fmap,fmap(_bp)) - if NestingLevel>0: - push(fmap,frame) + fmap[_bp] = fmap(_bp) - _bp.length + push(fmap, fmap(_bp)) + if NestingLevel > 0: + push(fmap, frame) fmap[_bp] = frame - fmap[esp] = fmap(esp-AllocSize) + fmap[esp] = fmap(esp - AllocSize) + # LEAVE instruction is a shortcut for 'mov esp,ebp ; pop ebp ;' def i_LEAVE(i, fmap): @@ -180,9 +185,9 @@ def i_LEAVE(i, fmap): def i_RET(i, fmap): - opdsz = i.misc["opdsz"] or internals['mode'] - _ip = eip if opdsz==32 else ip - if len(i.operands)>0: + opdsz = i.misc["opdsz"] or internals["mode"] + _ip = eip if opdsz == 32 else ip + if len(i.operands) > 0: src = i.operands[0].v pop(fmap, _ip) fmap[esp] = fmap(esp) + src @@ -196,21 +201,21 @@ def i_HLT(i, fmap): # ------------------------------------------------------------------------------ + def _ins_(i, fmap, l): - adrsz = i.misc["adrsz"] or internals['mode'] - counter = ecx if adrsz==32 else cx - dst_r = edi if adrsz==32 else di - dst = fmap(ptr(dst_r,seg=es)) - direction = fmap(df) + adrsz = i.misc["adrsz"] or internals["mode"] + counter = ecx if adrsz == 32 else cx + dst_r = edi if adrsz == 32 else di + dst = fmap(ptr(dst_r, seg=es)) cnt = 1 if i.misc["rep"]: cnt = fmap(counter) - if cnt==0: + if cnt == 0: return - fmap[counter] = cst(0,counter.size) - src = hw.IO.get_port(fmap(dx)).In(env=fmap,dl=l) + fmap[counter] = cst(0, counter.size) + src = hw.IO.get_port(fmap(dx)).In(env=fmap, dl=l) fmap[dst] = src - off = cnt*l + off = cnt * l fmap[dst_r] = tst(fmap(df), fmap(dst_r) - off, fmap(dst_r) + off) fmap[eip] = fmap[eip] + i.length @@ -230,24 +235,25 @@ def i_INSD(i, fmap): # ------------------------------------------------------------------------------ from amoco.cas.blobs import blob_ptr, blob_comp + def _outs_(i, fmap, l): - adrsz = i.misc["adrsz"] or internals['mode'] - counter = ecx if adrsz==32 else cx - src_r = esi if adrsz==32 else si + adrsz = i.misc["adrsz"] or internals["mode"] + counter = ecx if adrsz == 32 else cx + src_r = esi if adrsz == 32 else si src_seg = i.misc["segreg"] if src_seg is None: src_seg = ds cnt = 1 if i.misc["rep"]: cnt = fmap(counter) - if cnt==0: + if cnt == 0: return - fmap[counter] = cst(0,counter.size) - src = ptr(src_r,seg=src_seg) + fmap[counter] = cst(0, counter.size) + src = ptr(src_r, seg=src_seg) direction = fmap(df) - data = blob_ptr(dl=l,a=src).as_array(N=cnt,d=direction) - off = cnt*l - hw.IO.get_port(fmap(dx)).Out(env=fmap,src=fmap(data)) + data = blob_ptr(dl=l, a=src).as_array(N=cnt, d=direction) + off = cnt * l + hw.IO.get_port(fmap(dx)).Out(env=fmap, src=fmap(data)) fmap[src_r] = tst(fmap(df), fmap(src_r) - off, fmap(src_r) + off) fmap[eip] = fmap[eip] + i.length @@ -267,7 +273,8 @@ def i_OUTSD(i, fmap): # ------------------------------------------------------------------------------ def i_INT3(i, fmap): fmap[eip] = fmap[eip] + i.length - do_interrupt_call(i,fmap,cst(3,8)) + do_interrupt_call(i, fmap, cst(3, 8)) + def i_CLC(i, fmap): fmap[eip] = fmap[eip] + i.length @@ -370,23 +377,23 @@ def i_SAHF(i, fmap): # ------------------------------------------------------------------------------ def _cmps_(i, fmap, l): counter = cx if i.misc["adrsz"] else ecx - dst = fmap(mem(edi, l * 8,seg=es)) + dst = fmap(mem(edi, l * 8, seg=es)) src_seg = i.misc["segreg"] if src_seg is None: src_seg = ds - src = fmap(mem(esi, l * 8,seg=src_seg)) + src = fmap(mem(esi, l * 8, seg=src_seg)) x, carry, overflow = SubWithBorrow(dst, src) if i.misc["rep"] or i.misc["repne"]: zv = bit0 if i.misc["rep"] else bit1 cnt = fmap(counter) - cond = (cnt==0)|(fmap(zf)==zv) - if cond==bit1: + cond = (cnt == 0) | (fmap(zf) == zv) + if cond == bit1: fmap[eip] = fmap[eip] + i.length return - elif cond==bit0: + elif cond == bit0: fmap[counter] = cnt - 1 else: - fmap[counter] = cst(0,counter.size) + fmap[counter] = cst(0, counter.size) fmap[edi] = top(32) fmap[esi] = top(32) return @@ -419,23 +426,23 @@ def i_CMPSD(i, fmap): # ------------------------------------------------------------------------------ def _scas_(i, fmap, l): - adrsz = i.misc["adrsz"] or internals['mode'] - counter = ecx if adrsz==32 else cx - dst_r = edi if adrsz==32 else di + adrsz = i.misc["adrsz"] or internals["mode"] + counter = ecx if adrsz == 32 else cx + dst_r = edi if adrsz == 32 else di a = fmap({1: al, 2: ax, 4: eax}[l]) - src = fmap(mem(edi, l * 8,seg=es)) + src = fmap(mem(edi, l * 8, seg=es)) x, carry, overflow = SubWithBorrow(a, src) if i.misc["rep"] or i.misc["repne"]: zv = bit0 if i.misc["rep"] else bit1 cnt = fmap(counter) - cond = (cnt==0)|(fmap(zf)==zv) - if cond==bit1: + cond = (cnt == 0) | (fmap(zf) == zv) + if cond == bit1: fmap[eip] = fmap[eip] + i.length return - elif cond==bit0: + elif cond == bit0: fmap[counter] = cnt - 1 else: - fmap[counter] = cst(0,counter.size) + fmap[counter] = cst(0, counter.size) fmap[dst_r] = top(dst_r.size) return else: @@ -463,10 +470,11 @@ def i_SCASD(i, fmap): # ------------------------------------------------------------------------------ + def _lods_(i, fmap, l): - adrsz = i.misc["adrsz"] or internals['mode'] - counter = ecx if adrsz==32 else cx - src_r = esi if adrsz==32 else si + adrsz = i.misc["adrsz"] or internals["mode"] + counter = ecx if adrsz == 32 else cx + src_r = esi if adrsz == 32 else si dst = {1: al, 2: ax, 4: eax}[l] src_seg = i.misc["segreg"] if src_seg is None: @@ -476,10 +484,10 @@ def _lods_(i, fmap, l): cnt = 1 if i.misc["rep"]: cnt = fmap(counter) - fmap[counter] = cst(0,counter.size) - data = fmap(blob_ptr(dt=l,a=src).as_array(cnt,direction)) + fmap[counter] = cst(0, counter.size) + data = fmap(blob_ptr(dt=l, a=src).as_array(cnt, direction)) fmap[dst] = data[-1] - off = cnt*l + off = cnt * l fmap[src_r] = tst(direction, fmap(src_r) - off, fmap(src_r) + off) fmap[eip] = fmap[eip] + i.length @@ -498,23 +506,24 @@ def i_LODSD(i, fmap): # ------------------------------------------------------------------------------ + def _stos_(i, fmap, l): - adrsz = i.misc["adrsz"] or internals['mode'] - counter = ecx if adrsz==32 else cx - dst_r = edi if adrsz==32 else di + adrsz = i.misc["adrsz"] or internals["mode"] + counter = ecx if adrsz == 32 else cx + dst_r = edi if adrsz == 32 else di src = fmap({1: al, 2: ax, 4: eax}[l]) - dst = fmap(ptr(edi,seg=es)) + dst = fmap(ptr(edi, seg=es)) direction = fmap(df) cnt = 1 fmap[eip] = fmap[eip] + i.length if i.misc["rep"]: cnt = fmap(counter) - if cnt==0: + if cnt == 0: return - fmap[counter] = cst(0,counter.size) - src = blob_comp(dt=l,el=src).as_array(cnt,direction) + fmap[counter] = cst(0, counter.size) + src = blob_comp(dt=l, el=src).as_array(cnt, direction) fmap[dst] = src - off = cnt*l + off = cnt * l fmap[dst_r] = tst(direction, fmap(dst_r) - off, fmap(dst_r) + off) @@ -532,11 +541,12 @@ def i_STOSD(i, fmap): # ------------------------------------------------------------------------------ -def _movs_(i,fmap,l): - adrsz = i.misc["adrsz"] or internals['mode'] - counter = ecx if adrsz==32 else cx - dst_r = edi if adrsz==32 else di - src_r = esi if adrsz==32 else si + +def _movs_(i, fmap, l): + adrsz = i.misc["adrsz"] or internals["mode"] + counter = ecx if adrsz == 32 else cx + dst_r = edi if adrsz == 32 else di + src_r = esi if adrsz == 32 else si dst = fmap(ptr(dst_r, seg=es)) src_seg = i.misc["segreg"] if src_seg is None: @@ -545,14 +555,14 @@ def _movs_(i,fmap,l): direction = fmap(df) cnt = 1 fmap[eip] = fmap[eip] + i.length - if i.misc['rep']: + if i.misc["rep"]: cnt = fmap(counter) - if cnt==0: + if cnt == 0: return - fmap[counter] = cst(0,counter.size) - src = blob_ptr(dt=l,a=src) - fmap[dst] = fmap(src.as_array(N=cnt,d=direction)) - off = cnt*l + fmap[counter] = cst(0, counter.size) + src = blob_ptr(dt=l, a=src) + fmap[dst] = fmap(src.as_array(N=cnt, d=direction)) + off = cnt * l src_v = fmap(src_r) dst_v = fmap(dst_r) fmap[src_r] = tst(direction, src_v - off, src_v + off) @@ -579,7 +589,7 @@ def i_IN(i, fmap): fmap[eip] = fmap[eip] + i.length op1 = i.operands[0] op2 = fmap(i.operands[1]) - data = hw.IO.get_port(op2).In(env=fmap,dl=op1.length) + data = hw.IO.get_port(op2).In(env=fmap, dl=op1.length) fmap[op1] = data @@ -587,7 +597,7 @@ def i_OUT(i, fmap): fmap[eip] = fmap[eip] + i.length op1 = fmap(i.operands[0]) op2 = fmap(i.operands[1]) - hw.IO.get_port(op1).Out(env=fmap,src=op2) + hw.IO.get_port(op1).Out(env=fmap, src=op2) # op1_src retreives fmap[op1] (op1 value): @@ -612,7 +622,7 @@ def i_POP(i, fmap): def i_CALL(i, fmap): opdsz = i.misc["opdsz"] or internals["mode"] - _ip = eip if opdsz==32 else ip + _ip = eip if opdsz == 32 else ip pc = fmap(_ip) + i.length fmap[_ip] = pc push(fmap, pc) @@ -624,12 +634,12 @@ def i_CALL(i, fmap): def i_CALLF(i, fmap): opdsz = i.misc["opdsz"] or internals["mode"] - _ip = eip if opdsz==32 else ip + _ip = eip if opdsz == 32 else ip pc = fmap(_ip) + i.length fmap[_ip] = pc push(fmap, fmap(cs).zeroextend(opdsz)) push(fmap, pc) - do_far_jump(i,fmap,reason="CALLF") + do_far_jump(i, fmap, reason="CALLF") def i_JMP(i, fmap): @@ -638,19 +648,20 @@ def i_JMP(i, fmap): op1 = fmap(i.operands[0]) op1 = op1.signextend(pc.size) target = pc + op1 if not i.misc["absolute"] else op1 - if internals["mode"]==16 and not i.misc["opdsz"]: - target = target&0xffff + if internals["mode"] == 16 and not i.misc["opdsz"]: + target = target & 0xFFFF fmap[eip] = target def i_JMPF(i, fmap): pc = fmap[eip] + i.length fmap[eip] = pc - do_far_jump(i,fmap) + do_far_jump(i, fmap) + def do_far_jump(i, fmap, reason="JMPF"): op1 = i.operands[0] - if internals['mode']==16: + if internals["mode"] == 16: if op1._is_ptr: selector = op1.seg offset = op1.base @@ -658,7 +669,7 @@ def do_far_jump(i, fmap, reason="JMPF"): desc = fmap(op1) sz = 32 if i.misc["opdsz"] else 16 offset = desc[0:sz] - selector = desc[sz:desc.size] + selector = desc[sz : desc.size] else: sz = 16 if i.misc["opdsz"] else 32 if op1._is_ptr: @@ -666,15 +677,15 @@ def do_far_jump(i, fmap, reason="JMPF"): offset = op1.base elif op1._is_mem: fa = fmap(op1) - selector = fa[sz:fa.size] + selector = fa[sz : fa.size] offset = fa[0:sz] - if fmap(PE)==bit0: + if fmap(PE) == bit0: # still in (un)real mode: fmap[cs] = selector fmap[eip] = offset.zeroextend(32) return # read cs descriptor from GDT or LDT - _e = read_descriptor(fmap,selector) + _e = read_descriptor(fmap, selector) if _e is None: logger.error(reason) fmap[eip] = top(32) @@ -682,186 +693,196 @@ def do_far_jump(i, fmap, reason="JMPF"): # and update mode, hidden parts (MSRs) and eip: if _e.s == DESC_SEGMENT: fmap[cs] = selector - load_segment(fmap,cs,_e) + load_segment(fmap, cs, _e) target = offset.zeroextend(32) fmap[eip] = target return else: - if _e.type==GATE_TASK: - tss_sel = cst(_e.base0,16) - _e = read_descriptor(fmap,tss_sel) + if _e.type == GATE_TASK: + tss_sel = cst(_e.base0, 16) + _e = read_descriptor(fmap, tss_sel) selector = tss_sel - if _e.type==DESC_TSS32_OK and fmap(PE)==bit1: - switch_tss32(fmap,_e, selector, reason) + if _e.type == DESC_TSS32_OK and fmap(PE) == bit1: + switch_tss32(fmap, _e, selector, reason) return - if _e.type==GATE_CALL32: - _g = gate_call_t(_e.pack()) - fmap[cs] = cst(_g.selector,16) - _e = read_descriptor(fmap,fmap(cs)) - if _e.type==DESC_SEGMENT: - load_segment(fmap,cs,_e) + if _e.type == GATE_CALL32: + _g = call_gate_t(_e.pack()) + fmap[cs] = cst(_g.selector, 16) + _e = read_descriptor(fmap, fmap(cs)) + if _e.type == DESC_SEGMENT: + load_segment(fmap, cs, _e) fmap[eip] = _g.offset() return - logger.warning("%s to unsupported descriptor",reason) + logger.warning("%s to unsupported descriptor", reason) + -def read_descriptor(fmap,selector): - if isinstance(selector,int): - selector = cst(selector,16) +def read_descriptor(fmap, selector): + if isinstance(selector, int): + selector = cst(selector, 16) _ti = selector[2:3] - offset = selector[3:16].zeroextend(32)*8 - if _ti==bit0: - Tmx = GDTR[0:16] + offset = selector[3:16].zeroextend(32) * 8 + if _ti == bit0: + Tmx = GDTR[0:16] # noqa: F841 Tbl = GDTR[16:48] - elif _ti==bit1: - Tmx = seglimit(LDTR) + elif _ti == bit1: + Tmx = seglimit(LDTR) # noqa: F841 Tbl = segbase(LDTR) - adr = Tbl+offset - desc = fmap(mem(adr,64)) + adr = Tbl + offset + desc = fmap(mem(adr, 64)) if desc._is_cst: _e = gdt_entry_t(desc.to_bytes()) return _e - logger.verbose("impossible to access descriptor "%desc) + logger.verbose("impossible to access descriptor " % desc) return None -def write_descriptor(fmap,selector,new_desc): - if isinstance(selector,int): - selector = cst(selector,16) - if isinstance(new_desc,bytes): + +def write_descriptor(fmap, selector, new_desc): + if isinstance(selector, int): + selector = cst(selector, 16) + if isinstance(new_desc, bytes): new_desc = gdt_entry_t(new_desc) _ti = selector[2:3] - offset = selector[3:16].zeroextend(32)*8 - if _ti==bit0: + offset = selector[3:16].zeroextend(32) * 8 + if _ti == bit0: Tmx = GDTR[0:16] Tbl = GDTR[16:48] - elif _ti==bit1: - Tmx = seglimit(LDTR) + elif _ti == bit1: + Tmx = seglimit(LDTR) # noqa: F841 Tbl = segbase(LDTR) - adr = fmap(Tbl)+offset - fmap._Mem_write(ptr(adr),new_desc.pack()) + # Tbl holds a virtual address if PG is 1 + # since we use _Mem_write, we must first translate + # it to its physical address: + adr = ptr(fmap(Tbl) + offset).eval(fmap) + fmap._Mem_write(adr, new_desc.pack()) + -def load_segment(fmap,seg,desc): +def load_segment(fmap, seg, desc): rpl = fmap(seg)[0:2] if desc is not None: dpl = desc.dpl - if rpl._is_cst and dpl<=(rpl.v): - fmap[segbase(seg)] = cst(desc.base(),32) - if seg==cs: - internals['mode'] = 32 if desc.d else 16 - internals['ring'] = dpl + if rpl._is_cst and dpl <= (rpl.v): + fmap[segbase(seg)] = cst(desc.base(), 32) + if seg == cs: + internals["mode"] = 32 if desc.d else 16 + internals["ring"] = dpl else: logger.error("load_segment privilege error") fmap[segbase(seg)] = top(32) else: - logger.warning("load_segment into %s: invalid descriptor"%seg) + logger.warning("load_segment into %s: invalid descriptor" % seg) -def switch_tss32(fmap,e,selector,reason): + +def switch_tss32(fmap, e, selector, reason): # qemu reads the new tss before saving the current one... # (see tcg/seg_helper.c:switch_tss_ra). # not sure why its done this way, may be saving the current # could erase the new one ?? anyway lets do it the same way. - new_tss = read_tss32(fmap,e) - save_tss32(fmap,reason) - if reason in ('JMPF', 'CALLF'): + new_tss = read_tss32(fmap, e) + save_tss32(fmap, reason) + if reason in ("JMPF", "CALLF"): # set BUSY flag in descriptor: e._v.type |= 2 - write_descriptor(fmap,selector,e) - if reason == 'CALLF': + write_descriptor(fmap, selector, e) + if reason == "CALLF": # new task is "nested" so it needs to remember link to current: - adr = cst(e.base(),32) - fmap[mem(adr,32,disp=new_tss.offset_of("link"))] = fmap(TR) + adr = cst(e.base(), 32) + fmap[mem(adr, 32, disp=new_tss.offset_of("link"))] = fmap(TR) # now change state to new TR & TSS: fmap[TR] = selector - load_segment(fmap,TR,e) - load_tss32(fmap,new_tss,reason) + load_segment(fmap, TR, e) + load_tss32(fmap, new_tss, reason) + -def read_tss32(fmap,e): - adr = cst(e.base(),32) +def read_tss32(fmap, e): + adr = cst(e.base(), 32) sz = tss32_entry_t.size() - if sz>e.limit()+1: - logger.error("tss segment too short @ %s"%adr) - tss_ = fmap(mem(adr,sz*8)) + if sz > e.limit() + 1: + logger.error("tss segment too short @ %s" % adr) + tss_ = fmap(mem(adr, sz * 8)) if tss_._is_cst: return tss32_entry_t(tss_.to_bytes()) return tss_ -def save_tss32(fmap,reason): + +def save_tss32(fmap, reason): old_tss = tss32_entry_t() - cur_tr = read_descriptor(fmap,fmap(TR)) - if reason in ('JMPF', 'IRET'): + cur_tr = read_descriptor(fmap, fmap(TR)) + if reason in ("JMPF", "IRET"): # clear BUSY flag for current tss descriptor: cur_tr._v.type &= ~2 - write_descriptor(fmap,fmap(TR),cur_tr) + write_descriptor(fmap, fmap(TR), cur_tr) old_eflags = fmap(eflags) - if reason == 'IRET': + if reason == "IRET": # clear nested flag since the interrupt task is now terminated NT_MASK = 0x00004000 - old_eflags &= (~NT_MASK) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("EIP"))] = fmap(eip) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("EFLAGS"))] = old_eflags - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("EAX"))] = fmap(eax) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("ECX"))] = fmap(ecx) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("EDX"))] = fmap(edx) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("EBX"))] = fmap(ebx) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("ESP"))] = fmap(esp) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("EBP"))] = fmap(ebp) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("ESI"))] = fmap(esi) - fmap[mem(segbase(TR),32,disp=old_tss.offset_of("EDI"))] = fmap(edi) - fmap[mem(segbase(TR),16,disp=old_tss.offset_of("ES"))] = fmap(es) - fmap[mem(segbase(TR),16,disp=old_tss.offset_of("CS"))] = fmap(cs) - fmap[mem(segbase(TR),16,disp=old_tss.offset_of("SS"))] = fmap(ss) - fmap[mem(segbase(TR),16,disp=old_tss.offset_of("DS"))] = fmap(ds) - fmap[mem(segbase(TR),16,disp=old_tss.offset_of("FS"))] = fmap(fs) - fmap[mem(segbase(TR),16,disp=old_tss.offset_of("GS"))] = fmap(gs) - #if reason == 'CALLF': - # fmap[mem(segbase(TR),16,disp=old_tss.offset_of("link"))] = fmap(TR) - -def load_tss32(fmap,tss_,reason): + old_eflags &= ~NT_MASK + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("EIP"))] = fmap(eip) + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("EFLAGS"))] = old_eflags + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("EAX"))] = fmap(eax) + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("ECX"))] = fmap(ecx) + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("EDX"))] = fmap(edx) + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("EBX"))] = fmap(ebx) + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("ESP"))] = fmap(esp) + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("EBP"))] = fmap(ebp) + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("ESI"))] = fmap(esi) + fmap[mem(segbase(TR), 32, disp=old_tss.offset_of("EDI"))] = fmap(edi) + fmap[mem(segbase(TR), 16, disp=old_tss.offset_of("ES"))] = fmap(es) + fmap[mem(segbase(TR), 16, disp=old_tss.offset_of("CS"))] = fmap(cs) + fmap[mem(segbase(TR), 16, disp=old_tss.offset_of("SS"))] = fmap(ss) + fmap[mem(segbase(TR), 16, disp=old_tss.offset_of("DS"))] = fmap(ds) + fmap[mem(segbase(TR), 16, disp=old_tss.offset_of("FS"))] = fmap(fs) + fmap[mem(segbase(TR), 16, disp=old_tss.offset_of("GS"))] = fmap(gs) + + +def load_tss32(fmap, tss_, reason): fmap[TS] = bit1 try: - if isinstance(tss_,tss32_entry_t): - fmap[cr3] = cst(tss_.CR3,32) - fmap[eip] = cst(tss_.EIP,32) - fmap[eax] = cst(tss_.EAX,32) - fmap[ecx] = cst(tss_.ECX,32) - fmap[edx] = cst(tss_.EDX,32) - fmap[ebx] = cst(tss_.EBX,32) - fmap[esp] = cst(tss_.ESP,32) - fmap[ebp] = cst(tss_.EBP,32) - fmap[esi] = cst(tss_.ESI,32) - fmap[edi] = cst(tss_.EDI,32) + if isinstance(tss_, tss32_entry_t): + fmap[cr3] = cst(tss_.CR3, 32) + mmu_cache.clear() + fmap[eip] = cst(tss_.EIP, 32) + fmap[eax] = cst(tss_.EAX, 32) + fmap[ecx] = cst(tss_.ECX, 32) + fmap[edx] = cst(tss_.EDX, 32) + fmap[ebx] = cst(tss_.EBX, 32) + fmap[esp] = cst(tss_.ESP, 32) + fmap[ebp] = cst(tss_.EBP, 32) + fmap[esi] = cst(tss_.ESI, 32) + fmap[edi] = cst(tss_.EDI, 32) # update segment regs: - fmap[es] = cst(tss_.ES,16) - fmap[cs] = cst(tss_.CS,16) - fmap[ss] = cst(tss_.SS,16) - fmap[ds] = cst(tss_.DS,16) - fmap[fs] = cst(tss_.FS,16) - fmap[gs] = cst(tss_.GS,16) - fmap[eflags] = cst(tss_.EFLAGS,32) - if reason == 'CALLF': + fmap[es] = cst(tss_.ES, 16) + fmap[cs] = cst(tss_.CS, 16) + fmap[ss] = cst(tss_.SS, 16) + fmap[ds] = cst(tss_.DS, 16) + fmap[fs] = cst(tss_.FS, 16) + fmap[gs] = cst(tss_.GS, 16) + fmap[eflags] = cst(tss_.EFLAGS, 32) + if reason == "CALLF": fmap[Nt] = bit1 # update LDTR: - if (ldt_s:=tss_.LDTR&(~7)): - fmap[LDTR] = cst(tss_.LDTR,16) + if ldt_s := tss_.LDTR & (~7): + fmap[LDTR] = cst(tss_.LDTR, 16) # read LDT descriptor in the GDT and update hidden parts: - e = read_descriptor(fmap,ldt_s) - if e is not None and e.type==DESC_LDT: - fmap[seglimit(LDTR)] = cst(e.limit(),16) - fmap[segbase(LDTR)] = cst(e.base(),32) - for seg in (es,cs,ss,ds,fs,gs): - desc = read_descriptor(fmap,fmap(seg)) - load_segment(fmap,seg,desc) - elif isinstance(tss_,mem): + e = read_descriptor(fmap, ldt_s) + if e is not None and e.type == DESC_LDT: + fmap[seglimit(LDTR)] = cst(e.limit(), 16) + fmap[segbase(LDTR)] = cst(e.base(), 32) + for seg in (es, cs, ss, ds, fs, gs): + desc = read_descriptor(fmap, fmap(seg)) + load_segment(fmap, seg, desc) + elif isinstance(tss_, mem): logger.verbose("can't find TSS segment") - raise NotImplemented - except: + raise NotImplementedError + except Exception: fmap[eip] = top(32) logger.verbose("error in TSS switch:\n") - logger.verbose("%s"%tss_) + logger.verbose("%s" % tss_) + def i_RETF(i, fmap): - opdsz = i.misc["opdsz"] or internals['mode'] - _ip = eip if opdsz==32 else ip - if len(i.operands)>0: + opdsz = i.misc["opdsz"] or internals["mode"] + _ip = eip if opdsz == 32 else ip + if len(i.operands) > 0: src = i.operands[0].v pop(fmap, _ip) pop(fmap, cs, sz=opdsz) @@ -869,8 +890,8 @@ def i_RETF(i, fmap): else: pop(fmap, _ip) pop(fmap, cs, sz=opdsz) - desc = read_descriptor(fmap,fmap(cs)) - load_segment(fmap,cs,desc) + desc = read_descriptor(fmap, fmap(cs)) + load_segment(fmap, cs, desc) # ------------------------------------------------------------------------------ @@ -913,12 +934,13 @@ def i_LTR(i, fmap): fmap[eip] = fmap[eip] + i.length selector = fmap(i.operands[0]) fmap[TR] = selector - _e = read_descriptor(fmap,selector) - load_segment(fmap,TR,_e) + _e = read_descriptor(fmap, selector) + load_segment(fmap, TR, _e) if _e is None: logger.verbose("error in task register descriptor") # now load the information associated to this selector in the GDT + ####################### @@ -953,84 +975,88 @@ def i_JCXZ(i, fmap): def i_INT(i, fmap): fmap[eip] = fmap[eip] + i.length op1 = i.operands[0] - do_interrupt_call(i,fmap,op1) + do_interrupt_call(i, fmap, op1) -def do_interrupt_call(i,fmap,op1): - if isinstance(op1,int): - op1 = cst(op1,8) - op1.sf=False + +def do_interrupt_call(i, fmap, op1): + if isinstance(op1, int): + op1 = cst(op1, 8) + op1.sf = False vector = op1.v - Tmx = fmap(IDTR[0:16]) + Tmx = fmap(IDTR[0:16]) # noqa: F841 Tbl = fmap(IDTR[16:48]) - if internals['mode']==16: - offset = vector<<2 - adr = Tbl+offset - push(fmap,fmap(eflags[0:16])) + if internals["mode"] == 16: + offset = vector << 2 + adr = Tbl + offset + push(fmap, fmap(eflags[0:16])) fmap[If] = bit0 fmap[tf] = bit0 - push(fmap,fmap(cs)) - push(fmap,fmap(ip)) - desc = fmap(mem(adr,32)) - fmap[cs] = desc[16:32] + push(fmap, fmap(cs)) + push(fmap, fmap(ip)) + desc = fmap(mem(adr, 32)) + fmap[cs] = desc[16:32] fmap[eip] = desc[0:16].zeroextend(32) return # 32-bit protected-mode: - offset = vector<<3 - adr = Tbl+offset - desc = fmap(mem(adr,64)) + offset = vector << 3 + adr = Tbl + offset + desc = fmap(mem(adr, 64)) if desc._is_cst: _e = idt_entry_t(desc.to_bytes()) else: - logger.error("INT %d"%vector) + logger.error("INT %d" % vector) fmap[eip] = top(32) return if _e.type == GATE_TASK: - tss_sel = cst(_e.selector,16) + tss_sel = cst(_e.selector, 16) # read TSS in GDT: - _e = read_descriptor(fmap,tss_sel) - if _e.type==DESC_TSS32_OK and fmap(PE)==bit1: - #switch task with nesting (aka like a far call): - #(nesting means that the TSS.link is updated with previous TR) - switch_tss32(fmap,_e,tss_sel,'CALLF') + _e = read_descriptor(fmap, tss_sel) + if _e.type == DESC_TSS32_OK and fmap(PE) == bit1: + # switch task with nesting (aka like a far call): + # (nesting means that the TSS.link is updated with previous TR) + switch_tss32(fmap, _e, tss_sel, "CALLF") return logger.error("interrupt task gate error (not a TSS?)") elif _e.type in (GATE_INTERRUPT32, GATE_TRAP32): - #trap or interrupt 32-bit gates: + # trap or interrupt 32-bit gates: if _e.type == GATE_INTERRUPT32: fmap[If] = bit0 fmap[tf] = bit0 fmap[Nt] = bit0 - selector = cst(_e.selector,16) - desc = read_descriptor(fmap,selector) + selector = cst(_e.selector, 16) + desc = read_descriptor(fmap, selector) if desc is not None and desc.s == DESC_SEGMENT: - if desc.dpl < internals['ring']: + if desc.dpl < internals["ring"]: # inter-privilege-level-interrupt: - logger.warning("inter-privilege-level-interrupt is not implemented yet...") + logger.warning( + "inter-privilege-level-interrupt is not implemented yet..." + ) else: # intra-privilege-level-interrupt: - push(fmap,fmap(eflags)) - push(fmap,fmap(cs).zeroextend(32)) - push(fmap,fmap(eip)) + push(fmap, fmap(eflags)) + push(fmap, fmap(cs).zeroextend(32)) + push(fmap, fmap(eip)) fmap[cs] = selector - load_segment(fmap,cs,desc) + load_segment(fmap, cs, desc) fmap[eip] = desc.offset() return - logger.error("INT %d runtime error",vector) + logger.error("INT %d runtime error", vector) + def i_IRET(i, fmap): - if internals['mode']==16 or not (fmap(Nt)==bit1): + if internals["mode"] == 16 or not (fmap(Nt) == bit1): i_RETF(i, fmap) - pop(fmap,eip) - pop(fmap,cs,sz=32) - pop(fmap,eflags) + pop(fmap, eip) + pop(fmap, cs, sz=32) + pop(fmap, eflags) def i_IRETD(i, fmap): - if internals['mode']==16 or not (fmap(Nt)==bit1): + if internals["mode"] == 16 or not (fmap(Nt) == bit1): i_RETF(i, fmap) - pop(fmap,eip) - pop(fmap,cs,sz=32) - pop(fmap,eflags) + pop(fmap, eip) + pop(fmap, cs, sz=32) + pop(fmap, eflags) def i_INC(i, fmap): @@ -1095,9 +1121,11 @@ def i_MOV(i, fmap): op2 = fmap(i.operands[1]) fmap[eip] = fmap[eip] + i.length fmap[op1] = op2 - if fmap(PE)==bit1 and (op1 in (cs,ds,es,ss,fs,gs)): - desc = read_descriptor(fmap,fmap(op1)) - load_segment(fmap,op1,desc) + if fmap(PE) == bit1 and (op1 in (cs, ds, es, ss, fs, gs)): + desc = read_descriptor(fmap, fmap(op1)) + load_segment(fmap, op1, desc) + if op1 in (cr0, cr3): + mmu_cache.clear() def i_MOVBE(i, fmap): @@ -1286,7 +1314,7 @@ def i_LEA(i, fmap): op2 = i.operands[1] # "effective" address is agnostic of segmentation/pagination # so we don't want to compute op2.addr(fmap) - adr = fmap(op2.a.base+op2.a.disp) + adr = fmap(op2.a.base + op2.a.disp) if op1.size > adr.size: adr = adr.zeroextend(op1.size) elif op1.size < adr.size: @@ -1519,11 +1547,11 @@ def i_IMUL(i, fmap): if len(i.operands) == 1: src = i.operands[0] m, d = {8: (al, ah), 16: (ax, dx), 32: (eax, edx)}[src.size] - r = fmap(m ** src) + r = fmap(m**src) elif len(i.operands) == 2: dst, src = i.operands m = d = dst - r = fmap(dst ** src) + r = fmap(dst**src) else: dst, src, imm = i.operands m = d = dst @@ -1540,7 +1568,7 @@ def i_MUL(i, fmap): fmap[eip] = fmap[eip] + i.length src = i.operands[0] m, d = {8: (al, ah), 16: (ax, dx), 32: (eax, edx)}[src.size] - r = fmap(m ** src) + r = fmap(m**src) lo = r[0 : src.size] hi = r[src.size : r.size] fmap[d] = hi @@ -1560,6 +1588,7 @@ def i_DIV(i, fmap): fmap[d] = r_[0 : d.size] fmap[m] = q_[0 : m.size] + def i_IDIV(i, fmap): fmap[eip] = fmap[eip] + i.length src = i.operands[0] @@ -1615,26 +1644,26 @@ def i_CLTS(i, fmap): def i_CPUID(i, fmap): fmap[eip] = fmap[eip] + i.length - #EAX 0 returns maximum input eax value and vendor id: + # EAX 0 returns maximum input eax value and vendor id: v = fmap(eax) if v._is_cst: - if v==0: - fmap[eax] = cst(0x02,32) - fmap[ebx] = cst(struct.unpack('