├── .gitignore ├── py-irsim ├── .gitignore ├── README.md ├── ui_mainwindow.py ├── irsim.py └── resources_rc.py ├── mips-sim ├── .gitignore ├── Makefile ├── test │ ├── fib.S │ └── fact.S └── src │ ├── main.cc │ ├── MipsEmu.h │ ├── MipsEmu.cc │ └── instr.h └── cxx-irsim ├── test ├── ret.ir ├── infinite-loop.ir ├── infinite-memory.ir ├── call.ir ├── wrong.ir ├── add-next.ir ├── local.ir ├── add.ir ├── sgn-next.ir ├── sgn.ir ├── fact.ir ├── div.ir ├── array.ir ├── if-fault.ir └── fault.ir ├── Makefile ├── main.cc ├── irsim.h └── irsim.cc /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | workspace/ 3 | test.sh 4 | -------------------------------------------------------------------------------- /py-irsim/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /mips-sim/.gitignore: -------------------------------------------------------------------------------- 1 | *.[oO] 2 | *.elf 3 | *.bin 4 | -------------------------------------------------------------------------------- /cxx-irsim/test/ret.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | RETURN #12 3 | -------------------------------------------------------------------------------- /cxx-irsim/test/infinite-loop.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | LABEL loop : 3 | GOTO loop 4 | RETURN #0 5 | -------------------------------------------------------------------------------- /cxx-irsim/test/infinite-memory.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | DEC v1 10240 3 | t1 := CALL main 4 | RETURN #0 5 | -------------------------------------------------------------------------------- /cxx-irsim/test/call.ir: -------------------------------------------------------------------------------- 1 | FUNCTION f : 2 | PARAM v1 3 | t1 := v1 4 | RETURN t1 5 | FUNCTION main : 6 | ARG #100 7 | t := CALL f 8 | WRITE t 9 | RETURN #0 10 | -------------------------------------------------------------------------------- /cxx-irsim/test/wrong.ir: -------------------------------------------------------------------------------- 1 | FUNCTION process : 2 | v_dummy := #9996 3 | RETURN #0 4 | 5 | FUNCTION main : 6 | v_i := #0 7 | LABEL l6 : 8 | t72 := CALL process 9 | WRITE v_h 10 | v_h := #9 11 | v_i := v_i + #1 12 | WRITE v_h 13 | IF v_i <= #1 GOTO l6 14 | RETURN #0 15 | -------------------------------------------------------------------------------- /py-irsim/README.md: -------------------------------------------------------------------------------- 1 | # irsim written in python2 2 | 3 | decompiled from official \*.pyc 4 | 5 | ``` 6 | sudo pip install uncompyle6 7 | uncompyle6 irsim.pyc > irsim.py 8 | uncompyle6 ui_mainwindow.pyc > ui_mainwindow.py 9 | uncompyle6 resources_rc.pyc > resources_rc.py 10 | ``` 11 | -------------------------------------------------------------------------------- /cxx-irsim/test/add-next.ir: -------------------------------------------------------------------------------- 1 | FUNCTION add : 2 | PARAM v1 3 | PARAM v2 4 | t1 := v1 + v2 5 | RETURN t1 6 | FUNCTION main : 7 | DEC v3 8 8 | t9 := &v3 9 | *t9 := #1 10 | t12 := &v3 + #4 11 | *t12 := #2 12 | ARG *t9 13 | ARG *t12 14 | t14 := CALL add 15 | v2 := t14 16 | WRITE v2 17 | RETURN #0 18 | -------------------------------------------------------------------------------- /cxx-irsim/test/local.ir: -------------------------------------------------------------------------------- 1 | FUNCTION test : 2 | PARAM p1 3 | t1 := p1 4 | IF t1 == #1 GOTO label1 5 | RETURN #0 6 | 7 | LABEL label1 : 8 | ARG #0 9 | dummy := CALL test 10 | WRITE t1 11 | RETURN #0 12 | 13 | FUNCTION main : 14 | ARG #1 15 | dummy := CALL test 16 | WRITE dummy 17 | RETURN #0 18 | 19 | -------------------------------------------------------------------------------- /cxx-irsim/test/add.ir: -------------------------------------------------------------------------------- 1 | FUNCTION add : 2 | PARAM v1 3 | t2 := *v1 4 | t7 := v1 + #4 5 | t3 := *t7 6 | t1 := t2 + t3 7 | RETURN t1 8 | FUNCTION main : 9 | DEC v3 8 10 | t9 := &v3 11 | *t9 := #1 12 | t12 := &v3 + #4 13 | *t12 := #2 14 | ARG &v3 15 | t14 := CALL add 16 | v2 := t14 17 | WRITE v2 18 | RETURN #0 19 | -------------------------------------------------------------------------------- /cxx-irsim/test/sgn-next.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | READ t1 3 | v1 := t1 4 | t2 := #0 5 | IF v1 > t2 GOTO label1 6 | IF v1 < t2 GOTO label2 7 | WRITE t2 8 | GOTO label3 9 | LABEL label1 : 10 | t3 := #1 11 | WRITE t3 12 | GOTO label3 13 | LABEL label2 : 14 | t6 := #-1 15 | WRITE t6 16 | LABEL label3 : 17 | RETURN t2 18 | -------------------------------------------------------------------------------- /cxx-irsim/test/sgn.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | READ t1 3 | v1 := t1 4 | t2 := #0 5 | IF v1 > t2 GOTO label1 6 | GOTO label2 7 | LABEL label1 : 8 | t3 := #1 9 | WRITE t3 10 | GOTO label3 11 | LABEL label2 : 12 | t4 := #0 13 | IF v1 < t4 GOTO label4 14 | GOTO label5 15 | LABEL label4 : 16 | t5 := #1 17 | t6 := #0 - t5 18 | WRITE t6 19 | GOTO label6 20 | LABEL label5 : 21 | t7 := #0 22 | WRITE t7 23 | LABEL label6 : 24 | LABEL label3 : 25 | t8 := #0 26 | RETURN t8 27 | -------------------------------------------------------------------------------- /cxx-irsim/test/fact.ir: -------------------------------------------------------------------------------- 1 | FUNCTION fact : 2 | PARAM v1 3 | IF v1 == #1 GOTO label1 4 | GOTO label2 5 | LABEL label1 : 6 | RETURN v1 7 | LABEL label2 : 8 | t1 := v1 - #1 9 | ARG t1 10 | t2 := CALL fact 11 | t3 := v1 * t2 12 | RETURN t3 13 | FUNCTION main : 14 | READ t4 15 | v2 := t4 16 | IF v2 > #1 GOTO label3 17 | GOTO label4 18 | LABEL label3 : 19 | ARG v2 20 | t5 := CALL fact 21 | v3 := t5 22 | GOTO label5 23 | LABEL label4 : 24 | v3 := #1 25 | LABEL label5 : 26 | WRITE v3 27 | RETURN #0 28 | -------------------------------------------------------------------------------- /cxx-irsim/test/div.ir: -------------------------------------------------------------------------------- 1 | FUNCTION main : 2 | t1 := #0 - #3 3 | t2 := #2 4 | t3 := t1 / t2 5 | WRITE t3 6 | t1 := #0 - #3 7 | t2 := #0 - #2 8 | t3 := t1 / t2 9 | WRITE t3 10 | t1 := #3 11 | t2 := #0 - #2 12 | t3 := t1 / t2 13 | WRITE t3 14 | t1 := #3 15 | t2 := #2 16 | t3 := t1 / t2 17 | WRITE t3 18 | t1 := #0 - #4 19 | t2 := #2 20 | t3 := t1 / t2 21 | WRITE t3 22 | t1 := #0 - #4 23 | t2 := #0 - #2 24 | t3 := t1 / t2 25 | WRITE t3 26 | t1 := #4 27 | t2 := #0 - #2 28 | t3 := t1 / t2 29 | WRITE t3 30 | t1 := #4 31 | t2 := #2 32 | t3 := t1 / t2 33 | WRITE t3 34 | RETURN #0 35 | -------------------------------------------------------------------------------- /mips-sim/Makefile: -------------------------------------------------------------------------------- 1 | OBJ_DIR := build 2 | SRCS := $(wildcard src/*.cc) 3 | OBJS := $(patsubst %.cc,$(OBJ_DIR)/%.o,$(SRCS)) 4 | BIN := $(OBJ_DIR)/mips-sim 5 | CXX := g++ 6 | 7 | .DEFAULT_GOAL := $(BIN) 8 | CXXFLAGS := -Iinclude -O0 -ggdb3 -Wall -MMD 9 | -include $(OBJS:.o=.d) 10 | 11 | $(BIN): $(OBJS) 12 | @echo "+ LNK $@" 13 | @$(CXX) $^ -o $@ 14 | 15 | $(OBJ_DIR)/%.o: %.cc 16 | @echo "+ CC $<" 17 | @mkdir -p $(@D) 18 | @$(CXX) -c $(CXXFLAGS) $< -o $@ 19 | 20 | run: $(BIN) 21 | @$(BIN) test/fib.S 22 | 23 | clean: 24 | rm -rf $(OBJ_DIR) 25 | rm -rf test/*.elf 26 | rm -rf test/*.o 27 | -------------------------------------------------------------------------------- /cxx-irsim/Makefile: -------------------------------------------------------------------------------- 1 | OBJ_DIR := build 2 | SRCS := irsim.cc main.cc 3 | OBJS := $(patsubst %.cc,$(OBJ_DIR)/%.o,$(SRCS)) 4 | BIN := $(OBJ_DIR)/irsim 5 | CXX := g++ 6 | 7 | .DEFAULT_GOAL := $(BIN) 8 | CXXFLAGS := -Iinclude -std=c++17 -O0 -ggdb3 -Wall -MMD 9 | -include $(OBJS:.o=.d) 10 | 11 | $(BIN): $(OBJS) 12 | @echo "+ LNK $@" 13 | @$(CXX) $^ -o $@ 14 | 15 | $(OBJ_DIR)/%.o: %.cc 16 | @echo "+ CC $<" 17 | @mkdir -p $(@D) 18 | @$(CXX) -c $(CXXFLAGS) $< -o $@ 19 | 20 | run: $(BIN) 21 | @$(BIN) test/sgn.ir 22 | 23 | gdb: $(BIN) 24 | gdb --args $(BIN) test/add.ir 25 | 26 | clean: 27 | rm -rf $(OBJ_DIR) 28 | -------------------------------------------------------------------------------- /cxx-irsim/test/array.ir: -------------------------------------------------------------------------------- 1 | FUNCTION add : 2 | PARAM v1 3 | t2 := *v1 4 | t11 := v1 + #4 5 | t3 := *t11 6 | t1 := t2 + t3 7 | RETURN t1 8 | FUNCTION main : 9 | DEC v2 8 10 | DEC v3 8 11 | v4 := #0 12 | v5 := #0 13 | LABEL label1 : 14 | IF v4 < #2 GOTO label2 15 | GOTO label3 16 | LABEL label2 : 17 | LABEL label4 : 18 | IF v5 < #2 GOTO label5 19 | GOTO label6 20 | LABEL label5 : 21 | t18 := v5 * #4 22 | t19 := &v2 + t18 23 | t20 := v4 + v5 24 | *t19 := t20 25 | v5 := v5 + #1 26 | GOTO label4 27 | LABEL label6 : 28 | t31 := v4 * #4 29 | t32 := &v3 + t31 30 | ARG &v2 31 | t33 := CALL add 32 | *t32 := t33 33 | t41 := v4 * #4 34 | t42 := &v3 + t41 35 | t35 := *t42 36 | WRITE t35 37 | v4 := v4 + #1 38 | v5 := #0 39 | GOTO label1 40 | LABEL label3 : 41 | RETURN #0 42 | -------------------------------------------------------------------------------- /mips-sim/test/fib.S: -------------------------------------------------------------------------------- 1 | .data 2 | _prompt: .asciiz "Enter an integer:" 3 | _ret: .asciiz "\n" 4 | .globl main 5 | .text 6 | read: 7 | li $v0, 4 8 | la $a0, _prompt 9 | syscall 10 | li $v0, 5 11 | syscall 12 | jr $ra 13 | 14 | write: 15 | li $v0, 1 16 | syscall 17 | li $v0, 4 18 | la $a0, _ret 19 | syscall 20 | move $v0, $0 21 | jr $ra 22 | 23 | main: 24 | li $t5, 0 25 | li $t4, 1 26 | li $t3, 0 27 | addi $sp, $sp, -4 28 | sw $ra, 0($sp) 29 | jal read 30 | lw $ra, 0($sp) 31 | addi $sp, $sp, 4 32 | move $t1, $v0 33 | move $t2, $t1 34 | label1: 35 | blt $t3, $t2, label2 36 | j label3 37 | label2: 38 | add $t1, $t5, $t4 39 | move $a0, $t4 40 | addi $sp, $sp, -4 41 | sw $ra, 0($sp) 42 | jal write 43 | lw $ra, 0($sp) 44 | addi $sp, $sp, 4 45 | move $t5, $t4 46 | move $t4, $t1 47 | addi $t1, $t3, 1 48 | move $t3, $t1 49 | j label1 50 | label3: 51 | move $v0, $0 52 | jr $ra 53 | 54 | -------------------------------------------------------------------------------- /mips-sim/src/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "MipsEmu.h" 3 | 4 | int main(int argc, const char *argv[]) { 5 | if (argc <= 1) { 6 | printf("usage: irsim *.[sS]\n"); 7 | return 0; 8 | } 9 | 10 | MipsEmu emu; 11 | emu.setInstLimit(-1u); 12 | std::string elf = emu.compile(argv[1]); 13 | int code = emu.run(elf); 14 | if (code != 0) { 15 | switch (emu.getException()) { 16 | case MipsEmuEx::INVOP: 17 | printf("invalid instruction\n"); 18 | break; 19 | case MipsEmuEx::IF: 20 | printf("invalid addr while fetching instruction\n"); 21 | break; 22 | case MipsEmuEx::STORE: 23 | printf("invalid store addr\n"); 24 | break; 25 | case MipsEmuEx::LOAD: 26 | printf("invalid load addr\n"); 27 | break; 28 | case MipsEmuEx::TIMEOUT: 29 | printf("run out of instructions\n"); 30 | break; 31 | case MipsEmuEx::OVERFLOW: 32 | printf("arithmetic overflow\n"); 33 | break; 34 | } 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /mips-sim/test/fact.S: -------------------------------------------------------------------------------- 1 | .data 2 | _prompt: .asciiz "Enter an integer:" 3 | _ret: .asciiz "\n" 4 | .globl main 5 | .text 6 | read: 7 | li $v0, 4 8 | la $a0, _prompt 9 | syscall 10 | li $v0, 5 11 | syscall 12 | jr $ra 13 | 14 | write: 15 | li $v0, 1 16 | syscall 17 | li $v0, 4 18 | la $a0, _ret 19 | syscall 20 | move $v0, $0 21 | jr $ra 22 | 23 | main: 24 | addi $sp, $sp, -4 25 | sw $ra, 0($sp) 26 | jal read 27 | lw $ra, 0($sp) 28 | addi $sp, $sp, 4 29 | move $t1, $v0 30 | li $t3, 1 31 | bgt $t1, $t3, label6 32 | j label7 33 | label6: 34 | move $a0, $t1 35 | addi $sp, $sp, -4 36 | sw $ra, 0($sp) 37 | jal fact 38 | lw $ra, 0($sp) 39 | addi $sp, $sp, 4 40 | move $t2, $v0 41 | j label8 42 | label7: 43 | li $t2, 1 44 | label8: 45 | move $a0, $t2 46 | addi $sp, $sp, -4 47 | sw $ra, 0($sp) 48 | jal write 49 | lw $ra, 0($sp) 50 | addi $sp, $sp, 4 51 | move $v0, $0 52 | jr $ra 53 | 54 | fact: 55 | li $t4, 1 56 | beq $a0, $t4, label1 57 | j label2 58 | label1: 59 | move $v0, $a0 60 | jr $ra 61 | label2: 62 | addi $sp, $sp, -8 63 | sw $a0, ($sp) 64 | sw $ra, 4($sp) 65 | sub $a0, $a0, 1 66 | jal fact 67 | lw $a0, ($sp) 68 | lw $ra, 4($sp) 69 | addi $sp, $sp, 8 70 | mul $v0, $v0, $a0 71 | jr $ra 72 | -------------------------------------------------------------------------------- /cxx-irsim/main.cc: -------------------------------------------------------------------------------- 1 | #include "irsim.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define eprintf(...) fprintf(stderr, __VA_ARGS__) 8 | 9 | int main(int argc, const char *argv[]) { 10 | if (argc <= 1) { 11 | eprintf("usage: irsim [*.ir]\n"); 12 | return 0; 13 | } 14 | 15 | std::ifstream ifs(argv[1]); 16 | 17 | if (!ifs.good()) { 18 | eprintf("'%s' no such file\n", argv[1]); 19 | return 0; 20 | } 21 | 22 | using namespace irsim; 23 | Compiler compiler; 24 | auto prog = compiler.compile(ifs); 25 | prog->setInstsLimit(100000000); 26 | prog->setMemoryLimit(128 * 1024 * 1024); 27 | auto *entry = compiler.getFunction("main"); 28 | if (!entry) { 29 | eprintf("no main in %s\n", argv[1]); 30 | return 0; 31 | } 32 | 33 | auto code = prog->run(entry); 34 | if (code == 0 || 35 | prog->getException() == Exception::NONE) { 36 | eprintf("return %d, execute %d instructions\n", code, 37 | prog->getInstCounter()); 38 | } else { 39 | switch (prog->getException()) { 40 | case Exception::IF: 41 | eprintf( 42 | "fetch instruction error (labels used but not " 43 | "defined)\n"); 44 | break; 45 | case Exception::LOAD: 46 | eprintf("memory load exception\n"); 47 | break; 48 | case Exception::STORE: 49 | eprintf("memory store exception\n"); 50 | break; 51 | case Exception::DIV_ZERO: 52 | eprintf("divided by zero exception\n"); 53 | break; 54 | case Exception::OF: 55 | eprintf("divide INT_MIN by -1 exception\n"); 56 | break; 57 | case Exception::TIMEOUT: 58 | eprintf("run out of instructions\n"); 59 | break; 60 | case Exception::OOM: 61 | eprintf("run out of memory\n"); 62 | break; 63 | case Exception::ABORT: 64 | eprintf("abort (function not return)\n"); 65 | break; 66 | case Exception::INVOP: 67 | eprintf("invalid instruction (bug of irsim)\n"); 68 | break; 69 | default: break; 70 | } 71 | } 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /mips-sim/src/MipsEmu.h: -------------------------------------------------------------------------------- 1 | #ifndef MIPSEMU_H 2 | #define MIPSEMU_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define IGNORE_CERTAIN_EXCEPTION 10 | 11 | enum class MipsEmuEx { 12 | INVOP, 13 | IF, 14 | LOAD, 15 | STORE, 16 | TIMEOUT, 17 | OVERFLOW, 18 | }; 19 | 20 | class MipsEmu { 21 | typedef uint32_t paddr_t; 22 | typedef uint32_t vaddr_t; 23 | 24 | struct { 25 | uint32_t gpr[32]; 26 | uint32_t hi, lo; 27 | uint32_t pc; 28 | 29 | vaddr_t br_target; 30 | bool is_delayslot; 31 | } cpu = {0}; 32 | 33 | static constexpr uint32_t DDR_SIZE = 128 * 1024 * 1024; 34 | std::unique_ptr ddr; 35 | 36 | private: 37 | inline __attribute__((always_inline)) uint32_t vaddr_read( 38 | paddr_t addr, int len) { 39 | if (!(addr < DDR_SIZE && addr + len < DDR_SIZE)) 40 | #ifdef IGNORE_CERTAIN_EXCEPTION 41 | return 0; 42 | #else 43 | abort(); 44 | #endif 45 | return *((uint32_t *)((char *)ddr.get() + addr)) & 46 | (~0u >> ((4 - len) << 3)); 47 | } 48 | 49 | inline __attribute__((always_inline)) void vaddr_write( 50 | paddr_t addr, int len, uint32_t data) { 51 | if (!(addr < DDR_SIZE && addr + len < DDR_SIZE)) 52 | #ifdef IGNORE_CERTAIN_EXCEPTION 53 | return; 54 | #else 55 | abort(); 56 | #endif 57 | memcpy((uint8_t *)ddr.get() + addr, &data, len); 58 | } 59 | 60 | void *vaddr_map(uint32_t addr, uint32_t len) { 61 | if (!(addr < DDR_SIZE && addr + len < DDR_SIZE)) 62 | return nullptr; 63 | return (void *)(ddr.get() + addr); 64 | } 65 | 66 | uint32_t load_elf(const std::string &elf_file); 67 | void print_registers(uint32_t instr); 68 | 69 | private: 70 | uint32_t counter = 0; 71 | uint32_t limit = -1u; 72 | MipsEmuEx exception; 73 | std::vector *printedNumbers = nullptr; 74 | 75 | public: 76 | MipsEmu() : ddr(new uint8_t[DDR_SIZE]) {} 77 | 78 | void setInstLimit(uint32_t limit = -1u) { 79 | this->limit = limit; 80 | } 81 | MipsEmuEx getException() const { return exception; } 82 | void collectPrintedNumbers(std::vector &numbers) { 83 | this->printedNumbers = &numbers; 84 | } 85 | 86 | std::string compile(const std::string &source_file); 87 | int run(const std::string &elf_file); 88 | }; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /mips-sim/src/MipsEmu.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "MipsEmu.h" 15 | 16 | #define HALT_PC 0xBFC00380 17 | #define eprintf(...) fprintf(stderr, ##__VA_ARGS__) 18 | // #define DEBUG 19 | 20 | #define Assert(cond, fmt, ...) \ 21 | do { \ 22 | if (!(cond)) { \ 23 | eprintf("Assertion `%s' failed: \e[1;31m" fmt \ 24 | "\e[0m\n", \ 25 | #cond, ##__VA_ARGS__); \ 26 | abort(); \ 27 | } \ 28 | } while (0) 29 | 30 | 31 | typedef struct { 32 | union { 33 | uint32_t val; 34 | // R-type 35 | struct { 36 | uint32_t func : 6; 37 | uint32_t shamt : 5; 38 | uint32_t rd : 5; 39 | uint32_t rt : 5; 40 | uint32_t rs : 5; 41 | uint32_t op : 6; 42 | }; 43 | 44 | uint32_t uimm : 16; // I-type 45 | 46 | int32_t simm : 16; // SI-type 47 | 48 | uint32_t addr : 26; // J-type 49 | uint32_t sel : 3; // MFC0 50 | }; 51 | } Inst; // Instruction 52 | 53 | /* clang-format off */ 54 | const char *regs[32] = { 55 | "0 ", "at", "v0", "v1", 56 | "a0", "a1", "a2", "a3", 57 | "t0", "t1", "t2", "t3", 58 | "t4", "t5", "t6", "t7", 59 | "s0", "s1", "s2", "s3", 60 | "s4", "s5", "s6", "s7", 61 | "t8", "t9", "k0", "k1", 62 | "gp", "sp", "fp", "ra" 63 | }; 64 | 65 | enum { 66 | R_zero, R_at, R_v0, R_v1, 67 | R_a0, R_a1, R_a2, R_a3, 68 | R_t0, R_t1, R_t2, R_t3, 69 | R_t4, R_t5, R_t6, R_t7, 70 | R_s0, R_s1, R_s2, R_s3, 71 | R_s4, R_s5, R_s6, R_s7, 72 | R_t8, R_t9, R_k0, R_k1, 73 | R_gp, R_sp, R_fp, R_ra, 74 | }; 75 | /* clang-format on */ 76 | 77 | static int sh(const char *fmt, ...) { 78 | static char buffer[1024]; 79 | va_list ap; 80 | va_start(ap, fmt); 81 | vsnprintf(buffer, sizeof(buffer) - 1, fmt, ap); 82 | va_end(ap); 83 | 84 | return system(buffer); 85 | } 86 | 87 | static size_t get_file_size(const char *img_file) { 88 | struct stat file_status; 89 | lstat(img_file, &file_status); 90 | if (S_ISLNK(file_status.st_mode)) { 91 | char *buf = (char *)malloc(file_status.st_size + 1); 92 | size_t size = 93 | readlink(img_file, buf, file_status.st_size); 94 | (void)size; 95 | buf[file_status.st_size] = 0; 96 | size = get_file_size(buf); 97 | free(buf); 98 | return size; 99 | } else { 100 | return file_status.st_size; 101 | } 102 | } 103 | 104 | static void *read_file(const char *filename) { 105 | size_t size = get_file_size(filename); 106 | int fd = open(filename, O_RDONLY); 107 | if (fd == -1) return NULL; 108 | 109 | // malloc buf which should be freed by caller 110 | void *buf = malloc(size); 111 | size_t len = 0; 112 | while (len < size) { len += read(fd, buf, size - len); } 113 | close(fd); 114 | return buf; 115 | } 116 | 117 | uint32_t MipsEmu::load_elf(const std::string &elf_file) { 118 | Assert(elf_file.size(), "Need an elf file"); 119 | 120 | /* set symbol file to elf_file */ 121 | const uint32_t elf_magic = 0x464c457f; 122 | 123 | size_t size = get_file_size(elf_file.c_str()); 124 | void *buf = read_file(elf_file.c_str()); 125 | Assert(buf, "file '%s' cannot be opened for read\n", 126 | elf_file.c_str()); 127 | 128 | Elf32_Ehdr *elf = (Elf32_Ehdr *)buf; 129 | 130 | uint32_t elf_entry = elf->e_entry; 131 | 132 | uint32_t *p_magic = (uint32_t *)buf; 133 | Assert(*p_magic == elf_magic, "wrong file format"); 134 | Assert(elf->e_ident[EI_CLASS] == ELFCLASS32, 135 | "not a 32-bit elf file"); 136 | Assert(elf->e_ident[EI_DATA] == ELFDATA2LSB, 137 | "not a little endian elf file"); 138 | Assert(elf->e_machine == EM_MIPS, "not a mips elf file"); 139 | 140 | for (int i = 0; i < elf->e_phnum; i++) { 141 | size_t phdr_off = i * elf->e_phentsize + elf->e_phoff; 142 | Elf32_Phdr *ph = (Elf32_Phdr *)((char *)buf + phdr_off); 143 | Assert(phdr_off < size, "ELF32_Phdr out of file"); 144 | Assert(ph->p_offset < size, "ELF32_Ph out of file"); 145 | if (ph->p_type != PT_LOAD) { continue; } 146 | 147 | void *ptr = vaddr_map(ph->p_vaddr, ph->p_memsz); 148 | if (ptr) { 149 | memcpy(ptr, (char *)buf + ph->p_offset, ph->p_filesz); 150 | memset((char *)ptr + ph->p_filesz, 0, 151 | ph->p_memsz - ph->p_filesz); 152 | } 153 | } 154 | 155 | free(buf); 156 | return elf_entry; 157 | } 158 | 159 | void MipsEmu::print_registers(uint32_t instr) { 160 | eprintf("$pc: 0x%08x", cpu.pc); 161 | eprintf(" "); 162 | eprintf("$instr: 0x%08x", instr); 163 | eprintf("\n"); 164 | eprintf("$hi: 0x%08x", cpu.hi); 165 | eprintf(" "); 166 | eprintf("$lo: 0x%08x", cpu.lo); 167 | eprintf("\n"); 168 | 169 | for (int i = 0; i < 32; i++) { 170 | eprintf("$%s:0x%08x%c", regs[i], cpu.gpr[i], 171 | (i + 1) % 4 == 0 ? '\n' : ' '); 172 | } 173 | } 174 | 175 | const char *find_program(const char *name) { 176 | static char buffer[BUFSIZ]; 177 | const char *s_beg = getenv("PATH"); 178 | const char *s_end = s_beg; 179 | if (!s_beg) { 180 | s_beg = s_end = "/bin:/usr/bin:/usr/local/bin"; 181 | } 182 | 183 | while (*s_end) { 184 | while (*s_end && *s_end != ':') s_end++; 185 | 186 | int n = s_end - s_beg; 187 | memcpy(buffer, s_beg, n); 188 | sprintf(buffer + n, "/%s", name); 189 | if (access(buffer, F_OK | X_OK) == 0) return buffer; 190 | 191 | if (!*s_end) break; 192 | s_end++; 193 | s_beg = s_end; 194 | } 195 | 196 | return NULL; 197 | } 198 | 199 | const char *check_and_find(const char *name) { 200 | const char *path = find_program(name); 201 | if (!path) { 202 | eprintf("%s is required !\n", name); 203 | eprintf( 204 | "install it by `sudo apt-get install " 205 | "gcc-mips-linux-gnu`\n"); 206 | exit(0); 207 | } 208 | return path; 209 | } 210 | 211 | std::string MipsEmu::compile(const std::string &source) { 212 | const char *srcfile = source.c_str(); 213 | if (access(srcfile, F_OK | R_OK) != 0) { 214 | eprintf("unable to open '%s' for reading\n", srcfile); 215 | return 0; 216 | } 217 | 218 | const char *as = check_and_find("mips-linux-gnu-as"); 219 | int code = sh("%s %s -EL -o %s.o", as, srcfile, srcfile); 220 | if (code != 0) { 221 | eprintf("failed to compile %s\n", srcfile); 222 | return 0; 223 | } 224 | 225 | const char *ld = check_and_find("mips-linux-gnu-ld"); 226 | code = 227 | sh("%s -entry main -Ttext=0x1000 %s.o -EL -o %s.elf", 228 | ld, srcfile, srcfile); 229 | if (code != 0) { 230 | eprintf("failed to link %s\n", srcfile); 231 | return 0; 232 | } 233 | 234 | static char buffer[1024]; 235 | snprintf(buffer, 1023, "%s.elf", srcfile); 236 | return buffer; 237 | } 238 | 239 | int MipsEmu::run(const std::string &elf_file) { 240 | uint32_t entry = load_elf(elf_file); 241 | 242 | cpu.pc = entry; 243 | cpu.gpr[R_sp] = DDR_SIZE - 4; // set sp 244 | cpu.gpr[R_ra] = HALT_PC; 245 | 246 | while (true) { 247 | if ((cpu.pc & 0x3) != 0) { 248 | exception = MipsEmuEx::IF; 249 | return -1; 250 | } 251 | 252 | Inst inst = {.val = vaddr_read(cpu.pc, 4)}; 253 | 254 | #ifdef DEBUG 255 | print_registers(inst.val); 256 | #endif 257 | 258 | #include "instr.h" 259 | 260 | counter++; 261 | if (counter > limit) { 262 | exception = MipsEmuEx::TIMEOUT; 263 | return -1; 264 | } 265 | 266 | if (cpu.pc == HALT_PC) break; 267 | } 268 | return 0; 269 | } 270 | -------------------------------------------------------------------------------- /cxx-irsim/irsim.h: -------------------------------------------------------------------------------- 1 | #ifndef IRSIM_H 2 | #define IRSIM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace irsim { 16 | 17 | template 18 | int ptr_hi(const T *ptr) { 19 | return static_cast( 20 | reinterpret_cast(ptr) >> 32); 21 | } 22 | 23 | template 24 | int ptr_lo(const T *ptr) { 25 | return static_cast(reinterpret_cast(ptr)); 26 | } 27 | 28 | template 29 | T *lohi_to_ptr(uint32_t lo, uint32_t hi) { 30 | uintptr_t ptr = ((uint64_t)hi << 32) | lo; 31 | return reinterpret_cast(ptr); 32 | } 33 | 34 | /* clang-format off */ 35 | enum class Exception { 36 | NONE, IF, LOAD, STORE, DIV_ZERO, OF, TIMEOUT, OOM, ABORT, 37 | INVOP, 38 | }; 39 | 40 | enum CtrlRegs { 41 | CR_RET, // rw, used for return address 42 | CR_SERIAL, // read only 43 | CR_COUNT, // rw 44 | CR_ARG, // rw 45 | }; 46 | 47 | enum class Opc { 48 | abort, // as 0 49 | helper, // native call 50 | alloca, 51 | la, ld, st, li, mov, add, sub, 52 | mul, div, jmp, br, slt, sle, seq, sge, sgt, sne, 53 | call, ret, mfcr, mtcr, mark, 54 | quit, 55 | }; 56 | /* clang-format on */ 57 | 58 | using TransitionBlock = std::array; 59 | 60 | class ProgramInput { 61 | std::istream *is; 62 | std::vector *vec; 63 | 64 | friend class Program; 65 | 66 | public: 67 | ProgramInput(std::istream &is) : is(&is), vec(nullptr) {} 68 | ProgramInput(std::vector &vec) 69 | : is(nullptr), vec(&vec) {} 70 | ProgramInput(const ProgramInput &that) = default; 71 | 72 | int read() { 73 | if (vec) { 74 | auto ret = vec->back(); 75 | vec->pop_back(); 76 | return ret; 77 | } else { 78 | int ret; 79 | // printf("please input a number: "); 80 | (*is) >> ret; 81 | return ret; 82 | } 83 | } 84 | }; 85 | 86 | class ProgramOutput { 87 | std::ostream *os; 88 | std::vector *vec; 89 | 90 | friend class Program; 91 | 92 | public: 93 | ProgramOutput(std::ostream &os) : os(&os), vec(nullptr) {} 94 | ProgramOutput(std::vector &vec) 95 | : os(nullptr), vec(&vec) {} 96 | ProgramOutput(const ProgramOutput &that) = default; 97 | 98 | void write(int v) { 99 | if (vec) { 100 | vec->push_back(v); 101 | } else { 102 | (*os) << v << "\n"; 103 | } 104 | } 105 | }; 106 | 107 | class ProgramIO : public ProgramInput, 108 | public ProgramOutput { 109 | public: 110 | ProgramIO(ProgramInput in, ProgramOutput out) 111 | : ProgramInput(in), ProgramOutput(out) {} 112 | }; 113 | 114 | template 115 | class span { 116 | std::vector &container; 117 | size_t ptr; 118 | size_t _size; 119 | 120 | public: 121 | span() : container(*(std::vector *)nullptr) {} 122 | span(std::vector &container, size_t ptr, size_t size) 123 | : container(container), ptr(ptr), _size(size) {} 124 | 125 | using iterator = typename std::vector::iterator; 126 | using const_iterator = 127 | typename std::vector::const_iterator; 128 | 129 | span(span &&) = default; 130 | span(const span &) = default; 131 | span &operator=(span &&) = default; 132 | span &operator=(const span &) = default; 133 | 134 | void resize(size_t newSize) { 135 | if (ptr + newSize > container.size()) 136 | throw std::length_error("invalid new size"); 137 | _size = newSize; 138 | } 139 | 140 | size_t size() const { return _size; } 141 | 142 | iterator begin() { return container.begin() + ptr; } 143 | const_iterator begin() const { 144 | return container.begin() + ptr; 145 | } 146 | iterator end() { return container.begin() + ptr + _size; } 147 | const_iterator end() const { 148 | return container.begin() + ptr + _size; 149 | } 150 | 151 | T &at(size_t i) { 152 | if (i >= _size) throw std::range_error("out of range"); 153 | return container.at(ptr + i); 154 | } 155 | const T &at(size_t i) const { 156 | if (i >= _size) throw std::range_error("out of range"); 157 | return container.at(ptr + i); 158 | } 159 | T &operator[](size_t i) { return container[ptr + i]; } 160 | const T &operator[](size_t i) const { 161 | return container[ptr + i]; 162 | } 163 | }; 164 | 165 | class Program { 166 | ProgramIO io; 167 | 168 | unsigned memory_limit = -1u; 169 | unsigned insts_limit = -1u; 170 | 171 | std::vector> codes; 172 | TransitionBlock *curblk = nullptr; 173 | int *textptr = nullptr; 174 | int *curf = nullptr; 175 | 176 | friend class Compiler; 177 | 178 | /* running environment */ 179 | std::vector args; 180 | std::vector frames; 181 | std::vector memory; 182 | std::vector> stack; 183 | std::array ctrl_regs = {}; 184 | 185 | Exception exception = Exception::NONE; 186 | 187 | public: 188 | Program() : io(std::cin, std::cout) { 189 | curblk = new TransitionBlock; 190 | codes.push_back( 191 | std::unique_ptr(curblk)); 192 | textptr = &curblk->at(0); 193 | 194 | curf = gen_inst(Opc::quit, 0); 195 | } 196 | 197 | int run(int *eip); 198 | void setMemoryLimit(unsigned lim) { memory_limit = lim; } 199 | void setInstsLimit(unsigned lim) { insts_limit = lim; } 200 | unsigned getInstCounter() const { 201 | return ctrl_regs[CR_COUNT]; 202 | } 203 | Exception getException() const { return exception; } 204 | 205 | void setIO(ProgramIO io) { this->io = io; } 206 | void setInput(ProgramInput in) { 207 | static_cast(this->io) = in; 208 | } 209 | void setOutput(ProgramOutput out) { 210 | static_cast(this->io) = out; 211 | } 212 | 213 | private: 214 | int *get_textptr() const { return textptr; } 215 | void check_eof(unsigned N) { 216 | if (textptr + N + 2 >= &(*curblk)[curblk->size()]) { 217 | curblk = new TransitionBlock; 218 | codes.push_back( 219 | std::unique_ptr(curblk)); 220 | *textptr++ = (int)Opc::jmp; 221 | *textptr++ = ptr_lo(&(curblk->at(0))); 222 | *textptr++ = ptr_hi(&(curblk->at(0))); 223 | textptr = &curblk->at(0); 224 | } 225 | } 226 | 227 | template 228 | int *gen_inst(Opc opc, Args... args) { 229 | constexpr unsigned N = sizeof...(args); 230 | check_eof(N + 1); 231 | auto oldptr = textptr; 232 | *textptr++ = (int)opc; 233 | for (int v : 234 | std::array{static_cast(args)...}) { 235 | *textptr++ = v; 236 | } 237 | 238 | #ifdef DEBUG 239 | extern std::map opc_to_string; 240 | printf("+ %p: %s", oldptr, opc_to_string[opc].c_str()); 241 | for (int v : 242 | std::array{static_cast(args)...}) { 243 | printf(" 0x%x", v); 244 | } 245 | printf("\n"); 246 | #endif 247 | return oldptr; 248 | } 249 | 250 | int *gen_call(int *target) { 251 | return gen_inst( 252 | Opc::call, ptr_lo(target), ptr_hi(target)); 253 | } 254 | 255 | int *gen_jmp(int *target) { 256 | return gen_inst( 257 | Opc::jmp, ptr_lo(target), ptr_hi(target)); 258 | } 259 | 260 | int *gen_br(int cond, int *target) { 261 | return gen_inst( 262 | Opc::br, cond, ptr_lo(target), ptr_hi(target)); 263 | } 264 | }; 265 | 266 | class Compiler { 267 | int temp_ptr; 268 | static constexpr int temp_end = 4; 269 | int stack_size; 270 | std::map vars; 271 | std::map funcs; 272 | std::map labels; 273 | std::map temps; 274 | std::map> backfill_labels; 275 | 276 | int primary_exp(Program *prog, const std::string &tok, 277 | int to = INT_MAX); 278 | 279 | using TokenList = std::vector; 280 | 281 | bool handle_label(Program *, const TokenList &toks); 282 | bool handle_func(Program *, const TokenList &toks); 283 | bool handle_assign(Program *, const TokenList &toks); 284 | bool handle_arith(Program *, const TokenList &toks); 285 | bool handle_takeaddr(Program *, const TokenList &toks); 286 | bool handle_deref(Program *, const TokenList &toks); 287 | bool handle_deref_assign( 288 | Program *, const TokenList &toks); 289 | bool handle_goto_(Program *, const TokenList &toks); 290 | bool handle_branch(Program *, const TokenList &toks); 291 | bool handle_ret(Program *, const TokenList &toks); 292 | bool handle_dec(Program *, const TokenList &toks); 293 | bool handle_arg(Program *, const TokenList &toks); 294 | bool handle_call(Program *, const TokenList &toks); 295 | bool handle_param(Program *, const TokenList &toks); 296 | bool handle_read(Program *, const TokenList &toks); 297 | bool handle_write(Program *, const TokenList &toks); 298 | 299 | TokenList splitTokens(const std::string line) { 300 | std::string tmp; 301 | std::vector out; 302 | std::istringstream iss(line); 303 | while (iss >> tmp) out.push_back(tmp); 304 | return out; 305 | } 306 | 307 | public: 308 | Compiler() { clear_env(); } 309 | 310 | void clear_env() { 311 | temp_ptr = 0; 312 | stack_size = temp_end; // 0 for return value 313 | vars.clear(); 314 | labels.clear(); 315 | } 316 | 317 | int *getFunction(const std::string &fname) { 318 | return funcs[fname]; 319 | } 320 | 321 | int getVar(const std::string &name, unsigned size = 1) { 322 | auto it = vars.find(name); 323 | if (it == vars.end()) { 324 | std::tie(it, std::ignore) = vars.insert( 325 | std::pair{name, stack_size}); 326 | stack_size += size; 327 | } 328 | #ifdef DEBUG 329 | fprintf(stdout, "allocate %d for %s\n", it->second, 330 | name.c_str()); 331 | #endif 332 | return it->second; 333 | } 334 | 335 | void clearTemps() { temp_ptr = 0; } 336 | 337 | int newTemp() { 338 | int tmp = temp_ptr++; 339 | assert(tmp < temp_end); 340 | return tmp; 341 | } 342 | 343 | std::unique_ptr compile(std::istream &is); 344 | }; 345 | 346 | } // namespace irsim 347 | 348 | #endif 349 | -------------------------------------------------------------------------------- /py-irsim/ui_mainwindow.py: -------------------------------------------------------------------------------- 1 | # uncompyle6 version 3.6.7 2 | # Python bytecode 2.7 (62211) 3 | # Decompiled from: Python 3.8.2 (default, Apr 27 2020, 15:53:34) 4 | # [GCC 9.3.0] 5 | # Embedded file name: /home/zhuhaoyang/myWork/vm_modified source/ui_mainwindow.py 6 | # Compiled at: 2014-08-22 10:06:29 7 | from PyQt4 import QtCore, QtGui 8 | try: 9 | _fromUtf8 = QtCore.QString.fromUtf8 10 | except AttributeError: 11 | _fromUtf8 = lambda s: s 12 | 13 | class Ui_MainWindow(object): 14 | 15 | def setupUi(self, MainWindow): 16 | MainWindow.setObjectName(_fromUtf8('MainWindow')) 17 | MainWindow.resize(800, 600) 18 | sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) 19 | sizePolicy.setHorizontalStretch(0) 20 | sizePolicy.setVerticalStretch(0) 21 | sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) 22 | MainWindow.setSizePolicy(sizePolicy) 23 | MainWindow.setMinimumSize(QtCore.QSize(800, 600)) 24 | MainWindow.setMaximumSize(QtCore.QSize(800, 600)) 25 | icon = QtGui.QIcon() 26 | icon.addPixmap(QtGui.QPixmap(_fromUtf8(':/icon.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off) 27 | MainWindow.setWindowIcon(icon) 28 | self.centralwidget = QtGui.QWidget(MainWindow) 29 | self.centralwidget.setObjectName(_fromUtf8('centralwidget')) 30 | self.layoutWidget = QtGui.QWidget(self.centralwidget) 31 | self.layoutWidget.setGeometry(QtCore.QRect(20, 10, 761, 490)) 32 | self.layoutWidget.setObjectName(_fromUtf8('layoutWidget')) 33 | self.horizontalLayout = QtGui.QHBoxLayout(self.layoutWidget) 34 | self.horizontalLayout.setMargin(0) 35 | self.horizontalLayout.setObjectName(_fromUtf8('horizontalLayout')) 36 | self.verticalLayout = QtGui.QVBoxLayout() 37 | self.verticalLayout.setObjectName(_fromUtf8('verticalLayout')) 38 | self.label = QtGui.QLabel(self.layoutWidget) 39 | font = QtGui.QFont() 40 | font.setFamily(_fromUtf8('Verdana')) 41 | font.setBold(True) 42 | font.setWeight(75) 43 | self.label.setFont(font) 44 | self.label.setObjectName(_fromUtf8('label')) 45 | self.verticalLayout.addWidget(self.label) 46 | self.codeList = QtGui.QListWidget(self.layoutWidget) 47 | self.codeList.setEnabled(True) 48 | font = QtGui.QFont() 49 | font.setFamily(_fromUtf8('Arial')) 50 | self.codeList.setFont(font) 51 | self.codeList.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) 52 | self.codeList.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) 53 | self.codeList.setObjectName(_fromUtf8('codeList')) 54 | self.verticalLayout.addWidget(self.codeList) 55 | self.horizontalLayout.addLayout(self.verticalLayout) 56 | spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum) 57 | self.horizontalLayout.addItem(spacerItem) 58 | self.verticalLayout_2 = QtGui.QVBoxLayout() 59 | self.verticalLayout_2.setObjectName(_fromUtf8('verticalLayout_2')) 60 | self.label_2 = QtGui.QLabel(self.layoutWidget) 61 | font = QtGui.QFont() 62 | font.setFamily(_fromUtf8('Verdana')) 63 | font.setBold(True) 64 | font.setWeight(75) 65 | self.label_2.setFont(font) 66 | self.label_2.setObjectName(_fromUtf8('label_2')) 67 | self.verticalLayout_2.addWidget(self.label_2) 68 | self.watchTable = QtGui.QTableWidget(self.layoutWidget) 69 | font = QtGui.QFont() 70 | font.setFamily(_fromUtf8('Arial')) 71 | self.watchTable.setFont(font) 72 | self.watchTable.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) 73 | self.watchTable.setSelectionMode(QtGui.QAbstractItemView.SingleSelection) 74 | self.watchTable.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) 75 | self.watchTable.setHorizontalScrollMode(QtGui.QAbstractItemView.ScrollPerPixel) 76 | self.watchTable.setObjectName(_fromUtf8('watchTable')) 77 | self.watchTable.setColumnCount(2) 78 | self.watchTable.setRowCount(0) 79 | item = QtGui.QTableWidgetItem() 80 | self.watchTable.setHorizontalHeaderItem(0, item) 81 | item = QtGui.QTableWidgetItem() 82 | self.watchTable.setHorizontalHeaderItem(1, item) 83 | self.verticalLayout_2.addWidget(self.watchTable) 84 | spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred) 85 | self.verticalLayout_2.addItem(spacerItem1) 86 | self.label_3 = QtGui.QLabel(self.layoutWidget) 87 | font = QtGui.QFont() 88 | font.setFamily(_fromUtf8('Verdana')) 89 | font.setBold(True) 90 | font.setWeight(75) 91 | self.label_3.setFont(font) 92 | self.label_3.setObjectName(_fromUtf8('label_3')) 93 | self.verticalLayout_2.addWidget(self.label_3) 94 | self.console = QtGui.QTextEdit(self.layoutWidget) 95 | font = QtGui.QFont() 96 | font.setFamily(_fromUtf8('Serif')) 97 | self.console.setFont(font) 98 | self.console.setReadOnly(True) 99 | self.console.setObjectName(_fromUtf8('console')) 100 | self.verticalLayout_2.addWidget(self.console) 101 | self.horizontalLayout.addLayout(self.verticalLayout_2) 102 | MainWindow.setCentralWidget(self.centralwidget) 103 | self.menubar = QtGui.QMenuBar(MainWindow) 104 | self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 25)) 105 | self.menubar.setObjectName(_fromUtf8('menubar')) 106 | self.menuFile = QtGui.QMenu(self.menubar) 107 | self.menuFile.setObjectName(_fromUtf8('menuFile')) 108 | self.menuRun = QtGui.QMenu(self.menubar) 109 | self.menuRun.setObjectName(_fromUtf8('menuRun')) 110 | self.menuAbout = QtGui.QMenu(self.menubar) 111 | self.menuAbout.setObjectName(_fromUtf8('menuAbout')) 112 | MainWindow.setMenuBar(self.menubar) 113 | self.statusbar = QtGui.QStatusBar(MainWindow) 114 | self.statusbar.setObjectName(_fromUtf8('statusbar')) 115 | MainWindow.setStatusBar(self.statusbar) 116 | self.toolBar = QtGui.QToolBar(MainWindow) 117 | self.toolBar.setObjectName(_fromUtf8('toolBar')) 118 | MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) 119 | self.action_Open = QtGui.QAction(MainWindow) 120 | icon1 = QtGui.QIcon() 121 | icon1.addPixmap(QtGui.QPixmap(_fromUtf8(':/filenew.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off) 122 | self.action_Open.setIcon(icon1) 123 | self.action_Open.setObjectName(_fromUtf8('action_Open')) 124 | self.actionQuit = QtGui.QAction(MainWindow) 125 | icon2 = QtGui.QIcon() 126 | icon2.addPixmap(QtGui.QPixmap(_fromUtf8(':/filequit.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off) 127 | self.actionQuit.setIcon(icon2) 128 | self.actionQuit.setObjectName(_fromUtf8('actionQuit')) 129 | self.actionRun = QtGui.QAction(MainWindow) 130 | self.actionRun.setEnabled(True) 131 | icon3 = QtGui.QIcon() 132 | icon3.addPixmap(QtGui.QPixmap(_fromUtf8(':/run.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off) 133 | self.actionRun.setIcon(icon3) 134 | self.actionRun.setObjectName(_fromUtf8('actionRun')) 135 | self.actionStop = QtGui.QAction(MainWindow) 136 | self.actionStop.setEnabled(True) 137 | icon4 = QtGui.QIcon() 138 | icon4.addPixmap(QtGui.QPixmap(_fromUtf8(':/stop.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off) 139 | self.actionStop.setIcon(icon4) 140 | self.actionStop.setObjectName(_fromUtf8('actionStop')) 141 | self.actionStep = QtGui.QAction(MainWindow) 142 | self.actionStep.setEnabled(True) 143 | icon5 = QtGui.QIcon() 144 | icon5.addPixmap(QtGui.QPixmap(_fromUtf8(':/step.png')), QtGui.QIcon.Normal, QtGui.QIcon.Off) 145 | self.actionStep.setIcon(icon5) 146 | self.actionStep.setObjectName(_fromUtf8('actionStep')) 147 | self.actionAbout = QtGui.QAction(MainWindow) 148 | self.actionAbout.setIcon(icon) 149 | self.actionAbout.setObjectName(_fromUtf8('actionAbout')) 150 | self.menuFile.addAction(self.action_Open) 151 | self.menuFile.addSeparator() 152 | self.menuFile.addAction(self.actionQuit) 153 | self.menuRun.addAction(self.actionRun) 154 | self.menuRun.addAction(self.actionStop) 155 | self.menuRun.addAction(self.actionStep) 156 | self.menuAbout.addAction(self.actionAbout) 157 | self.menubar.addAction(self.menuFile.menuAction()) 158 | self.menubar.addAction(self.menuRun.menuAction()) 159 | self.menubar.addAction(self.menuAbout.menuAction()) 160 | self.toolBar.addAction(self.action_Open) 161 | self.toolBar.addSeparator() 162 | self.toolBar.addAction(self.actionRun) 163 | self.toolBar.addAction(self.actionStep) 164 | self.toolBar.addAction(self.actionStop) 165 | self.toolBar.addSeparator() 166 | self.toolBar.addAction(self.actionQuit) 167 | self.retranslateUi(MainWindow) 168 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 169 | MainWindow.setTabOrder(self.codeList, self.watchTable) 170 | MainWindow.setTabOrder(self.watchTable, self.console) 171 | 172 | def retranslateUi(self, MainWindow): 173 | MainWindow.setWindowTitle(QtGui.QApplication.translate('MainWindow', 'IR Simulator', None, QtGui.QApplication.UnicodeUTF8)) 174 | self.label.setText(QtGui.QApplication.translate('MainWindow', 'Code', None, QtGui.QApplication.UnicodeUTF8)) 175 | self.label_2.setText(QtGui.QApplication.translate('MainWindow', 'Watch', None, QtGui.QApplication.UnicodeUTF8)) 176 | item = self.watchTable.horizontalHeaderItem(0) 177 | item.setText(QtGui.QApplication.translate('MainWindow', 'Variable', None, QtGui.QApplication.UnicodeUTF8)) 178 | item = self.watchTable.horizontalHeaderItem(1) 179 | item.setText(QtGui.QApplication.translate('MainWindow', 'Value', None, QtGui.QApplication.UnicodeUTF8)) 180 | self.label_3.setText(QtGui.QApplication.translate('MainWindow', 'Console', None, QtGui.QApplication.UnicodeUTF8)) 181 | self.menuFile.setTitle(QtGui.QApplication.translate('MainWindow', 'File', None, QtGui.QApplication.UnicodeUTF8)) 182 | self.menuRun.setTitle(QtGui.QApplication.translate('MainWindow', 'Run', None, QtGui.QApplication.UnicodeUTF8)) 183 | self.menuAbout.setTitle(QtGui.QApplication.translate('MainWindow', 'About', None, QtGui.QApplication.UnicodeUTF8)) 184 | self.toolBar.setWindowTitle(QtGui.QApplication.translate('MainWindow', 'toolBar', None, QtGui.QApplication.UnicodeUTF8)) 185 | self.action_Open.setText(QtGui.QApplication.translate('MainWindow', '&Open...', None, QtGui.QApplication.UnicodeUTF8)) 186 | self.action_Open.setStatusTip(QtGui.QApplication.translate('MainWindow', 'Open an existing IR file', None, QtGui.QApplication.UnicodeUTF8)) 187 | self.action_Open.setWhatsThis(QtGui.QApplication.translate('MainWindow', 'Open', None, QtGui.QApplication.UnicodeUTF8)) 188 | self.action_Open.setShortcut(QtGui.QApplication.translate('MainWindow', 'Ctrl+O', None, QtGui.QApplication.UnicodeUTF8)) 189 | self.actionQuit.setText(QtGui.QApplication.translate('MainWindow', '&Quit', None, QtGui.QApplication.UnicodeUTF8)) 190 | self.actionQuit.setStatusTip(QtGui.QApplication.translate('MainWindow', 'Quit the application', None, QtGui.QApplication.UnicodeUTF8)) 191 | self.actionQuit.setShortcut(QtGui.QApplication.translate('MainWindow', 'Esc', None, QtGui.QApplication.UnicodeUTF8)) 192 | self.actionRun.setText(QtGui.QApplication.translate('MainWindow', '&Run', None, QtGui.QApplication.UnicodeUTF8)) 193 | self.actionRun.setStatusTip(QtGui.QApplication.translate('MainWindow', 'Run the code', None, QtGui.QApplication.UnicodeUTF8)) 194 | self.actionRun.setShortcut(QtGui.QApplication.translate('MainWindow', 'F5', None, QtGui.QApplication.UnicodeUTF8)) 195 | self.actionStop.setText(QtGui.QApplication.translate('MainWindow', 'St&op', None, QtGui.QApplication.UnicodeUTF8)) 196 | self.actionStop.setStatusTip(QtGui.QApplication.translate('MainWindow', 'Stop the current running process', None, QtGui.QApplication.UnicodeUTF8)) 197 | self.actionStop.setShortcut(QtGui.QApplication.translate('MainWindow', 'F4', None, QtGui.QApplication.UnicodeUTF8)) 198 | self.actionStep.setText(QtGui.QApplication.translate('MainWindow', 'St&ep...', None, QtGui.QApplication.UnicodeUTF8)) 199 | self.actionStep.setStatusTip(QtGui.QApplication.translate('MainWindow', 'Run the code step by step', None, QtGui.QApplication.UnicodeUTF8)) 200 | self.actionStep.setShortcut(QtGui.QApplication.translate('MainWindow', 'F8', None, QtGui.QApplication.UnicodeUTF8)) 201 | self.actionAbout.setText(QtGui.QApplication.translate('MainWindow', '&About...', None, QtGui.QApplication.UnicodeUTF8)) 202 | self.actionAbout.setStatusTip(QtGui.QApplication.translate('MainWindow', 'About this application', None, QtGui.QApplication.UnicodeUTF8)) 203 | return 204 | 205 | 206 | import resources_rc 207 | # okay decompiling ui_mainwindow.pyc 208 | -------------------------------------------------------------------------------- /cxx-irsim/test/if-fault.ir: -------------------------------------------------------------------------------- 1 | FUNCTION safe_add : 2 | PARAM v_lhs_add 3 | PARAM v_rhs_add 4 | t1 := #0 5 | t4 := #0 6 | t7 := #0 7 | t10 := v_lhs_add 8 | t11 := #0 9 | IF t10 > t11 GOTO label8 10 | GOTO label9 11 | LABEL label8 : 12 | t7 := #1 13 | LABEL label9 : 14 | IF t7 != #0 GOTO label4 15 | GOTO label6 16 | LABEL label4 : 17 | t12 := #0 18 | t15 := v_rhs_add 19 | t16 := #0 20 | IF t15 > t16 GOTO label13 21 | GOTO label14 22 | LABEL label13 : 23 | t12 := #1 24 | LABEL label14 : 25 | IF t12 != #0 GOTO label3 26 | GOTO label6 27 | LABEL label3 : 28 | t17 := #0 29 | t20 := v_lhs_add 30 | t22 := #2147483647 31 | t23 := v_rhs_add 32 | t21 := t22 - t23 33 | IF t20 > t21 GOTO label18 34 | GOTO label19 35 | LABEL label18 : 36 | t17 := #1 37 | LABEL label19 : 38 | IF t17 != #0 GOTO label5 39 | GOTO label6 40 | LABEL label5 : 41 | t4 := #1 42 | LABEL label6 : 43 | IF t4 != #0 GOTO label2 44 | GOTO label2 45 | LABEL label2 : 46 | t24 := #0 47 | t27 := #0 48 | t30 := v_lhs_add 49 | t31 := #0 50 | IF t30 < t31 GOTO label28 51 | GOTO label29 52 | LABEL label28 : 53 | t27 := #1 54 | LABEL label29 : 55 | IF t27 != #0 GOTO label6 56 | GOTO label26 57 | LABEL label6 : 58 | t32 := #0 59 | t35 := v_rhs_add 60 | t36 := #0 61 | IF t35 < t36 GOTO label33 62 | GOTO label34 63 | LABEL label33 : 64 | t32 := #1 65 | LABEL label34 : 66 | IF t32 != #0 GOTO label5 67 | GOTO label26 68 | LABEL label5 : 69 | t37 := #0 70 | t40 := v_lhs_add 71 | t44 := #-2147483648 72 | t42 := #0 - t44 73 | t43 := v_rhs_add 74 | t41 := t42 - t43 75 | IF t40 < t41 GOTO label38 76 | GOTO label39 77 | LABEL label38 : 78 | t37 := #1 79 | LABEL label39 : 80 | IF t37 != #0 GOTO label25 81 | GOTO label26 82 | LABEL label25 : 83 | t24 := #1 84 | LABEL label26 : 85 | IF t24 != #0 GOTO label2 86 | GOTO label3 87 | LABEL label2 : 88 | t1 := #1 89 | LABEL label3 : 90 | IF t1 != #0 GOTO label0 91 | GOTO label1 92 | t45 := v_lhs_add 93 | RETURN t45 94 | LABEL label1 : 95 | t47 := v_lhs_add 96 | t48 := v_rhs_add 97 | t46 := t47 + t48 98 | RETURN t46 99 | FUNCTION safe_sub : 100 | PARAM v_lhs_sub 101 | PARAM v_rhs_sub 102 | t49 := #0 103 | t52 := #0 104 | t55 := v_lhs_sub 105 | t56 := #0 106 | IF t55 > t56 GOTO label53 107 | GOTO label54 108 | LABEL label53 : 109 | t52 := #1 110 | LABEL label54 : 111 | IF t52 != #0 GOTO label10 112 | GOTO label51 113 | LABEL label10 : 114 | t57 := #0 115 | t60 := v_rhs_sub 116 | t61 := #0 117 | IF t60 < t61 GOTO label58 118 | GOTO label59 119 | LABEL label58 : 120 | t57 := #1 121 | LABEL label59 : 122 | IF t57 != #0 GOTO label9 123 | GOTO label51 124 | LABEL label9 : 125 | t62 := #0 126 | t65 := v_lhs_sub 127 | t67 := #2147483647 128 | t68 := v_rhs_sub 129 | t66 := t67 + t68 130 | IF t65 > t66 GOTO label63 131 | GOTO label64 132 | LABEL label63 : 133 | t62 := #1 134 | LABEL label64 : 135 | IF t62 != #0 GOTO label50 136 | GOTO label51 137 | LABEL label50 : 138 | t49 := #1 139 | LABEL label51 : 140 | IF t49 != #0 GOTO label0 141 | GOTO label8 142 | LABEL label8 : 143 | t69 := #0 144 | t72 := #0 145 | t75 := v_lhs_sub 146 | t76 := #0 147 | IF t75 < t76 GOTO label73 148 | GOTO label74 149 | LABEL label73 : 150 | t72 := #1 151 | LABEL label74 : 152 | IF t72 != #0 GOTO label12 153 | GOTO label71 154 | LABEL label12 : 155 | t77 := #0 156 | t80 := v_rhs_sub 157 | t81 := #0 158 | IF t80 > t81 GOTO label78 159 | GOTO label79 160 | LABEL label78 : 161 | t77 := #1 162 | LABEL label79 : 163 | IF t77 != #0 GOTO label11 164 | GOTO label71 165 | LABEL label11 : 166 | t82 := #0 167 | t85 := v_lhs_sub 168 | t89 := #-2147483648 169 | t87 := #0 - t89 170 | t88 := v_rhs_sub 171 | t86 := t87 + t88 172 | IF t85 < t86 GOTO label83 173 | GOTO label84 174 | LABEL label83 : 175 | t82 := #1 176 | LABEL label84 : 177 | IF t82 != #0 GOTO label70 178 | GOTO label71 179 | LABEL label70 : 180 | t69 := #1 181 | LABEL label71 : 182 | IF t69 != #0 GOTO label0 183 | GOTO label7 184 | t90 := v_lhs_sub 185 | RETURN t90 186 | LABEL label7 : 187 | t92 := v_lhs_sub 188 | t93 := v_rhs_sub 189 | t91 := t92 - t93 190 | RETURN t91 191 | FUNCTION safe_mul : 192 | PARAM v_lhs_mul 193 | PARAM v_rhs_mul 194 | t94 := #0 195 | t97 := #0 196 | t100 := #0 197 | t103 := v_lhs_mul 198 | t104 := #0 199 | IF t103 > t104 GOTO label101 200 | GOTO label102 201 | LABEL label101 : 202 | t100 := #1 203 | LABEL label102 : 204 | IF t100 != #0 GOTO label18 205 | GOTO label99 206 | LABEL label18 : 207 | t105 := #0 208 | t108 := v_rhs_mul 209 | t109 := #0 210 | IF t108 > t109 GOTO label106 211 | GOTO label107 212 | LABEL label106 : 213 | t105 := #1 214 | LABEL label107 : 215 | IF t105 != #0 GOTO label17 216 | GOTO label99 217 | LABEL label17 : 218 | t110 := #0 219 | t113 := v_lhs_mul 220 | t115 := #2147483647 221 | t116 := v_rhs_mul 222 | t114 := t115 / t116 223 | IF t113 > t114 GOTO label111 224 | GOTO label112 225 | LABEL label111 : 226 | t110 := #1 227 | LABEL label112 : 228 | IF t110 != #0 GOTO label98 229 | GOTO label99 230 | LABEL label98 : 231 | t97 := #1 232 | LABEL label99 : 233 | IF t97 != #0 GOTO label95 234 | GOTO label16 235 | LABEL label16 : 236 | t117 := #0 237 | t120 := #0 238 | t123 := v_lhs_mul 239 | t124 := #0 240 | IF t123 > t124 GOTO label121 241 | GOTO label122 242 | LABEL label121 : 243 | t120 := #1 244 | LABEL label122 : 245 | IF t120 != #0 GOTO label20 246 | GOTO label119 247 | LABEL label20 : 248 | t125 := #0 249 | t128 := v_rhs_mul 250 | t129 := #0 251 | IF t128 <= t129 GOTO label126 252 | GOTO label127 253 | LABEL label126 : 254 | t125 := #1 255 | LABEL label127 : 256 | IF t125 != #0 GOTO label19 257 | GOTO label119 258 | LABEL label19 : 259 | t130 := #0 260 | t133 := v_rhs_mul 261 | t136 := #-2147483648 262 | t137 := v_lhs_mul 263 | t135 := t136 / t137 264 | t134 := #0 - t135 265 | IF t133 < t134 GOTO label131 266 | GOTO label132 267 | LABEL label131 : 268 | t130 := #1 269 | LABEL label132 : 270 | IF t130 != #0 GOTO label118 271 | GOTO label119 272 | LABEL label118 : 273 | t117 := #1 274 | LABEL label119 : 275 | IF t117 != #0 GOTO label95 276 | GOTO label15 277 | LABEL label15 : 278 | t138 := #0 279 | t141 := #0 280 | t144 := v_lhs_mul 281 | t145 := #0 282 | IF t144 <= t145 GOTO label142 283 | GOTO label143 284 | LABEL label142 : 285 | t141 := #1 286 | LABEL label143 : 287 | IF t141 != #0 GOTO label22 288 | GOTO label140 289 | LABEL label22 : 290 | t146 := #0 291 | t149 := v_rhs_mul 292 | t150 := #0 293 | IF t149 > t150 GOTO label147 294 | GOTO label148 295 | LABEL label147 : 296 | t146 := #1 297 | LABEL label148 : 298 | IF t146 != #0 GOTO label21 299 | GOTO label140 300 | LABEL label21 : 301 | t151 := #0 302 | t154 := v_lhs_mul 303 | t157 := #-2147483648 304 | t158 := v_rhs_mul 305 | t156 := t157 / t158 306 | t155 := #0 - t156 307 | IF t154 < t155 GOTO label152 308 | GOTO label153 309 | LABEL label152 : 310 | t151 := #1 311 | LABEL label153 : 312 | IF t151 != #0 GOTO label139 313 | GOTO label140 314 | LABEL label139 : 315 | t138 := #1 316 | LABEL label140 : 317 | IF t138 != #0 GOTO label95 318 | GOTO label14 319 | LABEL label14 : 320 | t159 := #0 321 | t162 := #0 322 | t165 := v_lhs_mul 323 | t166 := #0 324 | IF t165 <= t166 GOTO label163 325 | GOTO label164 326 | LABEL label163 : 327 | t162 := #1 328 | LABEL label164 : 329 | IF t162 != #0 GOTO label25 330 | GOTO label161 331 | LABEL label25 : 332 | t167 := #0 333 | t170 := v_rhs_mul 334 | t171 := #0 335 | IF t170 <= t171 GOTO label168 336 | GOTO label169 337 | LABEL label168 : 338 | t167 := #1 339 | LABEL label169 : 340 | IF t167 != #0 GOTO label24 341 | GOTO label161 342 | LABEL label24 : 343 | t172 := #0 344 | t175 := v_lhs_mul 345 | t176 := #0 346 | IF t175 != t176 GOTO label173 347 | GOTO label174 348 | LABEL label173 : 349 | t172 := #1 350 | LABEL label174 : 351 | IF t172 != #0 GOTO label23 352 | GOTO label161 353 | LABEL label23 : 354 | t177 := #0 355 | t180 := v_rhs_mul 356 | t182 := #2147483647 357 | t183 := v_lhs_mul 358 | t181 := t182 / t183 359 | IF t180 < t181 GOTO label178 360 | GOTO label179 361 | LABEL label178 : 362 | t177 := #1 363 | LABEL label179 : 364 | IF t177 != #0 GOTO label160 365 | GOTO label161 366 | LABEL label160 : 367 | t159 := #1 368 | LABEL label161 : 369 | IF t159 != #0 GOTO label95 370 | GOTO label96 371 | LABEL label95 : 372 | t94 := #1 373 | LABEL label96 : 374 | IF t94 != #0 GOTO label0 375 | GOTO label13 376 | t184 := v_lhs_mul 377 | RETURN t184 378 | LABEL label13 : 379 | t186 := v_lhs_mul 380 | t187 := v_rhs_mul 381 | t185 := t186 * t187 382 | RETURN t185 383 | FUNCTION safe_div : 384 | PARAM v_lhs_div 385 | PARAM v_rhs_div 386 | t188 := #0 387 | t191 := #0 388 | t194 := v_rhs_div 389 | t195 := #0 390 | IF t194 == t195 GOTO label192 391 | GOTO label193 392 | LABEL label192 : 393 | t191 := #1 394 | LABEL label193 : 395 | IF t191 != #0 GOTO label189 396 | GOTO label27 397 | LABEL label27 : 398 | t196 := #0 399 | t199 := #0 400 | t202 := v_lhs_div 401 | t204 := #-2147483648 402 | t203 := #0 - t204 403 | IF t202 == t203 GOTO label200 404 | GOTO label201 405 | LABEL label200 : 406 | t199 := #1 407 | LABEL label201 : 408 | IF t199 != #0 GOTO label28 409 | GOTO label198 410 | LABEL label28 : 411 | t205 := #0 412 | t208 := v_rhs_div 413 | t210 := #1 414 | t209 := #0 - t210 415 | IF t208 == t209 GOTO label206 416 | GOTO label207 417 | LABEL label206 : 418 | t205 := #1 419 | LABEL label207 : 420 | IF t205 != #0 GOTO label197 421 | GOTO label198 422 | LABEL label197 : 423 | t196 := #1 424 | LABEL label198 : 425 | IF t196 != #0 GOTO label189 426 | GOTO label190 427 | LABEL label189 : 428 | t188 := #1 429 | LABEL label190 : 430 | IF t188 != #0 GOTO label0 431 | GOTO label26 432 | t211 := v_lhs_div 433 | RETURN t211 434 | LABEL label26 : 435 | t213 := v_lhs_div 436 | t214 := v_rhs_div 437 | t212 := t213 / t214 438 | RETURN t212 439 | FUNCTION i_func_0 : 440 | PARAM v_i_func_0_i_0 441 | PARAM v_i_func_0_i_1 442 | PARAM v_i_func_0_i_2 443 | DEC t215 4 444 | v_i_L0 := &t215 445 | DEC t216 4 446 | v_i_L1 := &t216 447 | DEC t217 4 448 | v_i_L2 := &t217 449 | t218 := v_i_func_0_i_2 450 | t219 := #0 451 | IF t218 > t219 GOTO label29 452 | t221 := #2086928948 453 | t220 := #0 - t221 454 | RETURN t220 455 | GOTO label30 456 | LABEL label29 : 457 | t223 := v_i_func_0_i_2 458 | t224 := #1 459 | t222 := t223 - t224 460 | v_i_func_0_i_2 := t222 461 | LABEL label30 : 462 | t226 := v_i_func_0_i_2 463 | t227 := #3 464 | t225 := t226 - t227 465 | v_i_func_0_i_2 := t225 466 | t230 := #51984868 467 | t231 := v_i_func_0_i_0 468 | t232 := v_i_func_0_i_2 469 | ARG t232 470 | ARG t231 471 | ARG t230 472 | t229 := CALL i_func_0 473 | t235 := #2119278282 474 | t234 := #0 - t235 475 | t236 := v_i_func_0_i_1 476 | t237 := v_i_func_0_i_2 477 | ARG t237 478 | ARG t236 479 | ARG t234 480 | t233 := CALL i_func_0 481 | t238 := v_i_func_0_i_2 482 | ARG t238 483 | ARG t233 484 | ARG t229 485 | t228 := CALL i_func_0 486 | v_i_L0 := t228 487 | t240 := #0 488 | t243 := #2045084602 489 | t245 := #1502844940 490 | t244 := #0 - t245 491 | IF t243 < t244 GOTO label241 492 | GOTO label242 493 | LABEL label241 : 494 | t240 := #1 495 | LABEL label242 : 496 | v_i_func_0_i_0 := t240 497 | t239 := v_i_func_0_i_0 498 | v_i_L1 := t239 499 | t248 := v_i_L0 500 | v_i_func_0_i_1 := t248 501 | t247 := v_i_func_0_i_1 502 | v_i_func_0_i_0 := t247 503 | t246 := v_i_func_0_i_0 504 | v_i_L2 := t246 505 | t250 := v_i_func_0_i_2 506 | t251 := #1 507 | t249 := t250 - t251 508 | v_i_func_0_i_2 := t249 509 | t253 := v_i_func_0_i_1 510 | t254 := v_i_L0 511 | t255 := v_i_func_0_i_2 512 | ARG t255 513 | ARG t254 514 | ARG t253 515 | t252 := CALL i_func_0 516 | v_i_func_0_i_0 := t252 517 | t257 := v_i_func_0_i_2 518 | t258 := #1 519 | t256 := t257 - t258 520 | v_i_func_0_i_2 := t256 521 | t260 := v_i_func_0_i_1 522 | t261 := v_i_L0 523 | t262 := v_i_func_0_i_2 524 | ARG t262 525 | ARG t261 526 | ARG t260 527 | t259 := CALL i_func_0 528 | v_i_func_0_i_0 := t259 529 | t263 := #0 530 | t266 := v_i_func_0_i_1 531 | t267 := v_i_L0 532 | IF t266 >= t267 GOTO label264 533 | GOTO label265 534 | LABEL label264 : 535 | t263 := #1 536 | LABEL label265 : 537 | v_i_func_0_i_0 := t263 538 | t268 := v_i_L0 539 | WRITE t268 540 | t269 := v_i_L1 541 | WRITE t269 542 | t270 := v_i_L2 543 | WRITE t270 544 | t272 := #0 545 | t275 := v_i_func_0_i_1 546 | t276 := v_i_L0 547 | IF t275 >= t276 GOTO label273 548 | GOTO label274 549 | LABEL label273 : 550 | t272 := #1 551 | LABEL label274 : 552 | v_i_func_0_i_0 := t272 553 | t271 := v_i_func_0_i_0 554 | RETURN t271 555 | FUNCTION top_caller : 556 | PARAM v_top_caller_i_0 557 | DEC t277 4 558 | v_i_L4 := &t277 559 | DEC t278 4 560 | v_i_L5 := &t278 561 | DEC t279 4 562 | v_i_L6 := &t279 563 | DEC t280 4 564 | v_i_L3 := &t280 565 | DEC t281 4 566 | v_i_L7 := &t281 567 | DEC t282 4 568 | v_i_L8 := &t282 569 | t283 := v_top_caller_i_0 570 | t284 := #0 571 | IF t283 > t284 GOTO label31 572 | t285 := #311043960 573 | RETURN t285 574 | GOTO label32 575 | LABEL label31 : 576 | t287 := v_top_caller_i_0 577 | t288 := #1 578 | t286 := t287 - t288 579 | v_top_caller_i_0 := t286 580 | LABEL label32 : 581 | t290 := v_top_caller_i_0 582 | t291 := #1 583 | t289 := t290 - t291 584 | v_top_caller_i_0 := t289 585 | t293 := v_top_caller_i_0 586 | ARG t293 587 | t292 := CALL top_caller 588 | v_i_L4 := t292 589 | t294 := #557002076 590 | v_i_L5 := t294 591 | t295 := #304704810 592 | v_i_L6 := t295 593 | t297 := #0 594 | t300 := v_i_L5 595 | IF t300 != #0 GOTO label298 596 | GOTO label33 597 | LABEL label33 : 598 | t301 := v_i_L6 599 | IF t301 != #0 GOTO label298 600 | GOTO label299 601 | LABEL label298 : 602 | t297 := #1 603 | LABEL label299 : 604 | v_i_L4 := t297 605 | t296 := v_i_L4 606 | v_i_L3 := t296 607 | t303 := #0 608 | t306 := v_i_L5 609 | t307 := #1320384247 610 | IF t306 <= t307 GOTO label304 611 | GOTO label305 612 | LABEL label304 : 613 | t303 := #1 614 | LABEL label305 : 615 | v_i_L4 := t303 616 | t302 := v_i_L4 617 | v_i_L7 := t302 618 | t309 := #0 619 | t312 := v_i_L5 620 | t313 := v_i_L6 621 | IF t312 != t313 GOTO label310 622 | GOTO label311 623 | LABEL label310 : 624 | t309 := #1 625 | LABEL label311 : 626 | v_i_L4 := t309 627 | t308 := v_i_L4 628 | v_i_L8 := t308 629 | t315 := v_top_caller_i_0 630 | t316 := #1 631 | t314 := t315 - t316 632 | v_top_caller_i_0 := t314 633 | t318 := v_i_L5 634 | t319 := v_i_L6 635 | t320 := v_top_caller_i_0 636 | ARG t320 637 | ARG t319 638 | ARG t318 639 | t317 := CALL i_func_0 640 | v_i_L4 := t317 641 | t321 := v_i_L4 642 | WRITE t321 643 | t322 := v_i_L5 644 | WRITE t322 645 | t323 := v_i_L6 646 | WRITE t323 647 | t324 := v_i_L3 648 | WRITE t324 649 | t325 := v_i_L7 650 | WRITE t325 651 | t326 := v_i_L8 652 | WRITE t326 653 | t328 := v_top_caller_i_0 654 | t329 := #1 655 | t327 := t328 - t329 656 | v_top_caller_i_0 := t327 657 | t332 := v_top_caller_i_0 658 | ARG t332 659 | t331 := CALL top_caller 660 | v_i_L4 := t331 661 | t330 := v_i_L4 662 | RETURN t330 663 | FUNCTION main : 664 | t333 := #10 665 | ARG t333 666 | t0 := CALL top_caller 667 | t334 := #0 668 | RETURN t334 669 | -------------------------------------------------------------------------------- /py-irsim/irsim.py: -------------------------------------------------------------------------------- 1 | # uncompyle6 version 3.6.7 2 | # Python bytecode 2.7 (62211) 3 | # Decompiled from: Python 3.8.2 (default, Apr 27 2020, 15:53:34) 4 | # [GCC 9.3.0] 5 | # Embedded file name: irsim.py 6 | # Compiled at: 2014-09-01 14:20:18 7 | import sys, os, platform 8 | from PyQt4.QtCore import * 9 | from PyQt4.QtGui import * 10 | import ui_mainwindow, resources_rc 11 | __version__ = '1.0.2' 12 | 13 | class IRSyntaxError(Exception): 14 | pass 15 | 16 | 17 | class DuplicatedLabelError(Exception): 18 | pass 19 | 20 | 21 | class UndefinedLabelError(Exception): 22 | pass 23 | 24 | 25 | class DuplicatedVariableError(Exception): 26 | pass 27 | 28 | 29 | class CurrentFunctionNoneError(Exception): 30 | pass 31 | 32 | 33 | class IRSim(QMainWindow, ui_mainwindow.Ui_MainWindow): 34 | 35 | def __init__(self, parent=None): 36 | super(IRSim, self).__init__(parent) 37 | self.cyanBrush = QBrush(Qt.cyan) 38 | self.yellowBrush = QBrush(Qt.yellow) 39 | self.noBrush = QBrush() 40 | self.setupUi(self) 41 | self.rowLabel = QLabel() 42 | self.rowLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) 43 | self.statusBar().addPermanentWidget(self.rowLabel) 44 | self.initialize() 45 | self.connect(self.actionQuit, SIGNAL('triggered()'), self.close) 46 | self.connect(self.action_Open, SIGNAL('triggered()'), self.fileOpen) 47 | self.connect(self.actionRun, SIGNAL('triggered()'), self.run) 48 | self.connect(self.actionStop, SIGNAL('triggered()'), self.stop) 49 | self.connect(self.actionStep, SIGNAL('triggered()'), self.step) 50 | self.connect(self.actionAbout, SIGNAL('triggered()'), self.helpAbout) 51 | self.connect(self.codeList, SIGNAL('currentRowChanged(int)'), self.updateRowLabel) 52 | 53 | def fileOpen(self): 54 | if not self.okToContinue(): 55 | return 56 | else: 57 | dir = '.' if self.filename is None else os.path.dirname(self.filename) 58 | fname = unicode(QFileDialog.getOpenFileName(self, 'IR Simulator - Open IR file', dir, 'IR files (*.ir)')) 59 | if fname: 60 | self.initialize() 61 | self.loadFile(fname) 62 | return 63 | 64 | def initialize(self): 65 | self.filename = None 66 | self.ip = -1 67 | self.entranceIP = -1 68 | self.pauseRunning = False 69 | self.offset = 0 70 | self.instrCnt = 0 71 | self.codes = list() 72 | self.mem = None 73 | self.functionDict = dict() 74 | self.currentFunction = None 75 | self.symTable = dict() 76 | self.labelTable = dict() 77 | self.callStack = list() 78 | self.argumentStack = list() 79 | self.codeList.clear() 80 | self.watchTable.setRowCount(0) 81 | self.watchTable.clearContents() 82 | self.console.clear() 83 | self.updateStatus(None) 84 | self.displayFunction = list() 85 | return 86 | 87 | def loadFile(self, fname): 88 | fp = open(fname, 'r') 89 | lineno = 0 90 | for line in fp: 91 | if line.isspace(): 92 | continue 93 | if self.sanity_check(line, lineno): 94 | self.codeList.addItem(line.strip().replace('\t', ' ')) 95 | else: 96 | break 97 | lineno += 1 98 | else: 99 | self.filename = fname 100 | self.lineno = lineno 101 | 102 | fp.close() 103 | if self.entranceIP == -1: 104 | QMessageBox.critical(self, 'Error', "Cannot find program entrance. Please make sure the 'main' function does exist.") 105 | if self.filename is None or not self.labelCheck() or self.offset > 1048576 or self.entranceIP == -1: 106 | self.updateStatus('Loading failed.') 107 | self.initialize() 108 | return 109 | else: 110 | self.mem = [ 111 | 0] * 262144 112 | self.displayFunction.append('main') 113 | self.updateStatus('File loaded successfully.') 114 | return 115 | 116 | def run(self): 117 | self.stop() 118 | self.ip = self.entranceIP 119 | while True: 120 | if self.ip < 0 or self.ip >= len(self.codes): 121 | error_code = 3 122 | break 123 | code = self.codes[self.ip] 124 | error_code = self.execute_code(code) 125 | if error_code > 0: 126 | break 127 | self.ip += 1 128 | 129 | if error_code == 1: 130 | QMessageBox.information(self, 'Finish', 'Program has exited gracefully.\nTotal instructions = %d' % self.instrCnt) 131 | self.updateStatus('Simulation OK. Instruction count = %d' % self.instrCnt) 132 | elif error_code == 2: 133 | QMessageBox.critical(self, 'Error', 'An error occurred at line %d: Illegal memory access. \nIf this message keeps popping out, please reload the source file' % (self.ip + 1)) 134 | self.updateStatus('Simulation failed: Memory access out of bound.') 135 | elif error_code == 3: 136 | QMessageBox.warning(self, 'Warning', 'Program Counter goes out of bound. The running program will be terminated instantly.') 137 | self.updateStatus('Simulation failed: PC error.') 138 | self.watchTable.setRowCount(0) 139 | self.displayFunction.append('main') 140 | self.displayWatchTable_ZXR() 141 | self.ip = -1 142 | 143 | def stop(self): 144 | if self.ip != -1: 145 | self.codeList.item(self.ip).setBackground(self.noBrush) 146 | self.ip = -1 147 | self.instrCnt = 0 148 | self.pauseRunning = False 149 | self.watchTable.setRowCount(0) 150 | self.mem = [0] * 262144 151 | self.callStack = list() 152 | self.argumentStack = list() 153 | self.displayFunction = list() 154 | self.displayFunction.append('main') 155 | self.displayWatchTable_ZXR() 156 | self.codeList.setCurrentRow(-1) 157 | self.console.clear() 158 | 159 | def step(self): 160 | if self.ip == -1: 161 | self.stop() 162 | self.pauseRunning = True 163 | self.ip = self.entranceIP - 1 164 | else: 165 | self.codeList.item(self.ip).setBackground(self.noBrush) 166 | self.ip += 1 167 | if self.ip < 0 or self.ip >= len(self.codes): 168 | QMessageBox.warning(self, 'Warning', 'Program Counter goes out of bound. The running program will be terminated instantly.') 169 | self.updateStatus('Simulation failed: PC error.') 170 | self.ip = -1 171 | self.pauseRunning = False 172 | return 173 | code = self.codes[self.ip] 174 | error_code = self.execute_code(code) 175 | if error_code == 1: 176 | QMessageBox.information(self, 'Finish', 'Program has exited gracefully.\nTotal instructions = %d' % self.instrCnt) 177 | self.updateStatus('Simulation OK. Instruction count = %d' % self.instrCnt) 178 | self.ip = -1 179 | self.pauseRunning = False 180 | elif error_code == 2: 181 | QMessageBox.critical(self, 'Error', 'An error occurred at line %d: Illegal memory access' % (self.ip + 1)) 182 | self.updateStatus('Simulation failed: Memory access out of bound') 183 | self.ip = -1 184 | self.pauseRunning = False 185 | else: 186 | self.codeList.item(self.ip).setBackground(self.cyanBrush) 187 | self.codeList.setCurrentRow(self.ip) 188 | self.watchTable.setRowCount(0) 189 | self.displayWatchTable_ZXR() 190 | 191 | def helpAbout(self): 192 | QMessageBox.about(self, 'About IR Simulator', ('IR Simulator v {0}\n\t\t\t\t

Copyright © 2012 Grieve. \n\t\t\t\tAll rights reserved.\n\t\t\t\t

This application can be used to simulate the IR \n\t\t\t\tdesigned for the Compiler course here at NJU.\n\t\t\t\t

Python {1} - Qt {2} - PyQt {3} on {4}').format(__version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) 193 | 194 | def okToContinue(self): 195 | if self.ip != -1: 196 | reply = QMessageBox.question(self, 'IR Simulator - Warning', 'You are running a file currently. Stop the running and proceed?', QMessageBox.Yes | QMessageBox.No) 197 | if reply == QMessageBox.No: 198 | return False 199 | self.ip = -1 200 | return True 201 | 202 | def updateStatus(self, message): 203 | if message: 204 | self.statusBar().showMessage(message, 5000) 205 | if self.filename is None: 206 | self.setWindowTitle('IR Simulator') 207 | self.actionRun.setEnabled(False) 208 | self.actionStop.setEnabled(False) 209 | self.actionStep.setEnabled(False) 210 | else: 211 | self.setWindowTitle(('IR Simulator - {0}').format(os.path.basename(self.filename))) 212 | self.actionRun.setEnabled(True) 213 | self.actionStop.setEnabled(True) 214 | self.actionStep.setEnabled(True) 215 | return 216 | 217 | def updateRowLabel(self): 218 | row = self.codeList.currentRow() 219 | if row >= 0: 220 | self.rowLabel.setText('Line %d' % (row + 1)) 221 | else: 222 | self.rowLabel.setText('') 223 | 224 | def sanity_check(self, code, lineno): 225 | strs = code.split() 226 | relops = ['>', '<', '>=', '<=', '==', '!='] 227 | arithops = ['+', '-', '*', '/'] 228 | try: 229 | if strs[0] == 'LABEL' or strs[0] == 'FUNCTION': 230 | if len(strs) != 3 or strs[2] != ':': 231 | raise IRSyntaxError 232 | if strs[1] in self.labelTable: 233 | raise DuplicatedLabelError 234 | self.labelTable[strs[1]] = lineno 235 | if strs[1] == 'main': 236 | if strs[0] == 'LABEL': 237 | raise IRSyntaxError 238 | self.entranceIP = lineno 239 | if strs[0] == 'FUNCTION': 240 | self.currentFunction = strs[1] 241 | self.functionDict[strs[1]] = list() 242 | self.codes.append(('LABEL', strs[1])) 243 | else: 244 | if self.currentFunction == None: 245 | raise CurrentFunctionNoneError 246 | if strs[0] == 'GOTO': 247 | if len(strs) != 2: 248 | raise IRSyntaxError 249 | self.codes.append(('GOTO', strs[1])) 250 | elif strs[0] == 'RETURN' or strs[0] == 'READ' or strs[0] == 'WRITE' or strs[0] == 'ARG' or strs[0] == 'PARAM': 251 | if len(strs) != 2: 252 | raise IRSyntaxError 253 | if (strs[0] == 'READ' or strs[0] == 'PARAM') and not strs[1][0].isalpha(): 254 | raise IRSyntaxError 255 | self.tableInsert(strs[1]) 256 | self.codes.append((strs[0], strs[1])) 257 | elif strs[0] == 'DEC': 258 | if len(strs) != 3 or int(strs[2]) % 4 != 0: 259 | raise IRSyntaxError 260 | if strs[1] in self.symTable: 261 | raise DuplicatedVariableError 262 | self.tableInsert(strs[1], int(strs[2]), True) 263 | self.codes.append('DEC') 264 | elif strs[0] == 'IF': 265 | if len(strs) != 6 or strs[4] != 'GOTO' or strs[2] not in relops: 266 | raise IRSyntaxError 267 | self.tableInsert(strs[1]) 268 | self.tableInsert(strs[3]) 269 | self.codes.append(('IF', strs[1], strs[2], strs[3], strs[5])) 270 | else: 271 | if strs[1] != ':=' or len(strs) < 3: 272 | raise IRSyntaxError 273 | if strs[0][0] == '&' or strs[0][0] == '#': 274 | raise IRSyntaxError 275 | self.tableInsert(strs[0]) 276 | if strs[2] == 'CALL': 277 | if len(strs) != 4: 278 | raise IRSyntaxError 279 | self.codes.append(('CALL', strs[0], strs[3])) 280 | elif len(strs) == 3: 281 | self.tableInsert(strs[2]) 282 | self.codes.append(('MOV', strs[0], strs[2])) 283 | elif len(strs) == 5 and strs[3] in arithops: 284 | self.tableInsert(strs[2]) 285 | self.tableInsert(strs[4]) 286 | self.codes.append(('ARITH', strs[0], strs[2], strs[3], strs[4])) 287 | else: 288 | raise IRSyntaxError 289 | except (IRSyntaxError, ValueError): 290 | QMessageBox.critical(self, 'Error', 'Syntax error at line %d:\n\n%s' % (lineno + 1, code)) 291 | return False 292 | except DuplicatedLabelError: 293 | QMessageBox.critical(self, 'Error', 'Duplicated label %s at line %d:\n\n%s' % (strs[1], lineno + 1, code)) 294 | return False 295 | except DuplicatedVariableError: 296 | QMessageBox.critical(self, 'Error', 'Duplicated variable %s at line %d:\n\n%s' % (strs[1], lineno + 1, code)) 297 | return False 298 | except CurrentFunctionNoneError: 299 | QMessageBox.critical(self, 'Error', 'Line %d does not belong to any function:\n\n%s' % (lineno + 1, code)) 300 | return False 301 | 302 | return True 303 | 304 | def labelCheck(self): 305 | try: 306 | for i in range(self.lineno): 307 | code = unicode(self.codeList.item(i).text()) 308 | strs = code.split() 309 | if strs[0] == 'GOTO': 310 | if strs[1] not in self.labelTable: 311 | raise UndefinedLabelError 312 | elif strs[0] == 'IF': 313 | if strs[5] not in self.labelTable: 314 | raise UndefinedLabelError 315 | elif len(strs) > 2 and strs[2] == 'CALL': 316 | if strs[3] not in self.labelTable: 317 | raise UndefinedLabelError 318 | 319 | except UndefinedLabelError: 320 | QMessageBox.critical(self, 'Error', 'Undefined label at line %d:\n\n%s' % (i + 1, code)) 321 | return False 322 | 323 | return True 324 | 325 | def tableInsert(self, var, size=4, array=False): 326 | if var.isdigit(): 327 | raise IRSyntaxError 328 | if var[0] == '&' or var[0] == '*': 329 | var = var[1:] 330 | elif var[0] == '#': 331 | test = int(var[1:]) 332 | return 333 | if var in self.symTable: 334 | return 335 | self.functionDict[self.currentFunction].append(var) 336 | if self.currentFunction == 'main': 337 | self.symTable[var] = ( 338 | self.offset, size, array) 339 | self.offset += size 340 | else: 341 | self.symTable[var] = ( 342 | -1, size, array) 343 | 344 | def getValue(self, var): 345 | if var[0] == '#': 346 | return int(var[1:]) 347 | else: 348 | if var[0] == '&': 349 | return self.symTable[var[1:]][0] 350 | if var[0] == '*': 351 | return self.mem[(self.mem[(self.symTable[var[1:]][0] / 4)] / 4)] 352 | return self.mem[(self.symTable[var][0] / 4)] 353 | 354 | def displayWatchTable(self): 355 | for row, key in enumerate(self.symTable.keys()): 356 | self.watchTable.insertRow(row) 357 | item = QTableWidgetItem(key) 358 | item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) 359 | self.watchTable.setItem(row, 0, item) 360 | if self.symTable[key][0] < 0: 361 | item = QTableWidgetItem('N/A') 362 | elif self.symTable[key][1] > 4: 363 | strs = str(self.mem[self.symTable[key][0] / 4:self.symTable[key][0] / 4 + self.symTable[key][1] / 4]) 364 | item = QTableWidgetItem(strs) 365 | else: 366 | item = QTableWidgetItem(str(self.mem[(self.symTable[key][0] / 4)])) 367 | item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) 368 | self.watchTable.setItem(row, 1, item) 369 | 370 | self.watchTable.sortItems(0) 371 | 372 | def displayWatchTable_ZXR(self): 373 | row = 0 374 | function = self.displayFunction.pop() 375 | for key in self.functionDict[function]: 376 | self.watchTable.insertRow(row) 377 | item = QTableWidgetItem(key) 378 | item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) 379 | self.watchTable.setItem(row, 0, item) 380 | if self.symTable[key][0] < 0: 381 | item = QTableWidgetItem('N/A') 382 | elif self.symTable[key][1] > 4: 383 | strs = str(self.mem[self.symTable[key][0] / 4:self.symTable[key][0] / 4 + self.symTable[key][1] / 4]) 384 | item = QTableWidgetItem(strs) 385 | else: 386 | item = QTableWidgetItem(str(self.mem[(self.symTable[key][0] / 4)])) 387 | item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) 388 | self.watchTable.setItem(row, 1, item) 389 | row += 1 390 | 391 | self.watchTable.sortItems(0) 392 | self.displayFunction.append(function) 393 | 394 | def execute_code(self, code): 395 | self.instrCnt += 1 396 | try: 397 | if code[0] == 'READ': 398 | result, ok = QInputDialog.getInteger(self, 'IR Simulator - Read', 'Please enter an integral value for %s' % code[1], 0) 399 | if ok: 400 | self.mem[self.symTable[code[1]][0] / 4] = result 401 | elif code[0] == 'WRITE': 402 | self.console.append(str(self.getValue(code[1]))) 403 | elif code[0] == 'GOTO': 404 | self.ip = self.labelTable[code[1]] 405 | elif code[0] == 'IF': 406 | value1 = self.getValue(code[1]) 407 | value2 = self.getValue(code[3]) 408 | if eval(str(value1) + code[2] + str(value2)): 409 | self.ip = self.labelTable[code[4]] 410 | elif code[0] == 'MOV': 411 | value = self.getValue(code[2]) 412 | if code[1][0] == '*': 413 | self.mem[self.mem[(self.symTable[code[1][1:]][0] / 4)] / 4] = value 414 | else: 415 | self.mem[self.symTable[code[1]][0] / 4] = value 416 | elif code[0] == 'ARITH': 417 | value1 = self.getValue(code[2]) 418 | value2 = self.getValue(code[4]) 419 | self.mem[self.symTable[code[1]][0] / 4] = eval(str(value1) + code[3] + str(value2)) 420 | elif code[0] == 'RETURN': 421 | if len(self.callStack) == 0: 422 | return 1 423 | returnValue = self.getValue(code[1]) 424 | stackItem = self.callStack.pop() 425 | self.ip = stackItem[0] 426 | for key in stackItem[2].keys(): 427 | self.symTable[key] = stackItem[2][key] 428 | 429 | self.offset = stackItem[3] 430 | self.mem[self.symTable[stackItem[1]][0] / 4] = returnValue 431 | self.displayFunction.pop() 432 | elif code[0] == 'CALL': 433 | oldAddrs = dict() 434 | oldOffset = self.offset 435 | for key in self.functionDict[code[2]]: 436 | oldAddrs[key] = self.symTable[key] 437 | self.symTable[key] = (self.getNewAddr(self.symTable[key][1]), self.symTable[key][1], self.symTable[key][2]) 438 | 439 | self.callStack.append((self.ip, code[1], oldAddrs, oldOffset)) 440 | self.ip = self.labelTable[code[2]] 441 | self.displayFunction.append(code[2]) 442 | elif code[0] == 'ARG': 443 | self.argumentStack.append(self.getValue(code[1])) 444 | elif code[0] == 'PARAM': 445 | self.mem[self.symTable[code[1]][0] / 4] = self.argumentStack.pop() 446 | except IndexError: 447 | return 2 448 | 449 | return 0 450 | 451 | def getNewAddr(self, size): 452 | ret = self.offset 453 | self.offset = self.offset + size 454 | return ret 455 | 456 | 457 | app = QApplication(sys.argv) 458 | app.setOrganizationName('Nanjing University') 459 | app.setApplicationName('IR Simulator') 460 | app.setWindowIcon(QIcon(':/icon.png')) 461 | app.setStyle('Plastique') 462 | form = IRSim() 463 | form.show() 464 | app.exec_() 465 | # okay decompiling irsim.pyc 466 | -------------------------------------------------------------------------------- /cxx-irsim/irsim.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // #define LOGIR 6 | // #define DEBUG 7 | #define IGNORE_CERTAIN_EXCEPTION 8 | 9 | #ifdef DEBUG 10 | # define dbgs(...) fprintf(stdout, __VA_ARGS__) 11 | #else 12 | # define dbgs(fmt, ...) 13 | #endif 14 | 15 | #include "irsim.h" 16 | 17 | namespace irsim { 18 | 19 | /* clang-format off */ 20 | std::map opc_to_string{ 21 | {Opc::abort, "abort"}, {Opc::helper, "helper"}, 22 | {Opc::alloca, "alloca"}, {Opc::la, "la"}, 23 | {Opc::ld, "ld"}, {Opc::st, "st"}, {Opc::li, "li"}, 24 | {Opc::mov, "mov"}, {Opc::add, "add"}, {Opc::sub, "sub"}, 25 | {Opc::mul, "mul"}, {Opc::div, "div"}, {Opc::jmp, "jmp"}, 26 | {Opc::br, "br"}, {Opc::slt, "slt"}, {Opc::sle, "sle"}, 27 | {Opc::seq, "seq"}, {Opc::sge, "sge"}, {Opc::sgt, "sgt"}, 28 | {Opc::sne, "sne"}, {Opc::call, "call"}, {Opc::ret, "ret"}, 29 | {Opc::mfcr, "mfcr"}, {Opc::mtcr, "mtcr"}, 30 | {Opc::quit, "quit"}, {Opc::mark, "mark"}, 31 | }; 32 | /* clang-format on */ 33 | 34 | int Program::run(int *eip) { 35 | /* clang-format off */ 36 | int _start[] = { 37 | (int)Opc::alloca, 1, 38 | (int)Opc::call, ptr_lo(eip), ptr_hi(eip), 39 | (int)Opc::mfcr, 0, CR_RET, 40 | (int)Opc::quit, 0, 41 | }; 42 | /* clang-format on */ 43 | 44 | eip = &_start[0]; 45 | 46 | while (true) { 47 | #ifdef DEBUG 48 | auto oldeip = eip; 49 | #endif 50 | if (eip == nullptr) { 51 | exception = Exception::IF; 52 | return -1; 53 | } 54 | 55 | int opc = *eip++; 56 | 57 | #ifdef DEBUG 58 | dbgs("stack:\n"); 59 | for (auto d = 0u; d < stack.size(); d++) { 60 | auto &s = stack[d]; 61 | constexpr int step = 6; 62 | for (auto i = 0u; i < s.size(); i += step) { 63 | if (i == 0) 64 | dbgs("%02d:%02d:", d, i); 65 | else 66 | dbgs(" :%02d:", i); 67 | for (auto j = i; j < i + step && j < s.size(); 68 | j++) { 69 | dbgs(" %08x", s[j]); 70 | } 71 | dbgs("\n"); 72 | } 73 | } 74 | dbgs("crs: "); 75 | for (auto i = 0u; i < ctrl_regs.size(); i++) 76 | dbgs(" %08x", ctrl_regs[i]); 77 | dbgs("\n"); 78 | #endif 79 | 80 | switch ((Opc)opc) { 81 | case Opc::abort: 82 | exception = Exception::ABORT; 83 | return -1; 84 | case Opc::helper: { 85 | int ptrlo = *eip++; 86 | int ptrhi = *eip++; 87 | int nr_args = *eip++; 88 | using F = void(int *); 89 | F *f = lohi_to_ptr(ptrlo, ptrhi); 90 | f(eip); 91 | eip += nr_args; 92 | dbgs("%p: helper %p\n", oldeip, (void *)f); 93 | } break; 94 | case Opc::la: { 95 | int to = *eip++; 96 | int from = *eip++; 97 | stack.back().at(to) = 98 | ((stack.back().begin() + from) - memory.begin()) * 99 | 4; 100 | dbgs("%p: la %d, %d\n", oldeip, to, from); 101 | } break; 102 | case Opc::ld: { 103 | int to = *eip++; 104 | int from = stack.back().at(*eip++); 105 | dbgs("%p: ld %d, (%d)\n", oldeip, to, from); 106 | if (memory.size() * 4 <= (size_t)from) { 107 | #ifndef IGNORE_CERTAIN_EXCEPTION 108 | exception = Exception::LOAD; 109 | return -1; 110 | #endif 111 | } else { 112 | uint8_t *from_ptr = (uint8_t *)&memory[0] + from; 113 | uint8_t *to_ptr = (uint8_t *)&stack.back().at(to); 114 | memcpy(to_ptr, from_ptr, sizeof(int)); 115 | } 116 | } break; 117 | case Opc::st: { 118 | int to = stack.back().at(*eip++); 119 | int from = *eip++; 120 | dbgs("%p: st (%d), %d\n", oldeip, to, from); 121 | if (memory.size() * 4 <= (size_t)to) { 122 | #ifndef IGNORE_CERTAIN_EXCEPTION 123 | exception = Exception::STORE; 124 | return -1; 125 | #endif 126 | } else { 127 | uint8_t *from_ptr = 128 | (uint8_t *)&stack.back().at(from); 129 | uint8_t *to_ptr = (uint8_t *)&memory[0] + to; 130 | memcpy(to_ptr, from_ptr, sizeof(int)); 131 | } 132 | } break; 133 | case Opc::li: { 134 | int to = *eip++; 135 | int lhs = *eip++; 136 | stack.back().at(to) = lhs; 137 | if (lhs < 0 || lhs > 256) 138 | dbgs("%p: li %d %08x\n", oldeip, to, lhs); 139 | else 140 | dbgs("%p: li %d %d\n", oldeip, to, lhs); 141 | } break; 142 | case Opc::mov: { 143 | int to = *eip++; 144 | int lhs = *eip++; 145 | dbgs("%p: mov %d %d\n", oldeip, to, lhs); 146 | stack.back().at(to) = stack.back().at(lhs); 147 | } break; 148 | case Opc::add: { 149 | int to = *eip++; 150 | int lhs = *eip++; 151 | int rhs = *eip++; 152 | stack.back().at(to) = 153 | stack.back().at(lhs) + stack.back().at(rhs); 154 | dbgs("%p: add %d, %d, %d\n", oldeip, to, lhs, rhs); 155 | } break; 156 | case Opc::sub: { 157 | int to = *eip++; 158 | int lhs = *eip++; 159 | int rhs = *eip++; 160 | stack.back().at(to) = 161 | stack.back().at(lhs) - stack.back().at(rhs); 162 | dbgs("%p: sub %d, %d, %d\n", oldeip, to, lhs, rhs); 163 | } break; 164 | case Opc::mul: { 165 | int to = *eip++; 166 | int lhs = *eip++; 167 | int rhs = *eip++; 168 | stack.back().at(to) = 169 | stack.back().at(lhs) * stack.back().at(rhs); 170 | dbgs("%p: mul %d, %d, %d\n", oldeip, to, lhs, rhs); 171 | } break; 172 | case Opc::div: { 173 | int to = *eip++; 174 | int lhs = *eip++; 175 | int rhs = *eip++; 176 | if (stack.back().at(rhs) == 0) { 177 | #ifndef IGNORE_CERTAIN_EXCEPTION 178 | exception = Exception::DIV_ZERO; 179 | return -1; 180 | #endif 181 | } else if (stack.back().at(lhs) == INT_MIN && 182 | stack.back().at(rhs) == -1) { 183 | #ifndef IGNORE_CERTAIN_EXCEPTION 184 | exception = Exception::OF; 185 | return -1; 186 | #endif 187 | } else { 188 | int lhsVal = stack.back().at(lhs); 189 | int rhsVal = stack.back().at(rhs); 190 | if (lhsVal < 0 && rhsVal > 0) { 191 | stack.back().at(to) = 192 | (lhsVal - rhsVal + 1) / rhsVal; 193 | } else if (lhsVal > 0 && rhsVal < 0) { 194 | stack.back().at(to) = 195 | (lhsVal - rhsVal - 1) / rhsVal; 196 | } else { 197 | stack.back().at(to) = lhsVal / rhsVal; 198 | } 199 | } 200 | dbgs("%p: div %d, %d, %d\n", oldeip, to, lhs, rhs); 201 | } break; 202 | case Opc::jmp: { 203 | uint64_t ptrlo = *eip++; 204 | uint64_t ptrhi = *eip++; 205 | dbgs("%p: jmp %p\n", oldeip, 206 | lohi_to_ptr(ptrlo, ptrhi)); 207 | eip = lohi_to_ptr(ptrlo, ptrhi); 208 | } break; 209 | case Opc::br: { 210 | int cond = stack.back().at(*eip++); 211 | uint64_t ptrlo = *eip++; 212 | uint64_t ptrhi = *eip++; 213 | dbgs("%p: cond %d br %p\n", oldeip, cond, 214 | lohi_to_ptr(ptrlo, ptrhi)); 215 | if (cond) { eip = lohi_to_ptr(ptrlo, ptrhi); } 216 | } break; 217 | case Opc::slt: { 218 | int to = *eip++; 219 | int lhs = *eip++; 220 | int rhs = *eip++; 221 | stack.back().at(to) = 222 | stack.back().at(lhs) < stack.back().at(rhs); 223 | dbgs("%p: slt %d, %d, %d\n", oldeip, to, lhs, rhs); 224 | } break; 225 | case Opc::sle: { 226 | int to = *eip++; 227 | int lhs = *eip++; 228 | int rhs = *eip++; 229 | stack.back().at(to) = 230 | stack.back().at(lhs) <= stack.back().at(rhs); 231 | dbgs("%p: sle %d, %d, %d\n", oldeip, to, lhs, rhs); 232 | } break; 233 | case Opc::seq: { 234 | int to = *eip++; 235 | int lhs = *eip++; 236 | int rhs = *eip++; 237 | stack.back().at(to) = 238 | stack.back().at(lhs) == stack.back().at(rhs); 239 | dbgs("%p: seq %d, %d, %d\n", oldeip, to, lhs, rhs); 240 | } break; 241 | case Opc::sge: { 242 | int to = *eip++; 243 | int lhs = *eip++; 244 | int rhs = *eip++; 245 | stack.back().at(to) = 246 | stack.back().at(lhs) >= stack.back().at(rhs); 247 | dbgs("%p: sge %d, %d, %d\n", oldeip, to, lhs, rhs); 248 | } break; 249 | case Opc::sgt: { 250 | int to = *eip++; 251 | int lhs = *eip++; 252 | int rhs = *eip++; 253 | stack.back().at(to) = 254 | stack.back().at(lhs) > stack.back().at(rhs); 255 | dbgs("%p: sgt %d, %d, %d\n", oldeip, to, lhs, rhs); 256 | } break; 257 | case Opc::sne: { 258 | int to = *eip++; 259 | int lhs = *eip++; 260 | int rhs = *eip++; 261 | stack.back().at(to) = 262 | stack.back().at(lhs) != stack.back().at(rhs); 263 | dbgs("%p: sne %d, %d, %d\n", oldeip, to, lhs, rhs); 264 | } break; 265 | case Opc::call: { 266 | int ptrlo = *eip++; 267 | int ptrhi = *eip++; 268 | int *target = lohi_to_ptr(ptrlo, ptrhi); 269 | frames.push_back(eip); 270 | int ptr = (stack.back().begin() - memory.begin()) + 271 | stack.back().size(); 272 | stack.emplace_back(memory, ptr, 0); 273 | eip = target; 274 | dbgs("%p: call %p\n", oldeip, eip); 275 | } break; 276 | case Opc::ret: { 277 | assert(stack.size() >= 1); 278 | stack.pop_back(); 279 | eip = frames.back(); 280 | frames.pop_back(); 281 | dbgs("%p: ret %p\n", oldeip, eip); 282 | } break; 283 | case Opc::alloca: { 284 | int size = *eip++; 285 | dbgs("%p: alloca %d\n", oldeip, size); 286 | if (stack.empty()) stack.emplace_back(memory, 0, 0); 287 | 288 | int ptr = stack.back().begin() - memory.begin(); 289 | size_t newMemSize = ptr + size; 290 | if (newMemSize >= memory_limit) { 291 | exception = Exception::OOM; 292 | return -1; 293 | } else if (newMemSize > memory.size()) { 294 | memory.resize(newMemSize); 295 | } 296 | stack.back().resize(size); 297 | } break; 298 | case Opc::mfcr: { 299 | int to = *eip++; 300 | int from = *eip++; 301 | switch (from) { 302 | case CR_COUNT: 303 | stack.back().at(to) = ctrl_regs.at(from); 304 | dbgs("%p: mfcr %d, cr_count\n", oldeip, to); 305 | break; 306 | case CR_RET: 307 | stack.back().at(to) = ctrl_regs.at(from); 308 | dbgs("%p: mfcr %d, cr_ret\n", oldeip, to); 309 | break; 310 | case CR_SERIAL: 311 | stack.back().at(to) = io.read(); 312 | dbgs("%p: mfcr %d, cr_serial\n", oldeip, to); 313 | break; 314 | case CR_ARG: 315 | if (args.size()) { 316 | stack.back().at(to) = args.back(); 317 | args.pop_back(); 318 | } 319 | dbgs("%p: mfcr %d, cr_arg\n", oldeip, to); 320 | break; 321 | default: abort(); 322 | } 323 | } break; 324 | case Opc::mtcr: { 325 | int to = *eip++; 326 | int from = *eip++; 327 | switch (to) { 328 | case CR_COUNT: 329 | dbgs("%p: mtcr cr_count, %d\n", oldeip, from); 330 | ctrl_regs.at(to) = stack.back().at(from); 331 | break; 332 | case CR_RET: 333 | ctrl_regs.at(to) = stack.back().at(from); 334 | dbgs("%p: mtcr cr_ret, %d\n", oldeip, from); 335 | break; 336 | case CR_SERIAL: 337 | io.write(stack.back().at(from)); 338 | dbgs("%p: mtcr cr_serial, %d\n", oldeip, from); 339 | break; 340 | case CR_ARG: 341 | args.push_back(stack.back().at(from)); 342 | dbgs("%p: mtcr cr_arg, %d\n", oldeip, from); 343 | break; 344 | default: abort(); 345 | } 346 | } break; 347 | case Opc::mark: 348 | ctrl_regs[CR_COUNT]++; 349 | dbgs("%p: mark\n", oldeip); 350 | if (ctrl_regs[CR_COUNT] >= insts_limit) { 351 | exception = Exception::TIMEOUT; 352 | return -1; 353 | } 354 | break; 355 | case Opc::quit: return stack.back().at(*eip++); 356 | default: exception = Exception::INVOP; return -1; 357 | } 358 | } 359 | return 0; 360 | } 361 | 362 | int Compiler::primary_exp( 363 | Program *prog, const std::string &tok, int to) { 364 | if (tok[0] == '#') { 365 | if (to == INT_MAX) to = newTemp(); 366 | long long value; 367 | sscanf(&tok[1], "%lld", &value); 368 | prog->gen_inst(Opc::li, to, (int)value); 369 | return to; 370 | } else if (tok[0] == '&') { 371 | auto var = getVar(&tok[1]); 372 | if (to == INT_MAX) to = newTemp(); 373 | prog->gen_inst(Opc::la, to, var); 374 | return to; 375 | } else if (tok[0] == '*') { 376 | auto var = getVar(&tok[1]); 377 | if (to == INT_MAX) to = newTemp(); 378 | prog->gen_inst(Opc::ld, to, var); 379 | return to; 380 | } else { 381 | if (to != INT_MAX) { 382 | prog->gen_inst(Opc::mov, to, getVar(tok)); 383 | return to; 384 | } else { 385 | return getVar(tok); 386 | } 387 | } 388 | } 389 | 390 | /* stmt label */ 391 | bool Compiler::handle_label( 392 | Program *prog, const TokenList &toks) { 393 | dbgs("at %s, %d\n", __func__, __LINE__); 394 | // LABEL ID : 395 | if (toks.size() != 3 || toks.at(2) != ":") return false; 396 | 397 | auto &label = toks.at(1); 398 | auto label_ptr = prog->get_textptr(); 399 | labels[label] = label_ptr; 400 | dbgs("add label %s, %p\n", label.c_str(), label_ptr); 401 | for (auto *ptr : backfill_labels[label]) { 402 | ptr[0] = ptr_lo(label_ptr); 403 | ptr[1] = ptr_hi(label_ptr); 404 | } 405 | backfill_labels.erase(label); 406 | return true; 407 | } 408 | 409 | /* stmt func */ 410 | bool Compiler::handle_func( 411 | Program *prog, const TokenList &toks) { 412 | dbgs("at %s, %d\n", __func__, __LINE__); 413 | // FUNCTION ID : 414 | if (toks.size() != 3 || toks.at(2) != ":") return false; 415 | 416 | auto &f = toks.at(1); 417 | prog->gen_inst(Opc::abort); // for last func 418 | funcs[f] = prog->get_textptr(); 419 | 420 | if (prog->curf[0] == (int)Opc::alloca) { 421 | dbgs("alloca %d\n", stack_size + 1); 422 | prog->curf[1] = stack_size + 1; 423 | clear_env(); 424 | } 425 | prog->curf = prog->gen_inst(Opc::alloca, 0); 426 | return true; 427 | } 428 | 429 | bool Compiler::handle_assign( 430 | Program *prog, const TokenList &toks) { 431 | dbgs("at %s, %d\n", __func__, __LINE__); 432 | // ID := (ID|NUM|&ID) 433 | if (toks.size() != 3 || toks.at(0).at(0) == '*' || 434 | toks.at(1) != ":=") 435 | return false; 436 | auto x = getVar(toks.at(0)); 437 | primary_exp(prog, toks.at(2), x); 438 | return true; 439 | } 440 | 441 | bool Compiler::handle_arith( 442 | Program *prog, const TokenList &toks) { 443 | dbgs("at %s, %d\n", __func__, __LINE__); 444 | // ID := (ID|NUM|&ID) OP (ID|NUM|&ID) 445 | if (toks.size() != 5 || toks.at(1) != ":=") return false; 446 | 447 | static std::map m{ 448 | {"+", Opc::add}, 449 | {"-", Opc::sub}, 450 | {"*", Opc::mul}, 451 | {"/", Opc::div}, 452 | }; 453 | 454 | if (m.find(toks.at(3)) == m.end()) return false; 455 | 456 | auto x = getVar(toks.at(0)); 457 | auto y = primary_exp(prog, toks.at(2)); 458 | auto op = toks.at(3); 459 | auto z = primary_exp(prog, toks.at(4)); 460 | 461 | prog->gen_inst(m[op], x, y, z); 462 | return true; 463 | } 464 | 465 | bool Compiler::handle_takeaddr( 466 | Program *prog, const TokenList &toks) { 467 | dbgs("at %s, %d\n", __func__, __LINE__); 468 | // ID := &ID 469 | if (toks.size() != 3 || toks.at(1) != ":=" || 470 | toks.at(2).at(0) != '&') 471 | return false; 472 | auto &x = toks.at(0); 473 | auto y = toks.at(2).substr(1); 474 | prog->gen_inst(Opc::la, getVar(x), getVar(y)); 475 | return true; 476 | } 477 | 478 | bool Compiler::handle_deref( 479 | Program *prog, const TokenList &toks) { 480 | dbgs("at %s, %d\n", __func__, __LINE__); 481 | // ID := *ID 482 | /* stmt assign */ 483 | if (toks.size() != 3 || toks.at(0).at(0) == '*' || 484 | toks.at(2).at(0) != '*' || toks.at(1) != ":=") 485 | return false; 486 | 487 | auto x = getVar(toks.at(0)); 488 | auto y = getVar(toks.at(2).substr(1)); 489 | auto tmp = newTemp(); 490 | prog->gen_inst(Opc::la, tmp, y); 491 | prog->gen_inst(Opc::ld, x, y); 492 | return true; 493 | } 494 | 495 | bool Compiler::handle_deref_assign( 496 | Program *prog, const TokenList &toks) { 497 | dbgs("at %s, %d\n", __func__, __LINE__); 498 | // *ID := (ID|NUM|&ID) 499 | if (toks.size() != 3 || toks.at(0).at(0) != '*' || 500 | toks.at(1) != ":=") 501 | return false; 502 | 503 | auto x = getVar(toks.at(0).substr(1)); 504 | auto y = primary_exp(prog, toks.at(2)); 505 | prog->gen_inst(Opc::st, x, y); 506 | return true; 507 | } 508 | 509 | bool Compiler::handle_goto_( 510 | Program *prog, const TokenList &toks) { 511 | dbgs("at %s, %d\n", __func__, __LINE__); 512 | // GOTO label 513 | if (toks.size() != 2) return false; 514 | 515 | auto &label = toks.at(1); 516 | auto label_ptr = labels[label]; 517 | auto code = prog->gen_jmp(label_ptr); 518 | if (!label_ptr) { 519 | backfill_labels[label].push_back(code + 1); 520 | } 521 | return true; 522 | } 523 | 524 | bool Compiler::handle_branch( 525 | Program *prog, const TokenList &toks) { 526 | dbgs("at %s, %d\n", __func__, __LINE__); 527 | // IF a < b GOTO label 528 | if (toks.size() != 6 || toks.at(4) != "GOTO") 529 | return false; 530 | 531 | auto x = primary_exp(prog, toks.at(1)); 532 | auto &opc = toks.at(2); 533 | auto y = primary_exp(prog, toks.at(3)); 534 | 535 | auto label = toks.at(5); 536 | auto label_ptr = labels[label]; 537 | 538 | static std::map s2op{ 539 | {"<", Opc::slt}, 540 | {">", Opc::sgt}, 541 | {"<=", Opc::sle}, 542 | {">=", Opc::sge}, 543 | {"==", Opc::seq}, 544 | {"!=", Opc::sne}, 545 | }; 546 | 547 | if (s2op.find(opc) == s2op.end()) return false; 548 | 549 | auto tmp = newTemp(); 550 | prog->gen_inst(s2op[opc], tmp, x, y); 551 | auto code = prog->gen_br(tmp, label_ptr); 552 | if (!label_ptr) { 553 | backfill_labels[label].push_back(code + 2); 554 | } 555 | return true; 556 | } 557 | 558 | bool Compiler::handle_ret( 559 | Program *prog, const TokenList &toks) { 560 | dbgs("at %s, %d\n", __func__, __LINE__); 561 | // RETURN exp 562 | if (toks.size() != 2) return false; 563 | 564 | auto x = primary_exp(prog, toks.at(1)); 565 | prog->gen_inst(Opc::mtcr, CR_RET, x); 566 | prog->gen_inst(Opc::ret); 567 | return true; 568 | } 569 | 570 | bool Compiler::handle_dec( 571 | Program *prog, const TokenList &toks) { 572 | dbgs("at %s, %d\n", __func__, __LINE__); 573 | // DEC id num 574 | if (toks.size() != 3) return false; 575 | 576 | auto x = toks.at(1); 577 | auto size = stoi(toks.at(2)); 578 | getVar(x, (size + 3) / 4); 579 | return true; 580 | } 581 | 582 | bool Compiler::handle_arg( 583 | Program *prog, const TokenList &toks) { 584 | dbgs("at %s, %d\n", __func__, __LINE__); 585 | // ARG exp 586 | if (toks.size() != 2) return false; 587 | 588 | auto tmp = primary_exp(prog, toks.at(1)); 589 | prog->gen_inst(Opc::mtcr, CR_ARG, tmp); 590 | return true; 591 | } 592 | 593 | bool Compiler::handle_call( 594 | Program *prog, const TokenList &toks) { 595 | dbgs("at %s, %d\n", __func__, __LINE__); 596 | // ID := CALL ID 597 | if (toks.size() != 4 || toks.at(1) != ":=") return false; 598 | auto &to = toks.at(0); 599 | auto &f = toks.at(3); 600 | 601 | prog->gen_call(funcs[f]); 602 | prog->gen_inst(Opc::mfcr, getVar(to), CR_RET); 603 | return true; 604 | } 605 | 606 | bool Compiler::handle_param( 607 | Program *prog, const TokenList &toks) { 608 | dbgs("at %s, %d\n", __func__, __LINE__); 609 | // PARAM ID 610 | if (toks.size() != 2) return false; 611 | prog->gen_inst(Opc::mfcr, getVar(toks.at(1)), CR_ARG); 612 | return true; 613 | } 614 | 615 | bool Compiler::handle_read( 616 | Program *prog, const TokenList &toks) { 617 | dbgs("at %s, %d\n", __func__, __LINE__); 618 | // READ ID 619 | if (toks.size() != 2) return false; 620 | 621 | auto &x = toks.at(1); 622 | prog->gen_inst(Opc::mfcr, getVar(x), CR_SERIAL); 623 | return true; 624 | } 625 | 626 | bool Compiler::handle_write( 627 | Program *prog, const TokenList &toks) { 628 | dbgs("at %s, %d\n", __func__, __LINE__); 629 | // WRITE ID 630 | if (toks.size() != 2) return false; 631 | 632 | auto x = primary_exp(prog, toks.at(1)); 633 | prog->gen_inst(Opc::mtcr, CR_SERIAL, x); 634 | return true; 635 | } 636 | 637 | void log_curir(int *eip) { 638 | const char *s = lohi_to_ptr(eip[0], eip[1]); 639 | fprintf(stdout, "IR:%03d> %s\n", eip[2], s); 640 | } 641 | 642 | std::unique_ptr Compiler::compile( 643 | std::istream &is) { 644 | #ifdef LOGIR 645 | static std::vector> lines; 646 | #endif 647 | auto prog = std::make_unique(); 648 | unsigned lineno = 0; 649 | while ((is.peek(), is.good())) { 650 | lineno++; 651 | std::string line; 652 | std::getline(is, line); 653 | 654 | prog->gen_inst(Opc::mark); 655 | 656 | #ifdef LOGIR 657 | char *ir = new char[line.size() + 1]; 658 | strcpy(ir, line.c_str()); 659 | lines.push_back(std::unique_ptr(ir)); 660 | prog->gen_inst(Opc::helper, ptr_lo((void *)log_curir), 661 | ptr_hi((void *)log_curir), 3, ptr_lo(ir), 662 | ptr_hi(ir), lineno); 663 | #endif 664 | 665 | dbgs("compile %s\n", line.c_str()); 666 | 667 | if (line.find_first_not_of("\r\n\v\f\t ") == 668 | line.npos) { 669 | continue; 670 | } 671 | 672 | clearTemps(); 673 | std::vector tokens = splitTokens(line); 674 | bool suc = false; 675 | if (tokens.size() == 0) { 676 | suc = true; 677 | } else if (tokens[0] == "LABEL") { 678 | suc = handle_label(&*prog, tokens); 679 | } else if (tokens[0] == "FUNCTION") { 680 | suc = handle_func(&*prog, tokens); 681 | } else if (tokens[0] == "GOTO") { 682 | suc = handle_goto_(&*prog, tokens); 683 | } else if (tokens[0] == "IF") { 684 | suc = handle_branch(&*prog, tokens); 685 | } else if (tokens[0] == "RETURN") { 686 | suc = handle_ret(&*prog, tokens); 687 | } else if (tokens[0] == "DEC") { 688 | suc = handle_dec(&*prog, tokens); 689 | } else if (tokens[0] == "ARG") { 690 | suc = handle_arg(&*prog, tokens); 691 | } else if (tokens.size() == 4 && tokens[1] == ":=" && 692 | tokens[2] == "CALL") { 693 | suc = handle_call(&*prog, tokens); 694 | } else if (tokens[0] == "PARAM") { 695 | suc = handle_param(&*prog, tokens); 696 | } else if (tokens[0] == "READ") { 697 | suc = handle_read(&*prog, tokens); 698 | } else if (tokens[0] == "WRITE") { 699 | suc = handle_write(&*prog, tokens); 700 | } else { 701 | std::vector 703 | handlers{ 704 | &Compiler::handle_assign, 705 | &Compiler::handle_arith, 706 | &Compiler::handle_takeaddr, 707 | &Compiler::handle_deref, 708 | &Compiler::handle_deref_assign, 709 | }; 710 | 711 | for (auto &h : handlers) { 712 | suc = (this->*h)(&*prog, tokens); 713 | if (suc) break; 714 | } 715 | } 716 | 717 | if (suc) continue; 718 | 719 | fprintf(stderr, 720 | "[IGNORED] syntax error at line %d: '%s'\n", lineno, 721 | line.c_str()); 722 | /* IGNORED and continue */ 723 | } 724 | 725 | if (prog->curf[0] == (int)Opc::alloca) { 726 | dbgs("alloca %d\n", stack_size + 2); 727 | prog->curf[1] = stack_size + 2; 728 | } 729 | prog->gen_inst(Opc::abort); 730 | return prog; 731 | } 732 | 733 | } // namespace irsim 734 | -------------------------------------------------------------------------------- /mips-sim/src/instr.h: -------------------------------------------------------------------------------- 1 | #define make_label(l) \ 2 | l: 3 | #define make_entry() 4 | #define make_exit() make_label(exit) 5 | 6 | #define InstAssert(cond) \ 7 | do { \ 8 | if (!(cond)) { \ 9 | this->exception = MipsEmuEx::INVOP; \ 10 | return -1; \ 11 | } \ 12 | } while (0) 13 | 14 | /* 15 | * ABS.D ADD.D ADDIU ADD.S ADDU AND ANDI BC1F BC1T BEQ 16 | * BGEZ BGEZAL BGTZ BLEZ BLTZ BLTZAL BNE BREAK C.EQ.D 17 | * C.EQ.S CFC1 C.LE.D C.LE.S C.LT.D C.LT.S CLZ CTC1 18 | * C.ULE.D C.ULE.S C.ULT.D C.ULT.S C.UN.D C.UN.S 19 | * CVT.D.S CVT.D.W CVT.S.D CVT.S.W DIV DIV.D DIV.S DIVU 20 | * EXT INS J JAL JALR JR LB LBU LDC1 LH LHU LL LUI LW 21 | * LWC1 LWL LWR MADD MADDU MFC1 MFHC1 MFHI MFLO MOV.D 22 | * MOVF MOVF.D MOVF.S MOVN MOVN.D MOVN.S MOV.S MOVT 23 | * MOVT.D MOVT.S MOVZ MOVZ.S MSUB MTC1 MTHC1 MTHI MTLO 24 | * MUL MUL.D MUL.S MULT MULTU NEG.D NOR OR ORI PREF RDHWR 25 | * ROR RORV SB SC SDC1 SEB SEH SH SLL SLLV SLT SLTI SLTIU 26 | * SLTU SQRT.D SQRT.S SRA SRAV SRL SRLV SUB.D SUB.S SUBU 27 | * SW SWC1 SWL SWR SYNC SYSCALL TEQ TRUNC.W.D TRUNC.W.S 28 | * WSBH XOR XORI 29 | * */ 30 | 31 | #define make_exec_handler(name) \ 32 | goto inst_end; \ 33 | make_label(name) 34 | #define prepare_delayslot() \ 35 | cpu.is_delayslot = true; \ 36 | cpu.pc += 4; \ 37 | goto exit; 38 | 39 | typedef union { 40 | struct { 41 | uint32_t lo, hi; 42 | }; 43 | uint64_t val; 44 | int64_t sval; 45 | } L64_t; 46 | 47 | /* clang-format off */ 48 | /* R-type */ 49 | static const void *special_table[64] = { 50 | /* 0x00 */ &&sll, &&inv, &&srl, &&sra, 51 | /* 0x04 */ &&sllv, &&inv, &&srlv, &&srav, 52 | /* 0x08 */ &&jr, &&jalr, &&movz, &&movn, 53 | /* 0x0c */ &&syscall, &&inv, &&inv, &&inv, 54 | /* 0x10 */ &&mfhi, &&mthi, &&mflo, &&mtlo, 55 | /* 0x14 */ &&inv, &&inv, &&inv, &&inv, 56 | /* 0x18 */ &&mult, &&multu, &÷, &&divu, 57 | /* 0x1c */ &&inv, &&inv, &&inv, &&inv, 58 | /* 0x20 */ &&add, &&addu, &&sub, &&subu, 59 | /* 0x24 */ &&and_, &&or_, &&xor_, &&nor, 60 | /* 0x28 */ &&inv, &&inv, &&slt, &&sltu, 61 | /* 0x2c */ &&inv, &&inv, &&inv, &&inv, 62 | /* 0x30 */ &&inv, &&inv, &&inv, &&inv, 63 | /* 0x34 */ &&inv, &&inv, &&inv, &&inv, 64 | /* 0x38 */ &&inv, &&inv, &&inv, &&inv, 65 | /* 0x3c */ &&inv, &&inv, &&inv, &&inv, 66 | }; 67 | 68 | static const void *special2_table[64] = { 69 | /* 0x00 */ &&madd, &&maddu, &&mul, &&inv, 70 | /* 0x04 */ &&msub, &&msubu, &&inv, &&inv, 71 | /* 0x08 */ &&inv, &&inv, &&inv, &&inv, 72 | /* 0x0c */ &&inv, &&inv, &&inv, &&inv, 73 | /* 0x10 */ &&inv, &&inv, &&inv, &&inv, 74 | /* 0x14 */ &&inv, &&inv, &&inv, &&inv, 75 | /* 0x18 */ &&inv, &&inv, &&inv, &&inv, 76 | /* 0x1c */ &&inv, &&inv, &&inv, &&inv, 77 | /* 0x20 */ &&clz, &&clo, &&inv, &&inv, 78 | /* 0x24 */ &&inv, &&inv, &&inv, &&inv, 79 | /* 0x28 */ &&inv, &&inv, &&inv, &&inv, 80 | /* 0x2c */ &&inv, &&inv, &&inv, &&inv, 81 | /* 0x30 */ &&inv, &&inv, &&inv, &&inv, 82 | /* 0x34 */ &&inv, &&inv, &&inv, &&inv, 83 | /* 0x38 */ &&inv, &&inv, &&inv, &&inv, 84 | /* 0x3c */ &&inv, &&inv, &&inv, &&inv, 85 | }; 86 | 87 | static const void *special3_table[64] = { 88 | /* 0x00 */ &&ext, &&inv, &&mul, &&inv, 89 | /* 0x04 */ &&ins, &&inv, &&inv, &&inv, 90 | /* 0x08 */ &&inv, &&inv, &&inv, &&inv, 91 | /* 0x0c */ &&inv, &&inv, &&inv, &&inv, 92 | /* 0x10 */ &&inv, &&inv, &&inv, &&inv, 93 | /* 0x14 */ &&inv, &&inv, &&inv, &&inv, 94 | /* 0x18 */ &&inv, &&inv, &&inv, &&inv, 95 | /* 0x1c */ &&inv, &&inv, &&inv, &&inv, 96 | /* 0x20 */ &&exec_bshfl, &&inv, &&inv, &&inv, 97 | /* 0x24 */ &&inv, &&inv, &&inv, &&inv, 98 | /* 0x28 */ &&inv, &&inv, &&inv, &&inv, 99 | /* 0x2c */ &&inv, &&inv, &&inv, &&inv, 100 | /* 0x30 */ &&inv, &&inv, &&inv, &&inv, 101 | /* 0x34 */ &&inv, &&inv, &&inv, &&inv, 102 | /* 0x38 */ &&inv, &&inv, &&inv, &&inv, 103 | /* 0x3c */ &&inv, &&inv, &&inv, &&inv, 104 | }; 105 | 106 | /* shamt */ 107 | static const void *bshfl_table[64] = { 108 | /* 0x00 */ &&inv, &&inv, &&wsbh, &&inv, 109 | /* 0x04 */ &&inv, &&inv, &&inv, &&inv, 110 | /* 0x08 */ &&inv, &&inv, &&inv, &&inv, 111 | /* 0x0c */ &&inv, &&inv, &&inv, &&inv, 112 | /* 0x10 */ &&seb, &&inv, &&inv, &&inv, 113 | /* 0x14 */ &&inv, &&inv, &&inv, &&inv, 114 | /* 0x18 */ &&seh, &&inv, &&inv, &&inv, 115 | /* 0x1c */ &&inv, &&inv, &&inv, &&inv, 116 | }; 117 | 118 | /* I-type */ 119 | static const void *regimm_table[64] = { 120 | /* 0x00 */ &&bltz, &&bgez, &&bltzl, &&bgezl, 121 | /* 0x04 */ &&inv, &&inv, &&inv, &&inv, 122 | /* 0x08 */ &&inv, &&inv, &&inv, &&inv, 123 | /* 0x0c */ &&inv, &&inv, &&inv, &&inv, 124 | /* 0x10 */ &&bltzal, &&bgezal, &&bltzall, &&bgezall, 125 | /* 0x14 */ &&inv, &&inv, &&inv, &&inv, 126 | /* 0x18 */ &&inv, &&inv, &&inv, &&inv, 127 | /* 0x1c */ &&inv, &&inv, &&inv, &&inv, 128 | }; 129 | 130 | /* I-type */ 131 | static const void *opcode_table[64] = { 132 | /* 0x00 */ &&exec_special, &&exec_regimm, &&j, &&jal, 133 | /* 0x04 */ &&beq, &&bne, &&blez, &&bgtz, 134 | /* 0x08 */ &&addi, &&addiu, &&slti, &&sltiu, 135 | /* 0x0c */ &&andi, &&ori, &&xori, &&lui, 136 | /* 0x10 */ &&inv, &&inv, &&inv, &&inv, 137 | /* 0x14 */ &&beql, &&bnel, &&blezl, &&bgtzl, 138 | /* 0x18 */ &&inv, &&inv, &&inv, &&inv, 139 | /* 0x1c */ &&exec_special2, &&inv, &&inv, &&exec_special3, 140 | /* 0x20 */ &&lb, &&lh, &&lwl, &&lw, 141 | /* 0x24 */ &&lbu, &&lhu, &&lwr, &&inv, 142 | /* 0x28 */ &&sb, &&sh, &&swl, &&sw, 143 | /* 0x2c */ &&inv, &&inv, &&swr, &&inv, 144 | /* 0x30 */ &&inv, &&inv, &&inv, &&inv, 145 | /* 0x34 */ &&inv, &&inv, &&inv, &&inv, 146 | /* 0x38 */ &&inv, &&inv, &&inv, &&inv, 147 | /* 0x3c */ &&inv, &&inv, &&inv, &&inv, 148 | }; 149 | 150 | /* clang-format on */ 151 | make_entry() { 152 | cpu.gpr[0] = 0; 153 | #if CONFIG_INSTR_LOG 154 | instr_enqueue_instr(inst.val); 155 | #endif 156 | goto *opcode_table[inst.op]; 157 | } 158 | 159 | make_exec_handler(exec_special) { 160 | goto *special_table[inst.func]; 161 | } 162 | make_exec_handler(exec_special2) { 163 | goto *special2_table[inst.func]; 164 | } 165 | make_exec_handler(exec_special3) { 166 | goto *special3_table[inst.func]; 167 | } 168 | make_exec_handler(exec_bshfl) { 169 | goto *bshfl_table[inst.shamt]; 170 | } 171 | 172 | make_exec_handler(exec_regimm) { 173 | goto *regimm_table[inst.rt]; 174 | } 175 | 176 | make_exec_handler(inv) { 177 | uint32_t instr = vaddr_read(cpu.pc, 4); 178 | uint8_t *p = (uint8_t *)&instr; 179 | printf( 180 | "invalid opcode(pc = 0x%08x): %02x %02x %02x %02x " 181 | "...\n", 182 | cpu.pc, p[0], p[1], p[2], p[3]); 183 | abort(); 184 | } 185 | 186 | /* temporary strategy: store timer registers in C0 */ 187 | make_exec_handler(syscall) { 188 | switch (cpu.gpr[R_v0]) { 189 | case 1: 190 | printf("%d", cpu.gpr[R_a0]); 191 | if (printedNumbers) 192 | printedNumbers->push_back(cpu.gpr[R_a0]); 193 | break; 194 | case 4: { 195 | char *ptr = (char *)vaddr_map(cpu.gpr[R_a0], 0); 196 | printf("%s", ptr); 197 | } break; 198 | case 5: { 199 | int value = 0; 200 | scanf("%d", &value); 201 | cpu.gpr[R_v0] = value; 202 | } break; 203 | case 8: { 204 | int len = cpu.gpr[R_a1]; 205 | char *ptr = (char *)vaddr_map(cpu.gpr[R_a0], len); 206 | if (ptr) 207 | for (int i = 0; i < len; i++) ptr[i] = getchar(); 208 | } break; 209 | case 11: putchar(cpu.gpr[R_a0]); break; 210 | case 12: cpu.gpr[R_a0] = getchar(); break; 211 | case 10: return 0; break; 212 | case 17: return 0; break; 213 | default: eprintf("unimplemented syscall\n"); 214 | } 215 | } 216 | 217 | #define R_SIMPLE(name, op, t) \ 218 | make_exec_handler(name) { \ 219 | InstAssert(inst.shamt == 0); \ 220 | cpu.gpr[inst.rd] = \ 221 | (t)cpu.gpr[inst.rs] op(t) cpu.gpr[inst.rt]; \ 222 | } 223 | 224 | R_SIMPLE(or_, |, uint32_t) 225 | R_SIMPLE(xor_, ^, uint32_t) 226 | R_SIMPLE(and_, &, uint32_t) 227 | R_SIMPLE(addu, +, uint32_t) 228 | R_SIMPLE(subu, -, uint32_t) 229 | R_SIMPLE(mul, *, uint32_t) 230 | R_SIMPLE(slt, <, int32_t) 231 | R_SIMPLE(sltu, <, uint32_t) 232 | 233 | make_exec_handler(add) { 234 | InstAssert(inst.shamt == 0); 235 | L64_t ret; 236 | ret.val = (int64_t)(int32_t)cpu.gpr[inst.rs] + 237 | (int64_t)(int32_t)cpu.gpr[inst.rt]; 238 | if ((ret.hi & 0x1) != ((ret.lo >> 31) & 1)) { 239 | #ifndef IGNORE_CERTAIN_EXCEPTION 240 | this->exception = MipsEmuEx::OVERFLOW; 241 | return -1; 242 | #endif 243 | } else { 244 | cpu.gpr[inst.rd] = ret.lo; 245 | } 246 | } 247 | 248 | make_exec_handler(sub) { 249 | InstAssert(inst.shamt == 0); 250 | L64_t ret; 251 | ret.val = (int64_t)(int32_t)cpu.gpr[inst.rs] - 252 | (int64_t)(int32_t)cpu.gpr[inst.rt]; 253 | if ((ret.hi & 0x1) != ((ret.lo >> 31) & 1)) { 254 | #ifndef IGNORE_CERTAIN_EXCEPTION 255 | this->exception = MipsEmuEx::OVERFLOW; 256 | return -1; 257 | #endif 258 | } else { 259 | cpu.gpr[inst.rd] = ret.lo; 260 | } 261 | } 262 | 263 | make_exec_handler(nor) { 264 | InstAssert(inst.shamt == 0); 265 | cpu.gpr[inst.rd] = ~(cpu.gpr[inst.rs] | cpu.gpr[inst.rt]); 266 | } 267 | 268 | #undef R_SIMPLE 269 | 270 | make_exec_handler(clz) { 271 | if (cpu.gpr[inst.rs] == 0) { 272 | cpu.gpr[inst.rd] = 32; 273 | } else { 274 | cpu.gpr[inst.rd] = __builtin_clz(cpu.gpr[inst.rs]); 275 | } 276 | } 277 | 278 | make_exec_handler(clo) { 279 | uint32_t in = cpu.gpr[inst.rs]; 280 | uint32_t cnt = 0; 281 | uint32_t b = 0x80000000; 282 | while ((in & b) != 0) { 283 | cnt++; 284 | b >>= 1; 285 | } 286 | cpu.gpr[inst.rd] = cnt; 287 | } 288 | 289 | make_exec_handler(madd) { 290 | InstAssert(inst.rd == 0 && inst.shamt == 0); 291 | L64_t hilo; 292 | hilo.hi = cpu.hi; 293 | hilo.lo = cpu.lo; 294 | hilo.sval += (int64_t)(int32_t)cpu.gpr[inst.rs] * 295 | (int64_t)(int32_t)cpu.gpr[inst.rt]; 296 | cpu.hi = hilo.hi; 297 | cpu.lo = hilo.lo; 298 | } 299 | 300 | make_exec_handler(maddu) { 301 | InstAssert(inst.rd == 0 && inst.shamt == 0); 302 | L64_t hilo; 303 | hilo.hi = cpu.hi; 304 | hilo.lo = cpu.lo; 305 | hilo.val += (uint64_t)cpu.gpr[inst.rs] * 306 | (uint64_t)cpu.gpr[inst.rt]; 307 | cpu.hi = hilo.hi; 308 | cpu.lo = hilo.lo; 309 | } 310 | 311 | make_exec_handler(msub) { 312 | InstAssert(inst.rd == 0 && inst.shamt == 0); 313 | L64_t hilo; 314 | hilo.hi = cpu.hi; 315 | hilo.lo = cpu.lo; 316 | hilo.sval -= (int64_t)(int32_t)cpu.gpr[inst.rs] * 317 | (int64_t)(int32_t)cpu.gpr[inst.rt]; 318 | cpu.hi = hilo.hi; 319 | cpu.lo = hilo.lo; 320 | } 321 | 322 | make_exec_handler(msubu) { 323 | InstAssert(inst.rd == 0 && inst.shamt == 0); 324 | L64_t hilo; 325 | hilo.hi = cpu.hi; 326 | hilo.lo = cpu.lo; 327 | hilo.val -= (uint64_t)cpu.gpr[inst.rs] * 328 | (uint64_t)cpu.gpr[inst.rt]; 329 | cpu.hi = hilo.hi; 330 | cpu.lo = hilo.lo; 331 | } 332 | 333 | make_exec_handler(mult) { 334 | InstAssert(inst.rd == 0 && inst.shamt == 0); 335 | int64_t prod = (int64_t)(int32_t)cpu.gpr[inst.rs] * 336 | (int64_t)(int32_t)cpu.gpr[inst.rt]; 337 | cpu.lo = (uint32_t)prod; 338 | cpu.hi = (uint32_t)(prod >> 32); 339 | } 340 | 341 | make_exec_handler(multu) { 342 | InstAssert(inst.rd == 0 && inst.shamt == 0); 343 | uint64_t prod = (uint64_t)cpu.gpr[inst.rs] * 344 | (uint64_t)cpu.gpr[inst.rt]; 345 | cpu.lo = (uint32_t)prod; 346 | cpu.hi = (uint32_t)(prod >> 32); 347 | } 348 | 349 | make_exec_handler(divide) { 350 | InstAssert(inst.rd == 0 && inst.shamt == 0); 351 | cpu.lo = 352 | (int32_t)cpu.gpr[inst.rs] / (int32_t)cpu.gpr[inst.rt]; 353 | cpu.hi = 354 | (int32_t)cpu.gpr[inst.rs] % (int32_t)cpu.gpr[inst.rt]; 355 | } 356 | 357 | make_exec_handler(divu) { 358 | InstAssert(inst.rd == 0 && inst.shamt == 0); 359 | cpu.lo = cpu.gpr[inst.rs] / cpu.gpr[inst.rt]; 360 | cpu.hi = cpu.gpr[inst.rs] % cpu.gpr[inst.rt]; 361 | } 362 | 363 | make_exec_handler(sll) { 364 | InstAssert(inst.rs == 0); 365 | cpu.gpr[inst.rd] = cpu.gpr[inst.rt] << inst.shamt; 366 | } 367 | 368 | make_exec_handler(sllv) { 369 | InstAssert(inst.shamt == 0); 370 | cpu.gpr[inst.rd] = cpu.gpr[inst.rt] 371 | << (cpu.gpr[inst.rs] & 0x1f); 372 | } 373 | 374 | make_exec_handler(sra) { 375 | InstAssert(inst.rs == 0); 376 | cpu.gpr[inst.rd] = 377 | (int32_t)cpu.gpr[inst.rt] >> inst.shamt; 378 | } 379 | 380 | make_exec_handler(srav) { 381 | InstAssert(inst.shamt == 0); 382 | cpu.gpr[inst.rd] = (int32_t)cpu.gpr[inst.rt] >> 383 | (cpu.gpr[inst.rs] & 0x1f); 384 | } 385 | 386 | make_exec_handler(srl) { 387 | if ((inst.rs & 0x1) == 0x1) { 388 | /* rotr */ 389 | uint32_t rt_val = cpu.gpr[inst.rt]; 390 | uint32_t sa = inst.shamt; 391 | cpu.gpr[inst.rd] = 392 | (rt_val >> sa) | (rt_val << (32 - sa)); 393 | } else { 394 | InstAssert(inst.rs == 0); 395 | cpu.gpr[inst.rd] = cpu.gpr[inst.rt] >> inst.shamt; 396 | } 397 | } 398 | 399 | make_exec_handler(srlv) { 400 | if ((inst.shamt & 0x1) == 0x1) { 401 | /* rotrv */ 402 | uint32_t rt_val = cpu.gpr[inst.rt]; 403 | uint32_t sa = cpu.gpr[inst.rs] & 0x1f; 404 | cpu.gpr[inst.rd] = 405 | (rt_val >> sa) | (rt_val << (32 - sa)); 406 | } else { 407 | InstAssert(inst.shamt == 0); 408 | cpu.gpr[inst.rd] = 409 | cpu.gpr[inst.rt] >> (cpu.gpr[inst.rs] & 0x1f); 410 | } 411 | } 412 | 413 | make_exec_handler(movn) { 414 | InstAssert(inst.shamt == 0); 415 | if (cpu.gpr[inst.rt] != 0) 416 | cpu.gpr[inst.rd] = cpu.gpr[inst.rs]; 417 | } 418 | 419 | make_exec_handler(movz) { 420 | InstAssert(inst.shamt == 0); 421 | if (cpu.gpr[inst.rt] == 0) 422 | cpu.gpr[inst.rd] = cpu.gpr[inst.rs]; 423 | } 424 | 425 | make_exec_handler(mfhi) { 426 | InstAssert( 427 | inst.rs == 0 && inst.rt == 0 && inst.shamt == 0); 428 | cpu.gpr[inst.rd] = cpu.hi; 429 | } 430 | 431 | make_exec_handler(mthi) { 432 | InstAssert( 433 | inst.rt == 0 && inst.rd == 0 && inst.shamt == 0); 434 | cpu.hi = cpu.gpr[inst.rs]; 435 | } 436 | 437 | make_exec_handler(mflo) { 438 | InstAssert( 439 | inst.rs == 0 && inst.rt == 0 && inst.shamt == 0); 440 | cpu.gpr[inst.rd] = cpu.lo; 441 | } 442 | 443 | make_exec_handler(mtlo) { 444 | InstAssert( 445 | inst.rt == 0 && inst.rd == 0 && inst.shamt == 0); 446 | cpu.lo = cpu.gpr[inst.rs]; 447 | } 448 | 449 | make_exec_handler(lui) { 450 | InstAssert(inst.rs == 0); 451 | cpu.gpr[inst.rt] = inst.uimm << 16; 452 | } 453 | 454 | make_exec_handler(addi) { 455 | // should throw exception 456 | L64_t ret; 457 | ret.val = (int64_t)(int32_t)cpu.gpr[inst.rs] + 458 | (int64_t)(int32_t)inst.simm; 459 | if ((ret.hi & 0x1) != ((ret.lo >> 31) & 1)) { 460 | InstAssert(0 && "addi overflow\n"); 461 | } else { 462 | cpu.gpr[inst.rt] = ret.lo; 463 | } 464 | } 465 | 466 | make_exec_handler(addiu) { 467 | cpu.gpr[inst.rt] = cpu.gpr[inst.rs] + inst.simm; 468 | } 469 | 470 | make_exec_handler(andi) { 471 | cpu.gpr[inst.rt] = cpu.gpr[inst.rs] & inst.uimm; 472 | } 473 | 474 | make_exec_handler(ori) { 475 | cpu.gpr[inst.rt] = cpu.gpr[inst.rs] | inst.uimm; 476 | } 477 | 478 | make_exec_handler(xori) { 479 | cpu.gpr[inst.rt] = cpu.gpr[inst.rs] ^ inst.uimm; 480 | } 481 | 482 | make_exec_handler(sltiu) { 483 | cpu.gpr[inst.rt] = cpu.gpr[inst.rs] < (uint32_t)inst.simm; 484 | } 485 | 486 | make_exec_handler(slti) { 487 | cpu.gpr[inst.rt] = (int32_t)cpu.gpr[inst.rs] < inst.simm; 488 | } 489 | 490 | #define CHECK_ALIGNED_ADDR_AdEL(align, addr) \ 491 | do { \ 492 | if (((addr) & (align - 1)) != 0) { \ 493 | this->exception = MipsEmuEx::LOAD; \ 494 | return -1; \ 495 | } \ 496 | } while (0) 497 | #define CHECK_ALIGNED_ADDR_AdES(align, addr) \ 498 | do { \ 499 | if (((addr) & (align - 1)) != 0) { \ 500 | this->exception = MipsEmuEx::STORE; \ 501 | return -1; \ 502 | } \ 503 | } while (0) 504 | 505 | make_exec_handler(swl) { 506 | uint32_t waddr = cpu.gpr[inst.rs] + inst.simm; 507 | int idx = waddr & 0x3; 508 | int len = idx + 1; 509 | uint32_t wdata = cpu.gpr[inst.rt] >> ((3 - idx) * 8); 510 | 511 | vaddr_write((waddr >> 2) << 2, len, wdata); 512 | } 513 | 514 | make_exec_handler(swr) { 515 | uint32_t waddr = cpu.gpr[inst.rs] + inst.simm; 516 | int len = 4 - (waddr & 0x3); 517 | uint32_t wdata = cpu.gpr[inst.rt]; 518 | 519 | vaddr_write(waddr, len, wdata); 520 | } 521 | 522 | make_exec_handler(sw) { 523 | CHECK_ALIGNED_ADDR_AdES(4, cpu.gpr[inst.rs] + inst.simm); 524 | vaddr_write( 525 | cpu.gpr[inst.rs] + inst.simm, 4, cpu.gpr[inst.rt]); 526 | } 527 | 528 | make_exec_handler(sh) { 529 | CHECK_ALIGNED_ADDR_AdES(2, cpu.gpr[inst.rs] + inst.simm); 530 | vaddr_write( 531 | cpu.gpr[inst.rs] + inst.simm, 2, cpu.gpr[inst.rt]); 532 | } 533 | 534 | make_exec_handler(sb) { 535 | CHECK_ALIGNED_ADDR_AdES(1, cpu.gpr[inst.rs] + inst.simm); 536 | vaddr_write( 537 | cpu.gpr[inst.rs] + inst.simm, 1, cpu.gpr[inst.rt]); 538 | } 539 | 540 | make_exec_handler(lwl) { 541 | uint32_t raddr = cpu.gpr[inst.rs] + inst.simm; 542 | int len = (raddr & 0x3) + 1; 543 | uint32_t rdata = vaddr_read((raddr >> 2) << 2, len); 544 | 545 | if (len < 4) 546 | cpu.gpr[inst.rt] = 547 | rdata << ((4 - len) * 8) | 548 | ((uint32_t)cpu.gpr[inst.rt] << (len * 8)) >> 549 | (len * 8); 550 | else 551 | cpu.gpr[inst.rt] = rdata; 552 | } 553 | 554 | make_exec_handler(lwr) { 555 | uint32_t raddr = cpu.gpr[inst.rs] + inst.simm; 556 | int idx = raddr & 0x3; 557 | int len = 4 - idx; 558 | uint32_t rdata = vaddr_read(raddr, len); 559 | if (len < 4) 560 | cpu.gpr[inst.rt] = 561 | (rdata << idx * 8) >> (idx * 8) | 562 | ((uint32_t)cpu.gpr[inst.rt] >> (len * 8)) 563 | << (len * 8); 564 | else 565 | cpu.gpr[inst.rt] = (rdata << idx * 8) >> (idx * 8); 566 | } 567 | 568 | make_exec_handler(lw) { 569 | CHECK_ALIGNED_ADDR_AdEL(4, cpu.gpr[inst.rs] + inst.simm); 570 | uint32_t rdata = 571 | vaddr_read(cpu.gpr[inst.rs] + inst.simm, 4); 572 | cpu.gpr[inst.rt] = rdata; 573 | } 574 | 575 | make_exec_handler(lb) { 576 | CHECK_ALIGNED_ADDR_AdEL(1, cpu.gpr[inst.rs] + inst.simm); 577 | uint32_t rdata = (int32_t)(int8_t)vaddr_read( 578 | cpu.gpr[inst.rs] + inst.simm, 1); 579 | cpu.gpr[inst.rt] = rdata; 580 | } 581 | 582 | make_exec_handler(lbu) { 583 | CHECK_ALIGNED_ADDR_AdEL(1, cpu.gpr[inst.rs] + inst.simm); 584 | uint32_t rdata = 585 | vaddr_read(cpu.gpr[inst.rs] + inst.simm, 1); 586 | cpu.gpr[inst.rt] = rdata; 587 | } 588 | 589 | make_exec_handler(lh) { 590 | CHECK_ALIGNED_ADDR_AdEL(2, cpu.gpr[inst.rs] + inst.simm); 591 | uint32_t rdata = (int32_t)(int16_t)vaddr_read( 592 | cpu.gpr[inst.rs] + inst.simm, 2); 593 | cpu.gpr[inst.rt] = rdata; 594 | } 595 | 596 | make_exec_handler(lhu) { 597 | CHECK_ALIGNED_ADDR_AdEL(2, cpu.gpr[inst.rs] + inst.simm); 598 | uint32_t rdata = 599 | vaddr_read(cpu.gpr[inst.rs] + inst.simm, 2); 600 | cpu.gpr[inst.rt] = rdata; 601 | } 602 | 603 | ////////////////////////////////////////////////////////////// 604 | // likely branch // 605 | ////////////////////////////////////////////////////////////// 606 | make_exec_handler(beql) { 607 | if (cpu.gpr[inst.rs] == cpu.gpr[inst.rt]) { 608 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 609 | prepare_delayslot(); 610 | } else { 611 | cpu.br_target = cpu.pc + 8; 612 | cpu.pc += 4; 613 | } 614 | } 615 | 616 | make_exec_handler(bnel) { 617 | if (cpu.gpr[inst.rs] != cpu.gpr[inst.rt]) { 618 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 619 | prepare_delayslot(); 620 | } else { 621 | cpu.br_target = cpu.pc + 8; 622 | cpu.pc += 4; 623 | } 624 | } 625 | 626 | make_exec_handler(blezl) { 627 | InstAssert(inst.rt == 0); 628 | if ((int32_t)cpu.gpr[inst.rs] <= 0) { 629 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 630 | prepare_delayslot(); 631 | } else { 632 | cpu.br_target = cpu.pc + 8; 633 | cpu.pc += 4; 634 | } 635 | } 636 | 637 | make_exec_handler(bgtzl) { 638 | if ((int32_t)cpu.gpr[inst.rs] > 0) { 639 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 640 | prepare_delayslot(); 641 | } else { 642 | cpu.br_target = cpu.pc + 8; 643 | cpu.pc += 4; 644 | } 645 | } 646 | 647 | make_exec_handler(bltzl) { 648 | if ((int32_t)cpu.gpr[inst.rs] < 0) { 649 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 650 | prepare_delayslot(); 651 | } else { 652 | cpu.br_target = cpu.pc + 8; 653 | cpu.pc += 4; 654 | } 655 | } 656 | 657 | make_exec_handler(bgezl) { 658 | if ((int32_t)cpu.gpr[inst.rs] >= 0) { 659 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 660 | prepare_delayslot(); 661 | } else { 662 | cpu.br_target = cpu.pc + 8; 663 | cpu.pc += 4; 664 | } 665 | } 666 | 667 | make_exec_handler(bgezall) { 668 | cpu.gpr[31] = cpu.pc + 8; 669 | if ((int32_t)cpu.gpr[inst.rs] >= 0) { 670 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 671 | prepare_delayslot(); 672 | } else { 673 | cpu.br_target = cpu.pc + 8; 674 | cpu.pc += 4; 675 | } 676 | } 677 | 678 | make_exec_handler(bltzall) { 679 | cpu.gpr[31] = cpu.pc + 8; 680 | if ((int32_t)cpu.gpr[inst.rs] < 0) { 681 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 682 | prepare_delayslot(); 683 | } else { 684 | cpu.br_target = cpu.pc + 8; 685 | cpu.pc += 4; 686 | } 687 | } 688 | 689 | ////////////////////////////////////////////////////////////// 690 | // unlikely branch // 691 | ////////////////////////////////////////////////////////////// 692 | make_exec_handler(beq) { 693 | if (cpu.gpr[inst.rs] == cpu.gpr[inst.rt]) 694 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 695 | else 696 | cpu.br_target = cpu.pc + 8; 697 | prepare_delayslot(); 698 | } 699 | 700 | make_exec_handler(bne) { 701 | if (cpu.gpr[inst.rs] != cpu.gpr[inst.rt]) 702 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 703 | else 704 | cpu.br_target = cpu.pc + 8; 705 | prepare_delayslot(); 706 | } 707 | 708 | make_exec_handler(blez) { 709 | InstAssert(inst.rt == 0); 710 | if ((int32_t)cpu.gpr[inst.rs] <= 0) 711 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 712 | else 713 | cpu.br_target = cpu.pc + 8; 714 | prepare_delayslot(); 715 | } 716 | 717 | make_exec_handler(bgtz) { 718 | if ((int32_t)cpu.gpr[inst.rs] > 0) 719 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 720 | else 721 | cpu.br_target = cpu.pc + 8; 722 | prepare_delayslot(); 723 | } 724 | 725 | make_exec_handler(bltz) { 726 | if ((int32_t)cpu.gpr[inst.rs] < 0) 727 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 728 | else 729 | cpu.br_target = cpu.pc + 8; 730 | prepare_delayslot(); 731 | } 732 | 733 | make_exec_handler(bgez) { 734 | if ((int32_t)cpu.gpr[inst.rs] >= 0) 735 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 736 | else 737 | cpu.br_target = cpu.pc + 8; 738 | prepare_delayslot(); 739 | } 740 | 741 | make_exec_handler(bgezal) { 742 | cpu.gpr[31] = cpu.pc + 8; 743 | if ((int32_t)cpu.gpr[inst.rs] >= 0) 744 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 745 | else 746 | cpu.br_target = cpu.pc + 8; 747 | prepare_delayslot(); 748 | } 749 | 750 | make_exec_handler(bltzal) { 751 | cpu.gpr[31] = cpu.pc + 8; 752 | if ((int32_t)cpu.gpr[inst.rs] < 0) 753 | cpu.br_target = cpu.pc + (inst.simm << 2) + 4; 754 | else 755 | cpu.br_target = cpu.pc + 8; 756 | prepare_delayslot(); 757 | } 758 | 759 | make_exec_handler(jal) { 760 | cpu.gpr[31] = cpu.pc + 8; 761 | cpu.br_target = (cpu.pc & 0xf0000000) | (inst.addr << 2); 762 | prepare_delayslot(); 763 | } 764 | 765 | make_exec_handler(jalr) { 766 | InstAssert(inst.rt == 0 && inst.shamt == 0); 767 | cpu.gpr[inst.rd] = cpu.pc + 8; 768 | cpu.br_target = cpu.gpr[inst.rs]; 769 | prepare_delayslot(); 770 | } 771 | 772 | make_exec_handler(j) { 773 | cpu.br_target = (cpu.pc & 0xf0000000) | (inst.addr << 2); 774 | prepare_delayslot(); 775 | } 776 | 777 | make_exec_handler(jr) { 778 | InstAssert(inst.rt == 0 && inst.rd == 0); 779 | cpu.br_target = cpu.gpr[inst.rs]; 780 | prepare_delayslot(); 781 | } 782 | 783 | make_exec_handler(seb) { 784 | cpu.gpr[inst.rd] = (int32_t)(int8_t)cpu.gpr[inst.rt]; 785 | } 786 | 787 | make_exec_handler(seh) { 788 | cpu.gpr[inst.rd] = (int32_t)(int16_t)cpu.gpr[inst.rt]; 789 | } 790 | 791 | make_exec_handler(wsbh) { 792 | uint32_t rt_val = cpu.gpr[inst.rt]; 793 | cpu.gpr[inst.rd] = ((rt_val & 0x00FF0000) << 8) | 794 | ((rt_val & 0xFF000000) >> 8) | 795 | ((rt_val & 0x000000FF) << 8) | 796 | ((rt_val & 0x0000FF00) >> 8); 797 | } 798 | 799 | make_exec_handler(ins) { 800 | uint32_t lsb = inst.shamt; 801 | uint32_t msb = inst.rd; 802 | InstAssert(lsb <= msb); 803 | uint32_t rs_val = cpu.gpr[inst.rs]; 804 | uint32_t rt_val = cpu.gpr[inst.rt]; 805 | uint32_t mask = (1ull << (msb - lsb + 1)) - 1; 806 | 807 | cpu.gpr[inst.rt] = 808 | (rt_val & ~(mask << lsb)) | ((rs_val & mask) << lsb); 809 | } 810 | 811 | make_exec_handler(ext) { 812 | uint32_t lsb = inst.shamt; 813 | uint32_t msbd = inst.rd; 814 | uint32_t size = msbd + 1; 815 | uint32_t rs_val = cpu.gpr[inst.rs]; 816 | uint32_t mask = (1ull << size) - 1; 817 | 818 | cpu.gpr[inst.rt] = ((rs_val & (mask << lsb)) >> lsb); 819 | } 820 | 821 | make_label(inst_end) { 822 | if (cpu.is_delayslot) { 823 | cpu.pc = cpu.br_target; 824 | cpu.is_delayslot = false; 825 | } else { 826 | cpu.pc += 4; 827 | } 828 | /* fall through */ 829 | } 830 | 831 | make_exit() {} 832 | -------------------------------------------------------------------------------- /cxx-irsim/test/fault.ir: -------------------------------------------------------------------------------- 1 | FUNCTION safe_add : 2 | PARAM t1 3 | PARAM t2 4 | t3 := #0 5 | t4 := #0 6 | t5 := #0 7 | t6 := t1 8 | t7 := #0 9 | IF t6 > t7 GOTO label10 10 | GOTO label11 11 | LABEL label10 : 12 | t5 := #1 13 | LABEL label11 : 14 | IF t5 != #0 GOTO label9 15 | GOTO label7 16 | LABEL label9 : 17 | t8 := #0 18 | t9 := t2 19 | t10 := #0 20 | IF t9 > t10 GOTO label12 21 | GOTO label13 22 | LABEL label12 : 23 | t8 := #1 24 | LABEL label13 : 25 | IF t8 != #0 GOTO label8 26 | GOTO label7 27 | LABEL label8 : 28 | t11 := #0 29 | t12 := t1 30 | t14 := #2147483647 31 | t15 := t2 32 | t13 := t14 - t15 33 | IF t12 > t13 GOTO label14 34 | GOTO label15 35 | LABEL label14 : 36 | t11 := #1 37 | LABEL label15 : 38 | IF t11 != #0 GOTO label6 39 | GOTO label7 40 | LABEL label6 : 41 | t4 := #1 42 | LABEL label7 : 43 | IF t4 != #0 GOTO label3 44 | GOTO label5 45 | LABEL label5 : 46 | t16 := #0 47 | t17 := #0 48 | t18 := t1 49 | t19 := #0 50 | IF t18 < t19 GOTO label20 51 | GOTO label21 52 | LABEL label20 : 53 | t17 := #1 54 | LABEL label21 : 55 | IF t17 != #0 GOTO label19 56 | GOTO label17 57 | LABEL label19 : 58 | t20 := #0 59 | t21 := t2 60 | t22 := #0 61 | IF t21 < t22 GOTO label22 62 | GOTO label23 63 | LABEL label22 : 64 | t20 := #1 65 | LABEL label23 : 66 | IF t20 != #0 GOTO label18 67 | GOTO label17 68 | LABEL label18 : 69 | t23 := #0 70 | t24 := t1 71 | t27 := #-2147483648 72 | t26 := #0 - t27 73 | t28 := t2 74 | t25 := t26 - t28 75 | IF t24 < t25 GOTO label24 76 | GOTO label25 77 | LABEL label24 : 78 | t23 := #1 79 | LABEL label25 : 80 | IF t23 != #0 GOTO label16 81 | GOTO label17 82 | LABEL label16 : 83 | t16 := #1 84 | LABEL label17 : 85 | IF t16 != #0 GOTO label3 86 | GOTO label4 87 | LABEL label3 : 88 | t3 := #1 89 | LABEL label4 : 90 | IF t3 != #0 GOTO label1 91 | GOTO label2 92 | LABEL label1 : 93 | t29 := t1 94 | RETURN t29 95 | LABEL label2 : 96 | t31 := t1 97 | t32 := t2 98 | t30 := t31 + t32 99 | RETURN t30 100 | FUNCTION safe_sub : 101 | PARAM t33 102 | PARAM t34 103 | t35 := #0 104 | t36 := #0 105 | t37 := t33 106 | t38 := #0 107 | IF t37 > t38 GOTO label33 108 | GOTO label34 109 | LABEL label33 : 110 | t36 := #1 111 | LABEL label34 : 112 | IF t36 != #0 GOTO label32 113 | GOTO label30 114 | LABEL label32 : 115 | t39 := #0 116 | t40 := t34 117 | t41 := #0 118 | IF t40 < t41 GOTO label35 119 | GOTO label36 120 | LABEL label35 : 121 | t39 := #1 122 | LABEL label36 : 123 | IF t39 != #0 GOTO label31 124 | GOTO label30 125 | LABEL label31 : 126 | t42 := #0 127 | t43 := t33 128 | t45 := #2147483647 129 | t46 := t34 130 | t44 := t45 + t46 131 | IF t43 > t44 GOTO label37 132 | GOTO label38 133 | LABEL label37 : 134 | t42 := #1 135 | LABEL label38 : 136 | IF t42 != #0 GOTO label29 137 | GOTO label30 138 | LABEL label29 : 139 | t35 := #1 140 | LABEL label30 : 141 | IF t35 != #0 GOTO label26 142 | GOTO label28 143 | LABEL label28 : 144 | t47 := #0 145 | t48 := #0 146 | t49 := t33 147 | t50 := #0 148 | IF t49 < t50 GOTO label43 149 | GOTO label44 150 | LABEL label43 : 151 | t48 := #1 152 | LABEL label44 : 153 | IF t48 != #0 GOTO label42 154 | GOTO label40 155 | LABEL label42 : 156 | t51 := #0 157 | t52 := t34 158 | t53 := #0 159 | IF t52 > t53 GOTO label45 160 | GOTO label46 161 | LABEL label45 : 162 | t51 := #1 163 | LABEL label46 : 164 | IF t51 != #0 GOTO label41 165 | GOTO label40 166 | LABEL label41 : 167 | t54 := #0 168 | t55 := t33 169 | t58 := #-2147483648 170 | t57 := #0 - t58 171 | t59 := t34 172 | t56 := t57 + t59 173 | IF t55 < t56 GOTO label47 174 | GOTO label48 175 | LABEL label47 : 176 | t54 := #1 177 | LABEL label48 : 178 | IF t54 != #0 GOTO label39 179 | GOTO label40 180 | LABEL label39 : 181 | t47 := #1 182 | LABEL label40 : 183 | IF t47 != #0 GOTO label26 184 | GOTO label27 185 | LABEL label26 : 186 | t60 := t33 187 | RETURN t60 188 | LABEL label27 : 189 | t62 := t33 190 | t63 := t34 191 | t61 := t62 - t63 192 | RETURN t61 193 | FUNCTION safe_mul : 194 | PARAM t64 195 | PARAM t65 196 | t66 := #0 197 | t67 := #0 198 | t68 := #0 199 | t69 := t64 200 | t70 := #0 201 | IF t69 > t70 GOTO label60 202 | GOTO label61 203 | LABEL label60 : 204 | t68 := #1 205 | LABEL label61 : 206 | IF t68 != #0 GOTO label59 207 | GOTO label57 208 | LABEL label59 : 209 | t71 := #0 210 | t72 := t65 211 | t73 := #0 212 | IF t72 > t73 GOTO label62 213 | GOTO label63 214 | LABEL label62 : 215 | t71 := #1 216 | LABEL label63 : 217 | IF t71 != #0 GOTO label58 218 | GOTO label57 219 | LABEL label58 : 220 | t74 := #0 221 | t75 := t64 222 | t77 := #2147483647 223 | t78 := t65 224 | t76 := t77 / t78 225 | IF t75 > t76 GOTO label64 226 | GOTO label65 227 | LABEL label64 : 228 | t74 := #1 229 | LABEL label65 : 230 | IF t74 != #0 GOTO label56 231 | GOTO label57 232 | LABEL label56 : 233 | t67 := #1 234 | LABEL label57 : 235 | IF t67 != #0 GOTO label51 236 | GOTO label55 237 | LABEL label55 : 238 | t79 := #0 239 | t80 := #0 240 | t81 := t64 241 | t82 := #0 242 | IF t81 > t82 GOTO label70 243 | GOTO label71 244 | LABEL label70 : 245 | t80 := #1 246 | LABEL label71 : 247 | IF t80 != #0 GOTO label69 248 | GOTO label67 249 | LABEL label69 : 250 | t83 := #0 251 | t84 := t65 252 | t85 := #0 253 | IF t84 <= t85 GOTO label72 254 | GOTO label73 255 | LABEL label72 : 256 | t83 := #1 257 | LABEL label73 : 258 | IF t83 != #0 GOTO label68 259 | GOTO label67 260 | LABEL label68 : 261 | t86 := #0 262 | t87 := t65 263 | t90 := #-2147483648 264 | t91 := t64 265 | t89 := t90 / t91 266 | t88 := #0 - t89 267 | IF t87 < t88 GOTO label74 268 | GOTO label75 269 | LABEL label74 : 270 | t86 := #1 271 | LABEL label75 : 272 | IF t86 != #0 GOTO label66 273 | GOTO label67 274 | LABEL label66 : 275 | t79 := #1 276 | LABEL label67 : 277 | IF t79 != #0 GOTO label51 278 | GOTO label54 279 | LABEL label54 : 280 | t92 := #0 281 | t93 := #0 282 | t94 := t64 283 | t95 := #0 284 | IF t94 <= t95 GOTO label80 285 | GOTO label81 286 | LABEL label80 : 287 | t93 := #1 288 | LABEL label81 : 289 | IF t93 != #0 GOTO label79 290 | GOTO label77 291 | LABEL label79 : 292 | t96 := #0 293 | t97 := t65 294 | t98 := #0 295 | IF t97 > t98 GOTO label82 296 | GOTO label83 297 | LABEL label82 : 298 | t96 := #1 299 | LABEL label83 : 300 | IF t96 != #0 GOTO label78 301 | GOTO label77 302 | LABEL label78 : 303 | t99 := #0 304 | t100 := t64 305 | t103 := #-2147483648 306 | t104 := t65 307 | t102 := t103 / t104 308 | t101 := #0 - t102 309 | IF t100 < t101 GOTO label84 310 | GOTO label85 311 | LABEL label84 : 312 | t99 := #1 313 | LABEL label85 : 314 | IF t99 != #0 GOTO label76 315 | GOTO label77 316 | LABEL label76 : 317 | t92 := #1 318 | LABEL label77 : 319 | IF t92 != #0 GOTO label51 320 | GOTO label53 321 | LABEL label53 : 322 | t105 := #0 323 | t106 := #0 324 | t107 := t64 325 | t108 := #0 326 | IF t107 <= t108 GOTO label91 327 | GOTO label92 328 | LABEL label91 : 329 | t106 := #1 330 | LABEL label92 : 331 | IF t106 != #0 GOTO label90 332 | GOTO label87 333 | LABEL label90 : 334 | t109 := #0 335 | t110 := t65 336 | t111 := #0 337 | IF t110 <= t111 GOTO label93 338 | GOTO label94 339 | LABEL label93 : 340 | t109 := #1 341 | LABEL label94 : 342 | IF t109 != #0 GOTO label89 343 | GOTO label87 344 | LABEL label89 : 345 | t112 := #0 346 | t113 := t64 347 | t114 := #0 348 | IF t113 != t114 GOTO label95 349 | GOTO label96 350 | LABEL label95 : 351 | t112 := #1 352 | LABEL label96 : 353 | IF t112 != #0 GOTO label88 354 | GOTO label87 355 | LABEL label88 : 356 | t115 := #0 357 | t116 := t65 358 | t118 := #2147483647 359 | t119 := t64 360 | t117 := t118 / t119 361 | IF t116 < t117 GOTO label97 362 | GOTO label98 363 | LABEL label97 : 364 | t115 := #1 365 | LABEL label98 : 366 | IF t115 != #0 GOTO label86 367 | GOTO label87 368 | LABEL label86 : 369 | t105 := #1 370 | LABEL label87 : 371 | IF t105 != #0 GOTO label51 372 | GOTO label52 373 | LABEL label51 : 374 | t66 := #1 375 | LABEL label52 : 376 | IF t66 != #0 GOTO label49 377 | GOTO label50 378 | LABEL label49 : 379 | t120 := t64 380 | RETURN t120 381 | LABEL label50 : 382 | t122 := t64 383 | t123 := t65 384 | t121 := t122 * t123 385 | RETURN t121 386 | FUNCTION safe_div : 387 | PARAM t124 388 | PARAM t125 389 | t126 := #0 390 | t127 := #0 391 | t128 := t125 392 | t129 := #0 393 | IF t128 == t129 GOTO label104 394 | GOTO label105 395 | LABEL label104 : 396 | t127 := #1 397 | LABEL label105 : 398 | IF t127 != #0 GOTO label101 399 | GOTO label103 400 | LABEL label103 : 401 | t130 := #0 402 | t131 := #0 403 | t132 := t124 404 | t134 := #-2147483648 405 | t133 := #0 - t134 406 | IF t132 == t133 GOTO label109 407 | GOTO label110 408 | LABEL label109 : 409 | t131 := #1 410 | LABEL label110 : 411 | IF t131 != #0 GOTO label108 412 | GOTO label107 413 | LABEL label108 : 414 | t135 := #0 415 | t136 := t125 416 | t138 := #1 417 | t137 := #0 - t138 418 | IF t136 == t137 GOTO label111 419 | GOTO label112 420 | LABEL label111 : 421 | t135 := #1 422 | LABEL label112 : 423 | IF t135 != #0 GOTO label106 424 | GOTO label107 425 | LABEL label106 : 426 | t130 := #1 427 | LABEL label107 : 428 | IF t130 != #0 GOTO label101 429 | GOTO label102 430 | LABEL label101 : 431 | t126 := #1 432 | LABEL label102 : 433 | IF t126 != #0 GOTO label99 434 | GOTO label100 435 | LABEL label99 : 436 | t139 := t124 437 | RETURN t139 438 | LABEL label100 : 439 | t141 := t124 440 | t142 := t125 441 | t140 := t141 / t142 442 | RETURN t140 443 | FUNCTION i_func_8 : 444 | PARAM t143 445 | PARAM t144 446 | PARAM t145 447 | PARAM t146 448 | PARAM t147 449 | PARAM t148 450 | t161 := t148 451 | t162 := #0 452 | IF t161 <= t162 GOTO label113 453 | GOTO label114 454 | LABEL label113 : 455 | t164 := #1512450053 456 | t163 := #0 - t164 457 | RETURN t163 458 | GOTO label115 459 | LABEL label114 : 460 | t166 := t148 461 | t167 := #1 462 | t165 := t166 - t167 463 | t148 := t165 464 | t164 := t148 465 | LABEL label115 : 466 | t169 := #0 467 | t170 := t144 468 | IF t170 != #0 GOTO label117 469 | GOTO label116 470 | LABEL label116 : 471 | t169 := #1 472 | LABEL label117 : 473 | t143 := t169 474 | t168 := t143 475 | t149 := t168 476 | t167 := t149 477 | t172 := t148 478 | t173 := #1 479 | t171 := t172 - t173 480 | t148 := t171 481 | t170 := t148 482 | t176 := t144 483 | t178 := #896749083 484 | t177 := #0 - t178 485 | t179 := t145 486 | t180 := t146 487 | t181 := t147 488 | t182 := t148 489 | ARG t182 490 | ARG t181 491 | ARG t180 492 | ARG t179 493 | ARG t177 494 | ARG t176 495 | t175 := CALL i_func_8 496 | t143 := t175 497 | t174 := t143 498 | t150 := t174 499 | t173 := t150 500 | t186 := #896829459 501 | t185 := #0 - t186 502 | t187 := t144 503 | ARG t187 504 | ARG t185 505 | t184 := CALL safe_div 506 | t143 := t184 507 | t183 := t143 508 | t151 := t183 509 | t182 := t151 510 | t188 := #295642080 511 | t152 := t188 512 | t187 := t152 513 | t189 := #602091564 514 | t153 := t189 515 | t188 := t153 516 | t191 := #988962615 517 | t190 := #0 - t191 518 | t154 := t190 519 | t189 := t154 520 | t193 := #367593023 521 | t192 := #0 - t193 522 | t155 := t192 523 | t191 := t155 524 | t195 := #27229972 525 | t194 := #0 - t195 526 | t156 := t194 527 | t193 := t156 528 | t196 := #644270041 529 | t157 := t196 530 | t195 := t157 531 | t197 := #1219844571 532 | t158 := t197 533 | t196 := t158 534 | t199 := #1932311414 535 | t198 := #0 - t199 536 | t159 := t198 537 | t197 := t159 538 | t201 := #1163090888 539 | t200 := #0 - t201 540 | t160 := t200 541 | t199 := t160 542 | t203 := t148 543 | t204 := #4 544 | t202 := t203 - t204 545 | t148 := t202 546 | t201 := t148 547 | t205 := #0 548 | t206 := t143 549 | t207 := t144 550 | IF t206 != t207 GOTO label118 551 | GOTO label119 552 | LABEL label118 : 553 | t205 := #1 554 | LABEL label119 : 555 | t209 := #836850414 556 | t210 := t145 557 | t211 := t146 558 | t212 := t147 559 | t213 := t149 560 | t214 := t148 561 | ARG t214 562 | ARG t213 563 | ARG t212 564 | ARG t211 565 | ARG t210 566 | ARG t209 567 | t208 := CALL i_func_8 568 | t216 := t151 569 | t150 := t216 570 | t215 := t150 571 | t218 := t152 572 | t219 := t153 573 | t220 := t154 574 | t222 := #316285467 575 | t221 := #0 - t222 576 | t223 := t155 577 | t224 := t148 578 | ARG t224 579 | ARG t223 580 | ARG t221 581 | ARG t220 582 | ARG t219 583 | ARG t218 584 | t217 := CALL i_func_8 585 | t226 := t156 586 | t227 := t157 587 | t228 := t158 588 | t229 := t159 589 | t230 := t160 590 | t231 := t148 591 | ARG t231 592 | ARG t230 593 | ARG t229 594 | ARG t228 595 | ARG t227 596 | ARG t226 597 | t225 := CALL i_func_8 598 | t232 := t148 599 | ARG t232 600 | ARG t225 601 | ARG t217 602 | ARG t215 603 | ARG t208 604 | ARG t205 605 | t204 := CALL i_func_8 606 | t233 := t149 607 | WRITE t233 608 | t234 := t150 609 | WRITE t234 610 | t235 := t151 611 | WRITE t235 612 | t236 := t152 613 | WRITE t236 614 | t237 := t153 615 | WRITE t237 616 | t238 := t154 617 | WRITE t238 618 | t239 := t155 619 | WRITE t239 620 | t240 := t156 621 | WRITE t240 622 | t241 := t157 623 | WRITE t241 624 | t242 := t158 625 | WRITE t242 626 | t243 := t159 627 | WRITE t243 628 | t244 := t160 629 | WRITE t244 630 | t246 := t148 631 | t247 := #1 632 | t245 := t246 - t247 633 | t148 := t245 634 | t244 := t148 635 | t250 := #1208889375 636 | t251 := t144 637 | t252 := t145 638 | t253 := t146 639 | t254 := t147 640 | t255 := t148 641 | ARG t255 642 | ARG t254 643 | ARG t253 644 | ARG t252 645 | ARG t251 646 | ARG t250 647 | t249 := CALL i_func_8 648 | t143 := t249 649 | t248 := t143 650 | RETURN t248 651 | FUNCTION top_caller : 652 | PARAM t256 653 | t265 := t256 654 | t266 := #0 655 | IF t265 <= t266 GOTO label120 656 | GOTO label121 657 | LABEL label120 : 658 | t268 := #80664145 659 | t267 := #0 - t268 660 | RETURN t267 661 | GOTO label122 662 | LABEL label121 : 663 | t270 := t256 664 | t271 := #1 665 | t269 := t270 - t271 666 | t256 := t269 667 | t268 := t256 668 | LABEL label122 : 669 | t273 := t256 670 | t274 := #1 671 | t272 := t273 - t274 672 | t256 := t272 673 | t271 := t256 674 | t276 := t256 675 | ARG t276 676 | t275 := CALL top_caller 677 | t257 := t275 678 | t274 := t257 679 | t278 := t256 680 | t279 := #1 681 | t277 := t278 - t279 682 | t256 := t277 683 | t276 := t256 684 | t282 := t256 685 | ARG t282 686 | t281 := CALL top_caller 687 | t257 := t281 688 | t280 := t257 689 | t258 := t280 690 | t279 := t258 691 | t284 := #1697852659 692 | t283 := #0 - t284 693 | t259 := t283 694 | t282 := t259 695 | t286 := #0 696 | t287 := t258 697 | t288 := t259 698 | IF t287 < t288 GOTO label123 699 | GOTO label124 700 | LABEL label123 : 701 | t286 := #1 702 | LABEL label124 : 703 | t257 := t286 704 | t285 := t257 705 | t260 := t285 706 | t284 := t260 707 | t290 := t256 708 | t291 := #1 709 | t289 := t290 - t291 710 | t256 := t289 711 | t288 := t256 712 | t293 := t256 713 | ARG t293 714 | t292 := CALL top_caller 715 | t261 := t292 716 | t291 := t261 717 | t295 := #367545819 718 | t294 := #0 - t295 719 | t262 := t294 720 | t293 := t262 721 | t297 := #1965617935 722 | t296 := #0 - t297 723 | t263 := t296 724 | t295 := t263 725 | t298 := #0 726 | t264 := t298 727 | t297 := t264 728 | t300 := t256 729 | t301 := #2 730 | t299 := t300 - t301 731 | t256 := t299 732 | t298 := t256 733 | t302 := t257 734 | t304 := t258 735 | t305 := t259 736 | t303 := t304 - t305 737 | t307 := t256 738 | ARG t307 739 | t306 := CALL top_caller 740 | t309 := t261 741 | t260 := t309 742 | t308 := t260 743 | t310 := #0 744 | t311 := t262 745 | t312 := t263 746 | IF t311 >= t312 GOTO label125 747 | GOTO label126 748 | LABEL label125 : 749 | t310 := #1 750 | LABEL label126 : 751 | t313 := t256 752 | ARG t313 753 | ARG t310 754 | ARG t308 755 | ARG t306 756 | ARG t303 757 | ARG t302 758 | t301 := CALL i_func_8 759 | t315 := t256 760 | t316 := #1 761 | t314 := t315 - t316 762 | t256 := t314 763 | t313 := t256 764 | LABEL label127 : 765 | t319 := t258 766 | t320 := t259 767 | t321 := t260 768 | t322 := t261 769 | t323 := t262 770 | t324 := t256 771 | ARG t324 772 | ARG t323 773 | ARG t322 774 | ARG t321 775 | ARG t320 776 | ARG t319 777 | t318 := CALL i_func_8 778 | t257 := t318 779 | t317 := t257 780 | IF t317 != #0 GOTO label130 781 | GOTO label129 782 | LABEL label130 : 783 | t325 := #0 784 | t326 := t264 785 | t327 := #10 786 | IF t326 < t327 GOTO label131 787 | GOTO label132 788 | LABEL label131 : 789 | t325 := #1 790 | LABEL label132 : 791 | IF t325 != #0 GOTO label128 792 | GOTO label129 793 | LABEL label128 : 794 | t332 := #0 795 | t333 := t258 796 | t334 := t259 797 | IF t333 != t334 GOTO label133 798 | GOTO label134 799 | LABEL label133 : 800 | t332 := #1 801 | LABEL label134 : 802 | t257 := t332 803 | t331 := t257 804 | t328 := t331 805 | t327 := t328 806 | t336 := t256 807 | t337 := #1 808 | t335 := t336 - t337 809 | t256 := t335 810 | t334 := t256 811 | t340 := t258 812 | t341 := t259 813 | t342 := t260 814 | t343 := t261 815 | t344 := t262 816 | t345 := t256 817 | ARG t345 818 | ARG t344 819 | ARG t343 820 | ARG t342 821 | ARG t341 822 | ARG t340 823 | t339 := CALL i_func_8 824 | t257 := t339 825 | t338 := t257 826 | t329 := t338 827 | t337 := t329 828 | t347 := #0 829 | t348 := t258 830 | t349 := t259 831 | IF t348 >= t349 GOTO label135 832 | GOTO label136 833 | LABEL label135 : 834 | t347 := #1 835 | LABEL label136 : 836 | t257 := t347 837 | t346 := t257 838 | t330 := t346 839 | t345 := t330 840 | t351 := t264 841 | t352 := #1 842 | t350 := t351 + t352 843 | t264 := t350 844 | t349 := t264 845 | t354 := t256 846 | t355 := #1 847 | t353 := t354 - t355 848 | t256 := t353 849 | t352 := t256 850 | t356 := t256 851 | ARG t356 852 | t355 := CALL top_caller 853 | t357 := t328 854 | WRITE t357 855 | t358 := t329 856 | WRITE t358 857 | t359 := t330 858 | WRITE t359 859 | GOTO label127 860 | LABEL label129 : 861 | t360 := t257 862 | WRITE t360 863 | t361 := t258 864 | WRITE t361 865 | t362 := t259 866 | WRITE t362 867 | t363 := t260 868 | WRITE t363 869 | t364 := t261 870 | WRITE t364 871 | t365 := t262 872 | WRITE t365 873 | t366 := t263 874 | WRITE t366 875 | t369 := t259 876 | t258 := t369 877 | t368 := t258 878 | t257 := t368 879 | t367 := t257 880 | RETURN t367 881 | FUNCTION main : 882 | t370 := #10 883 | ARG t370 884 | t369 := CALL top_caller 885 | t371 := #0 886 | RETURN t371 887 | FUNCTION safe_add : 888 | PARAM t1 889 | PARAM t2 890 | t3 := #0 891 | t4 := #0 892 | t5 := #0 893 | t6 := t1 894 | t7 := #0 895 | IF t6 > t7 GOTO label10 896 | GOTO label11 897 | LABEL label10 : 898 | t5 := #1 899 | LABEL label11 : 900 | IF t5 != #0 GOTO label9 901 | GOTO label7 902 | LABEL label9 : 903 | t8 := #0 904 | t9 := t2 905 | t10 := #0 906 | IF t9 > t10 GOTO label12 907 | GOTO label13 908 | LABEL label12 : 909 | t8 := #1 910 | LABEL label13 : 911 | IF t8 != #0 GOTO label8 912 | GOTO label7 913 | LABEL label8 : 914 | t11 := #0 915 | t12 := t1 916 | t14 := #2147483647 917 | t15 := t2 918 | t13 := t14 - t15 919 | IF t12 > t13 GOTO label14 920 | GOTO label15 921 | LABEL label14 : 922 | t11 := #1 923 | LABEL label15 : 924 | IF t11 != #0 GOTO label6 925 | GOTO label7 926 | LABEL label6 : 927 | t4 := #1 928 | LABEL label7 : 929 | IF t4 != #0 GOTO label3 930 | GOTO label5 931 | LABEL label5 : 932 | t16 := #0 933 | t17 := #0 934 | t18 := t1 935 | t19 := #0 936 | IF t18 < t19 GOTO label20 937 | GOTO label21 938 | LABEL label20 : 939 | t17 := #1 940 | LABEL label21 : 941 | IF t17 != #0 GOTO label19 942 | GOTO label17 943 | LABEL label19 : 944 | t20 := #0 945 | t21 := t2 946 | t22 := #0 947 | IF t21 < t22 GOTO label22 948 | GOTO label23 949 | LABEL label22 : 950 | t20 := #1 951 | LABEL label23 : 952 | IF t20 != #0 GOTO label18 953 | GOTO label17 954 | LABEL label18 : 955 | t23 := #0 956 | t24 := t1 957 | t27 := #-2147483648 958 | t26 := #0 - t27 959 | t28 := t2 960 | t25 := t26 - t28 961 | IF t24 < t25 GOTO label24 962 | GOTO label25 963 | LABEL label24 : 964 | t23 := #1 965 | LABEL label25 : 966 | IF t23 != #0 GOTO label16 967 | GOTO label17 968 | LABEL label16 : 969 | t16 := #1 970 | LABEL label17 : 971 | IF t16 != #0 GOTO label3 972 | GOTO label4 973 | LABEL label3 : 974 | t3 := #1 975 | LABEL label4 : 976 | IF t3 != #0 GOTO label1 977 | GOTO label2 978 | LABEL label1 : 979 | t29 := t1 980 | RETURN t29 981 | LABEL label2 : 982 | t31 := t1 983 | t32 := t2 984 | t30 := t31 + t32 985 | RETURN t30 986 | FUNCTION safe_sub : 987 | PARAM t33 988 | PARAM t34 989 | t35 := #0 990 | t36 := #0 991 | t37 := t33 992 | t38 := #0 993 | IF t37 > t38 GOTO label33 994 | GOTO label34 995 | LABEL label33 : 996 | t36 := #1 997 | LABEL label34 : 998 | IF t36 != #0 GOTO label32 999 | GOTO label30 1000 | LABEL label32 : 1001 | t39 := #0 1002 | t40 := t34 1003 | t41 := #0 1004 | IF t40 < t41 GOTO label35 1005 | GOTO label36 1006 | LABEL label35 : 1007 | t39 := #1 1008 | LABEL label36 : 1009 | IF t39 != #0 GOTO label31 1010 | GOTO label30 1011 | LABEL label31 : 1012 | t42 := #0 1013 | t43 := t33 1014 | t45 := #2147483647 1015 | t46 := t34 1016 | t44 := t45 + t46 1017 | IF t43 > t44 GOTO label37 1018 | GOTO label38 1019 | LABEL label37 : 1020 | t42 := #1 1021 | LABEL label38 : 1022 | IF t42 != #0 GOTO label29 1023 | GOTO label30 1024 | LABEL label29 : 1025 | t35 := #1 1026 | LABEL label30 : 1027 | IF t35 != #0 GOTO label26 1028 | GOTO label28 1029 | LABEL label28 : 1030 | t47 := #0 1031 | t48 := #0 1032 | t49 := t33 1033 | t50 := #0 1034 | IF t49 < t50 GOTO label43 1035 | GOTO label44 1036 | LABEL label43 : 1037 | t48 := #1 1038 | LABEL label44 : 1039 | IF t48 != #0 GOTO label42 1040 | GOTO label40 1041 | LABEL label42 : 1042 | t51 := #0 1043 | t52 := t34 1044 | t53 := #0 1045 | IF t52 > t53 GOTO label45 1046 | GOTO label46 1047 | LABEL label45 : 1048 | t51 := #1 1049 | LABEL label46 : 1050 | IF t51 != #0 GOTO label41 1051 | GOTO label40 1052 | LABEL label41 : 1053 | t54 := #0 1054 | t55 := t33 1055 | t58 := #-2147483648 1056 | t57 := #0 - t58 1057 | t59 := t34 1058 | t56 := t57 + t59 1059 | IF t55 < t56 GOTO label47 1060 | GOTO label48 1061 | LABEL label47 : 1062 | t54 := #1 1063 | LABEL label48 : 1064 | IF t54 != #0 GOTO label39 1065 | GOTO label40 1066 | LABEL label39 : 1067 | t47 := #1 1068 | LABEL label40 : 1069 | IF t47 != #0 GOTO label26 1070 | GOTO label27 1071 | LABEL label26 : 1072 | t60 := t33 1073 | RETURN t60 1074 | LABEL label27 : 1075 | t62 := t33 1076 | t63 := t34 1077 | t61 := t62 - t63 1078 | RETURN t61 1079 | FUNCTION safe_mul : 1080 | PARAM t64 1081 | PARAM t65 1082 | t66 := #0 1083 | t67 := #0 1084 | t68 := #0 1085 | t69 := t64 1086 | t70 := #0 1087 | IF t69 > t70 GOTO label60 1088 | GOTO label61 1089 | LABEL label60 : 1090 | t68 := #1 1091 | LABEL label61 : 1092 | IF t68 != #0 GOTO label59 1093 | GOTO label57 1094 | LABEL label59 : 1095 | t71 := #0 1096 | t72 := t65 1097 | t73 := #0 1098 | IF t72 > t73 GOTO label62 1099 | GOTO label63 1100 | LABEL label62 : 1101 | t71 := #1 1102 | LABEL label63 : 1103 | IF t71 != #0 GOTO label58 1104 | GOTO label57 1105 | LABEL label58 : 1106 | t74 := #0 1107 | t75 := t64 1108 | t77 := #2147483647 1109 | t78 := t65 1110 | t76 := t77 / t78 1111 | IF t75 > t76 GOTO label64 1112 | GOTO label65 1113 | LABEL label64 : 1114 | t74 := #1 1115 | LABEL label65 : 1116 | IF t74 != #0 GOTO label56 1117 | GOTO label57 1118 | LABEL label56 : 1119 | t67 := #1 1120 | LABEL label57 : 1121 | IF t67 != #0 GOTO label51 1122 | GOTO label55 1123 | LABEL label55 : 1124 | t79 := #0 1125 | t80 := #0 1126 | t81 := t64 1127 | t82 := #0 1128 | IF t81 > t82 GOTO label70 1129 | GOTO label71 1130 | LABEL label70 : 1131 | t80 := #1 1132 | LABEL label71 : 1133 | IF t80 != #0 GOTO label69 1134 | GOTO label67 1135 | LABEL label69 : 1136 | t83 := #0 1137 | t84 := t65 1138 | t85 := #0 1139 | IF t84 <= t85 GOTO label72 1140 | GOTO label73 1141 | LABEL label72 : 1142 | t83 := #1 1143 | LABEL label73 : 1144 | IF t83 != #0 GOTO label68 1145 | GOTO label67 1146 | LABEL label68 : 1147 | t86 := #0 1148 | t87 := t65 1149 | t90 := #-2147483648 1150 | t91 := t64 1151 | t89 := t90 / t91 1152 | t88 := #0 - t89 1153 | IF t87 < t88 GOTO label74 1154 | GOTO label75 1155 | LABEL label74 : 1156 | t86 := #1 1157 | LABEL label75 : 1158 | IF t86 != #0 GOTO label66 1159 | GOTO label67 1160 | LABEL label66 : 1161 | t79 := #1 1162 | LABEL label67 : 1163 | IF t79 != #0 GOTO label51 1164 | GOTO label54 1165 | LABEL label54 : 1166 | t92 := #0 1167 | t93 := #0 1168 | t94 := t64 1169 | t95 := #0 1170 | IF t94 <= t95 GOTO label80 1171 | GOTO label81 1172 | LABEL label80 : 1173 | t93 := #1 1174 | LABEL label81 : 1175 | IF t93 != #0 GOTO label79 1176 | GOTO label77 1177 | LABEL label79 : 1178 | t96 := #0 1179 | t97 := t65 1180 | t98 := #0 1181 | IF t97 > t98 GOTO label82 1182 | GOTO label83 1183 | LABEL label82 : 1184 | t96 := #1 1185 | LABEL label83 : 1186 | IF t96 != #0 GOTO label78 1187 | GOTO label77 1188 | LABEL label78 : 1189 | t99 := #0 1190 | t100 := t64 1191 | t103 := #-2147483648 1192 | t104 := t65 1193 | t102 := t103 / t104 1194 | t101 := #0 - t102 1195 | IF t100 < t101 GOTO label84 1196 | GOTO label85 1197 | LABEL label84 : 1198 | t99 := #1 1199 | LABEL label85 : 1200 | IF t99 != #0 GOTO label76 1201 | GOTO label77 1202 | LABEL label76 : 1203 | t92 := #1 1204 | LABEL label77 : 1205 | IF t92 != #0 GOTO label51 1206 | GOTO label53 1207 | LABEL label53 : 1208 | t105 := #0 1209 | t106 := #0 1210 | t107 := t64 1211 | t108 := #0 1212 | IF t107 <= t108 GOTO label91 1213 | GOTO label92 1214 | LABEL label91 : 1215 | t106 := #1 1216 | LABEL label92 : 1217 | IF t106 != #0 GOTO label90 1218 | GOTO label87 1219 | LABEL label90 : 1220 | t109 := #0 1221 | t110 := t65 1222 | t111 := #0 1223 | IF t110 <= t111 GOTO label93 1224 | GOTO label94 1225 | LABEL label93 : 1226 | t109 := #1 1227 | LABEL label94 : 1228 | IF t109 != #0 GOTO label89 1229 | GOTO label87 1230 | LABEL label89 : 1231 | t112 := #0 1232 | t113 := t64 1233 | t114 := #0 1234 | IF t113 != t114 GOTO label95 1235 | GOTO label96 1236 | LABEL label95 : 1237 | t112 := #1 1238 | LABEL label96 : 1239 | IF t112 != #0 GOTO label88 1240 | GOTO label87 1241 | LABEL label88 : 1242 | t115 := #0 1243 | t116 := t65 1244 | t118 := #2147483647 1245 | t119 := t64 1246 | t117 := t118 / t119 1247 | IF t116 < t117 GOTO label97 1248 | GOTO label98 1249 | LABEL label97 : 1250 | t115 := #1 1251 | LABEL label98 : 1252 | IF t115 != #0 GOTO label86 1253 | GOTO label87 1254 | LABEL label86 : 1255 | t105 := #1 1256 | LABEL label87 : 1257 | IF t105 != #0 GOTO label51 1258 | GOTO label52 1259 | LABEL label51 : 1260 | t66 := #1 1261 | LABEL label52 : 1262 | IF t66 != #0 GOTO label49 1263 | GOTO label50 1264 | LABEL label49 : 1265 | t120 := t64 1266 | RETURN t120 1267 | LABEL label50 : 1268 | t122 := t64 1269 | t123 := t65 1270 | t121 := t122 * t123 1271 | RETURN t121 1272 | FUNCTION safe_div : 1273 | PARAM t124 1274 | PARAM t125 1275 | t126 := #0 1276 | t127 := #0 1277 | t128 := t125 1278 | t129 := #0 1279 | IF t128 == t129 GOTO label104 1280 | GOTO label105 1281 | LABEL label104 : 1282 | t127 := #1 1283 | LABEL label105 : 1284 | IF t127 != #0 GOTO label101 1285 | GOTO label103 1286 | LABEL label103 : 1287 | t130 := #0 1288 | t131 := #0 1289 | t132 := t124 1290 | t134 := #-2147483648 1291 | t133 := #0 - t134 1292 | IF t132 == t133 GOTO label109 1293 | GOTO label110 1294 | LABEL label109 : 1295 | t131 := #1 1296 | LABEL label110 : 1297 | IF t131 != #0 GOTO label108 1298 | GOTO label107 1299 | LABEL label108 : 1300 | t135 := #0 1301 | t136 := t125 1302 | t138 := #1 1303 | t137 := #0 - t138 1304 | IF t136 == t137 GOTO label111 1305 | GOTO label112 1306 | LABEL label111 : 1307 | t135 := #1 1308 | LABEL label112 : 1309 | IF t135 != #0 GOTO label106 1310 | GOTO label107 1311 | LABEL label106 : 1312 | t130 := #1 1313 | LABEL label107 : 1314 | IF t130 != #0 GOTO label101 1315 | GOTO label102 1316 | LABEL label101 : 1317 | t126 := #1 1318 | LABEL label102 : 1319 | IF t126 != #0 GOTO label99 1320 | GOTO label100 1321 | LABEL label99 : 1322 | t139 := t124 1323 | RETURN t139 1324 | LABEL label100 : 1325 | t141 := t124 1326 | t142 := t125 1327 | t140 := t141 / t142 1328 | RETURN t140 1329 | FUNCTION i_func_8 : 1330 | PARAM t143 1331 | PARAM t144 1332 | PARAM t145 1333 | PARAM t146 1334 | PARAM t147 1335 | PARAM t148 1336 | t161 := t148 1337 | t162 := #0 1338 | IF t161 <= t162 GOTO label113 1339 | GOTO label114 1340 | LABEL label113 : 1341 | t164 := #1512450053 1342 | t163 := #0 - t164 1343 | RETURN t163 1344 | GOTO label115 1345 | LABEL label114 : 1346 | t166 := t148 1347 | t167 := #1 1348 | t165 := t166 - t167 1349 | t148 := t165 1350 | t164 := t148 1351 | LABEL label115 : 1352 | t169 := #0 1353 | t170 := t144 1354 | IF t170 != #0 GOTO label117 1355 | GOTO label116 1356 | LABEL label116 : 1357 | t169 := #1 1358 | LABEL label117 : 1359 | t143 := t169 1360 | t168 := t143 1361 | t149 := t168 1362 | t167 := t149 1363 | t172 := t148 1364 | t173 := #1 1365 | t171 := t172 - t173 1366 | t148 := t171 1367 | t170 := t148 1368 | t176 := t144 1369 | t178 := #896749083 1370 | t177 := #0 - t178 1371 | t179 := t145 1372 | t180 := t146 1373 | t181 := t147 1374 | t182 := t148 1375 | ARG t182 1376 | ARG t181 1377 | ARG t180 1378 | ARG t179 1379 | ARG t177 1380 | ARG t176 1381 | t175 := CALL i_func_8 1382 | t143 := t175 1383 | t174 := t143 1384 | t150 := t174 1385 | t173 := t150 1386 | t186 := #896829459 1387 | t185 := #0 - t186 1388 | t187 := t144 1389 | ARG t187 1390 | ARG t185 1391 | t184 := CALL safe_div 1392 | t143 := t184 1393 | t183 := t143 1394 | t151 := t183 1395 | t182 := t151 1396 | t188 := #295642080 1397 | t152 := t188 1398 | t187 := t152 1399 | t189 := #602091564 1400 | t153 := t189 1401 | t188 := t153 1402 | t191 := #988962615 1403 | t190 := #0 - t191 1404 | t154 := t190 1405 | t189 := t154 1406 | t193 := #367593023 1407 | t192 := #0 - t193 1408 | t155 := t192 1409 | t191 := t155 1410 | t195 := #27229972 1411 | t194 := #0 - t195 1412 | t156 := t194 1413 | t193 := t156 1414 | t196 := #644270041 1415 | t157 := t196 1416 | t195 := t157 1417 | t197 := #1219844571 1418 | t158 := t197 1419 | t196 := t158 1420 | t199 := #1932311414 1421 | t198 := #0 - t199 1422 | t159 := t198 1423 | t197 := t159 1424 | t201 := #1163090888 1425 | t200 := #0 - t201 1426 | t160 := t200 1427 | t199 := t160 1428 | t203 := t148 1429 | t204 := #4 1430 | t202 := t203 - t204 1431 | t148 := t202 1432 | t201 := t148 1433 | t205 := #0 1434 | t206 := t143 1435 | t207 := t144 1436 | IF t206 != t207 GOTO label118 1437 | GOTO label119 1438 | LABEL label118 : 1439 | t205 := #1 1440 | LABEL label119 : 1441 | t209 := #836850414 1442 | t210 := t145 1443 | t211 := t146 1444 | t212 := t147 1445 | t213 := t149 1446 | t214 := t148 1447 | ARG t214 1448 | ARG t213 1449 | ARG t212 1450 | ARG t211 1451 | ARG t210 1452 | ARG t209 1453 | t208 := CALL i_func_8 1454 | t216 := t151 1455 | t150 := t216 1456 | t215 := t150 1457 | t218 := t152 1458 | t219 := t153 1459 | t220 := t154 1460 | t222 := #316285467 1461 | t221 := #0 - t222 1462 | t223 := t155 1463 | t224 := t148 1464 | ARG t224 1465 | ARG t223 1466 | ARG t221 1467 | ARG t220 1468 | ARG t219 1469 | ARG t218 1470 | t217 := CALL i_func_8 1471 | t226 := t156 1472 | t227 := t157 1473 | t228 := t158 1474 | t229 := t159 1475 | t230 := t160 1476 | t231 := t148 1477 | ARG t231 1478 | ARG t230 1479 | ARG t229 1480 | ARG t228 1481 | ARG t227 1482 | ARG t226 1483 | t225 := CALL i_func_8 1484 | t232 := t148 1485 | ARG t232 1486 | ARG t225 1487 | ARG t217 1488 | ARG t215 1489 | ARG t208 1490 | ARG t205 1491 | t204 := CALL i_func_8 1492 | t233 := t149 1493 | WRITE t233 1494 | t234 := t150 1495 | WRITE t234 1496 | t235 := t151 1497 | WRITE t235 1498 | t236 := t152 1499 | WRITE t236 1500 | t237 := t153 1501 | WRITE t237 1502 | t238 := t154 1503 | WRITE t238 1504 | t239 := t155 1505 | WRITE t239 1506 | t240 := t156 1507 | WRITE t240 1508 | t241 := t157 1509 | WRITE t241 1510 | t242 := t158 1511 | WRITE t242 1512 | t243 := t159 1513 | WRITE t243 1514 | t244 := t160 1515 | WRITE t244 1516 | t246 := t148 1517 | t247 := #1 1518 | t245 := t246 - t247 1519 | t148 := t245 1520 | t244 := t148 1521 | t250 := #1208889375 1522 | t251 := t144 1523 | t252 := t145 1524 | t253 := t146 1525 | t254 := t147 1526 | t255 := t148 1527 | ARG t255 1528 | ARG t254 1529 | ARG t253 1530 | ARG t252 1531 | ARG t251 1532 | ARG t250 1533 | t249 := CALL i_func_8 1534 | t143 := t249 1535 | t248 := t143 1536 | RETURN t248 1537 | FUNCTION top_caller : 1538 | PARAM t256 1539 | t265 := t256 1540 | t266 := #0 1541 | IF t265 <= t266 GOTO label120 1542 | GOTO label121 1543 | LABEL label120 : 1544 | t268 := #80664145 1545 | t267 := #0 - t268 1546 | RETURN t267 1547 | GOTO label122 1548 | LABEL label121 : 1549 | t270 := t256 1550 | t271 := #1 1551 | t269 := t270 - t271 1552 | t256 := t269 1553 | t268 := t256 1554 | LABEL label122 : 1555 | t273 := t256 1556 | t274 := #1 1557 | t272 := t273 - t274 1558 | t256 := t272 1559 | t271 := t256 1560 | t276 := t256 1561 | ARG t276 1562 | t275 := CALL top_caller 1563 | t257 := t275 1564 | t274 := t257 1565 | t278 := t256 1566 | t279 := #1 1567 | t277 := t278 - t279 1568 | t256 := t277 1569 | t276 := t256 1570 | t282 := t256 1571 | ARG t282 1572 | t281 := CALL top_caller 1573 | t257 := t281 1574 | t280 := t257 1575 | t258 := t280 1576 | t279 := t258 1577 | t284 := #1697852659 1578 | t283 := #0 - t284 1579 | t259 := t283 1580 | t282 := t259 1581 | t286 := #0 1582 | t287 := t258 1583 | t288 := t259 1584 | IF t287 < t288 GOTO label123 1585 | GOTO label124 1586 | LABEL label123 : 1587 | t286 := #1 1588 | LABEL label124 : 1589 | t257 := t286 1590 | t285 := t257 1591 | t260 := t285 1592 | t284 := t260 1593 | t290 := t256 1594 | t291 := #1 1595 | t289 := t290 - t291 1596 | t256 := t289 1597 | t288 := t256 1598 | t293 := t256 1599 | ARG t293 1600 | t292 := CALL top_caller 1601 | t261 := t292 1602 | t291 := t261 1603 | t295 := #367545819 1604 | t294 := #0 - t295 1605 | t262 := t294 1606 | t293 := t262 1607 | t297 := #1965617935 1608 | t296 := #0 - t297 1609 | t263 := t296 1610 | t295 := t263 1611 | t298 := #0 1612 | t264 := t298 1613 | t297 := t264 1614 | t300 := t256 1615 | t301 := #2 1616 | t299 := t300 - t301 1617 | t256 := t299 1618 | t298 := t256 1619 | t302 := t257 1620 | t304 := t258 1621 | t305 := t259 1622 | t303 := t304 - t305 1623 | t307 := t256 1624 | ARG t307 1625 | t306 := CALL top_caller 1626 | t309 := t261 1627 | t260 := t309 1628 | t308 := t260 1629 | t310 := #0 1630 | t311 := t262 1631 | t312 := t263 1632 | IF t311 >= t312 GOTO label125 1633 | GOTO label126 1634 | LABEL label125 : 1635 | t310 := #1 1636 | LABEL label126 : 1637 | t313 := t256 1638 | ARG t313 1639 | ARG t310 1640 | ARG t308 1641 | ARG t306 1642 | ARG t303 1643 | ARG t302 1644 | t301 := CALL i_func_8 1645 | t315 := t256 1646 | t316 := #1 1647 | t314 := t315 - t316 1648 | t256 := t314 1649 | t313 := t256 1650 | LABEL label127 : 1651 | t319 := t258 1652 | t320 := t259 1653 | t321 := t260 1654 | t322 := t261 1655 | t323 := t262 1656 | t324 := t256 1657 | ARG t324 1658 | ARG t323 1659 | ARG t322 1660 | ARG t321 1661 | ARG t320 1662 | ARG t319 1663 | t318 := CALL i_func_8 1664 | t257 := t318 1665 | t317 := t257 1666 | IF t317 != #0 GOTO label130 1667 | GOTO label129 1668 | LABEL label130 : 1669 | t325 := #0 1670 | t326 := t264 1671 | t327 := #10 1672 | IF t326 < t327 GOTO label131 1673 | GOTO label132 1674 | LABEL label131 : 1675 | t325 := #1 1676 | LABEL label132 : 1677 | IF t325 != #0 GOTO label128 1678 | GOTO label129 1679 | LABEL label128 : 1680 | t332 := #0 1681 | t333 := t258 1682 | t334 := t259 1683 | IF t333 != t334 GOTO label133 1684 | GOTO label134 1685 | LABEL label133 : 1686 | t332 := #1 1687 | LABEL label134 : 1688 | t257 := t332 1689 | t331 := t257 1690 | t328 := t331 1691 | t327 := t328 1692 | t336 := t256 1693 | t337 := #1 1694 | t335 := t336 - t337 1695 | t256 := t335 1696 | t334 := t256 1697 | t340 := t258 1698 | t341 := t259 1699 | t342 := t260 1700 | t343 := t261 1701 | t344 := t262 1702 | t345 := t256 1703 | ARG t345 1704 | ARG t344 1705 | ARG t343 1706 | ARG t342 1707 | ARG t341 1708 | ARG t340 1709 | t339 := CALL i_func_8 1710 | t257 := t339 1711 | t338 := t257 1712 | t329 := t338 1713 | t337 := t329 1714 | t347 := #0 1715 | t348 := t258 1716 | t349 := t259 1717 | IF t348 >= t349 GOTO label135 1718 | GOTO label136 1719 | LABEL label135 : 1720 | t347 := #1 1721 | LABEL label136 : 1722 | t257 := t347 1723 | t346 := t257 1724 | t330 := t346 1725 | t345 := t330 1726 | t351 := t264 1727 | t352 := #1 1728 | t350 := t351 + t352 1729 | t264 := t350 1730 | t349 := t264 1731 | t354 := t256 1732 | t355 := #1 1733 | t353 := t354 - t355 1734 | t256 := t353 1735 | t352 := t256 1736 | t356 := t256 1737 | ARG t356 1738 | t355 := CALL top_caller 1739 | t357 := t328 1740 | WRITE t357 1741 | t358 := t329 1742 | WRITE t358 1743 | t359 := t330 1744 | WRITE t359 1745 | GOTO label127 1746 | LABEL label129 : 1747 | t360 := t257 1748 | WRITE t360 1749 | t361 := t258 1750 | WRITE t361 1751 | t362 := t259 1752 | WRITE t362 1753 | t363 := t260 1754 | WRITE t363 1755 | t364 := t261 1756 | WRITE t364 1757 | t365 := t262 1758 | WRITE t365 1759 | t366 := t263 1760 | WRITE t366 1761 | t369 := t259 1762 | t258 := t369 1763 | t368 := t258 1764 | t257 := t368 1765 | t367 := t257 1766 | RETURN t367 1767 | FUNCTION main : 1768 | t370 := #10 1769 | ARG t370 1770 | t369 := CALL top_caller 1771 | t371 := #0 1772 | RETURN t371 1773 | -------------------------------------------------------------------------------- /py-irsim/resources_rc.py: -------------------------------------------------------------------------------- 1 | # uncompyle6 version 3.6.7 2 | # Python bytecode 2.7 (62211) 3 | # Decompiled from: Python 3.8.2 (default, Apr 27 2020, 15:53:34) 4 | # [GCC 9.3.0] 5 | # Embedded file name: /home/zhuhaoyang/myWork/vm_modified source/resources_rc.py 6 | # Compiled at: 2012-02-20 21:32:36 7 | from PyQt4 import QtCore 8 | qt_resource_data = b'\x00\x00\x05\xbc\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04gAMA\x00\x00\xaf\xc87\x05\x8a\xe9\x00\x00\x00\x19tEXtSoftware\x00Adobe ImageReadyq\xc9e<\x00\x00\x05NIDATx\xdab\xfc\xff\xff?\xc3@\x02\x80\x00b\xc0\xe6\x80\xc7\xe6\x0c\x89O\xcc\x19>\xec\xd7e\xb0\x04r\xd9\x80\x98\x91\\\xf3O\x8a3\x18\x9e\x16g8\xb0_\x94!\r\xc8e\x07b&dy\x80\x00b\xc2f9Pp\x1e\x9b\xaa\x02\xbf<+\xc3\xceYJ\x0c\x0eP\x8d\x8c\xe4X\x0e4k?\xaf\x94\x80=\x0f\x03\xc3\xcc\x95\xfc\x0c9@a.d{\x01\x02\x08%\x04@\x96?5g\xf8\xffuJ\xda\xff\x7f\xc7\xb7\xfe\x7f\x93e\xf2\xff\x8e\x1e\xc3\xa7ir\x0c\xee@i\x0eR\x1c\x01\xf5\xf9\x87\xfb\xb6R\xff\xff\x95G\xfe\x7f\x1d\xa0\xf7\xff\xa4 \xc3\xffE\xbc\x0ce@i\x1e\x98#\x00\x02\x88\t\xdd\xe7\x02\xb1i\x0c\x9c\xc6\xfe\x0c\x0c\x7f\xff0\x08\x85U0\xf0\x99\x1b\xf2:\xf30\xac\x9e"\xc3`OlH\xc0|.\xa2&\xc5/o\x05\xd4\xf6\xeb\x17\x83\xb0\x8c\x02\x83\x92\xb9\x06\x83*#C\xe7Bn\x86,XH\x00\x04\x10\x13.\xcb\x19\xfe\xfc\x06\xd3"!E\x0c\xfcf\xfa\xbcN@GL\x92"\xec\x08l\x963\xfc\xfe\rq\x84\xa44\x83\xb2\xa1\x12\x83*\x13C\xe7\x02.\x88#\x00\x02\x08\xec\x00\xa0i\xfd\xac\xaa\n\x18\x96\x83\xe9?\x7f\x18\xc4\x02\xb3\x19\x04\x8dux\x9d\xb8\x19VO\x90\xc0\xed\x08|\x96\xc3h\x1111\x06>!N\x06EF\x86Z\xa0\x16\x11\x80\x00\x02;\xe0\xf67\x06\xcf/\xd7\x1e|~\xb7\xb8\x1e\xc3r\x18_\xdc?\x95A\xd0P\x83\xd7\x89\x93au\x9f\x18\xa6#\x88\xb1\x9c\xe1\xd7o\x86;\x97\xaf3\xbcy\xf3\xfd\xeb\xac\x9f\x0c\xa5\xa0\x10\x00\x08 \xb0\x03\x1c/3\x9c\xdd\xf3\x81!\xe4\xc3\x913\x9f\xdf,m\xc5\xb0\x1cL\x03\r\x91\xf4\x8eg\x104P\xe3u\xe2`X\xdd+\x82p\x04)\x96?{\xfc\xf1\xeb\x8c\x9f\x0ceK\xff0\x9c\x07\xea\xfd\x08\x10@\x8c\xa0\\\xc0\x08\x04 \xc3\x80\xa9\xdd\x1e\x94\xe0@q\x0e\nvd\xcb!\x8e\x82\xe0\'\x9b\x972\xbc\xb9p\xef\xf3\xbe\xaf\x0c\xa1\xea\xcc\x0c\x1f$\x98\x19v\x92b\xf9\x8a?\x0cg\x81\xf6=\x05\xe27\x00\x01\x04s\x004)0\xb0\x83R;(\xc1\x81\xe2\x1c\x14\xec\xe8\x96\x83\xf9@\xfcx\xc7Z\x86W\x17\x1f|\x06j\xff/\xaa&\xc5G\x8e\xe5@\xfc\x13 \x80\x90\x1d\x00w\x04(\xb5\x83\x12\x1c(\xceA\xc1\x8en9\xc3\xef_\x90\x908\xb8\x0b\x18J\xff\x19d\x8c-\xc8\xb2\x1c\x88\xff\x03\x04\x10\xba\x03\xe0\x8e\x00\xa5vP\x82\x03\xc5\xb9\xb4G8\x86\xe5\x08\xfeo\xb2-\x07Y\x06\x10@\xd8\x1c\x00w\x04(\xb5\x83\x12\x9c\x90\x9e\x12\xaf\x8cs \xd5-\x07\x01\x80\x00\xc2\xe5\x00\xb8#@\xa9\xdd\x11\xe8\x08am\x05^Y{\x0f\xaaZ\x0e\x02\x00\x01\x84\xcf\x01pG\xf4\x082\xd8\xdb\xb33\xac\x16\xd5\x94\xe5\x95\xb3v\xa4\x9a\xe5 \x00\x10@L\x84jk\x90FPV\x03\xa5\xf6\xff\x7f\xfe\xe2\xb5\x1c\x122\xff\x18\xfe\xff\x03\x17\x10 \x0b_\x03\xf1[\\\x96\x83\x00@\x00\x11\n\x01\xa2K8\x08\x1b\xc2\xbf}\xeb\x11\xc3\xb3W\xdf\xbe\xec\xfe\xc3\x10\xd9\xf6\x87a/\xd0\x98\x1f\xb8\x1c\x00\x10@L\xa4\xd6j\x84,g\xf8\xf9\x9bAUB\x98A\x92\x9f\x9d\xc7\x95\x89aY\x13\x0b\x83\x1d\xbe\n\x0c \x80\x98\xa8m9\xc3O\x10\xfd\x87AM\x88\x97A\x92\x9b\x85\xd7\x86\x81au#3\xee\n\x0c \x80\x98(\xb1\x1c\x94\xe0\xee\\\xbe\x85a9\xd8A?~3\xa8q\xb23H\xb22\x82\x1d\xd1\xc0\x84\xdd\x11\x00\x01\x84\x91\x06H\xadX@\tNJ\x94\x8b\x1b\x14\xec\xc8\x96\x83\xd9 \xfa\xfb\x1f\x86\x9b\xbf\xfe1<\xfd\xc7\xf0\xf9\x08\x03Ch\xc3\x7f\x86\x83\xc8\x89\x12 \x80P\x1c@N\xad\x06J\xed\t,\x0c\x13@q\x0e\nvt\xcb\x19\x80\x963\x003\xcfMFp~\xfc|\xe4?\xd0\x11\x0c\x08G\x00\x04\x10\xdc\x01\xe4X\x0e\xcd\xe7\xaf\xabX\x18\xb4@\t\x0e\x14\xe7\xa0`G\xb7\x1c\x06n2@\x1d\xc1\x80p\x04@\x00\x81\x1dpJ\x82\x91\\\xcb\x9fB\xf39\x03(\xb5\x83\xe2\x1a\x14\xe7\xea\xa0hF\xb3\x1c\x97#\x00\x02\x08\xec\x80\xb3\x12\x8c\xefy\xa4\x04\x04\xd4\xdc<\xc9-\xe1@\x80\x1d\x94\xdaA\x8e\x90b`\xe0U\xff\x8b;{_\x00\xe2w@G\xb800h\x02\x04\x108\x17|\xfc\xc7P\xf1\xf9\xc9\x07\x86\xb77\xaf\x92[\xbc\x82K\xcc\xfa\xbf\x0c\x07\x0f\x03\xe3\x18\x94\xe0n\xe2(\xdb^\x00\xf1\x07 >\x0e\xec\'\x00)~\x80\x00\x02;\xc0\xf95\xc3\xc2;\xbf\x18J\xef\x1d\xbc\xc4\xf0\xf6\xce-r\xcbv\xb0#\x1a\xfe1\x1c\x04\x05/(\x98ob\xb1\xfc\x06\x10\x1f\x026\x82\x81-\xd2\x8d@\xe67\x80\x00\x82uL@\x0e\xe1\x01u\x1a\x8e\xf31\xfc\x7fe\xaf\xf4\xff_\xa8\xc5\xff[\x1a\xfc\xff\x0fp3|\x89`\x017\xa1\xcd\x81X\x86\x88\x0e\nH\x8e\x03\x18\xbf\xee{\x18\x18>]g\x00W\r\xff\x9f\x01\xf1> \x06\x8a\xf7\x01\xe5\x811\xc5\xa0\x0c\xb2\x13 \x80\x90{F`G\x00;\re\xc7x\x19\xfe_\x91\xe7$\xc7r\xac\x8e8\x87\xcbr\xa0\x9d\x00\x01\x84\xde9\x05;\x02\xd8i(;\xc8\xcd\xf09\x9a\x85!\x83\x0c\xcb\xb1:\xa2\x99\x81\xa1\x1b\xc3r \x00\x08 l\xb5!\x13\xb4\xdb$\x02\xa5?\x12\xaaR\t8\x02T\xfc\n\x83\x12\x1c8\xce!\xe9\x07D\xff\x03)\x00\x080\x00\x05\x83\'E\xc2mN\xf3\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x05D\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04gAMA\x00\x00\xaf\xc87\x05\x8a\xe9\x00\x00\x00\x19tEXtSoftware\x00Adobe ImageReadyq\xc9e<\x00\x00\x04\xd6IDATx\xdab\xfc\xff\xff?\xc3@\x02\x80\x00bb\x18`\x00\x10@\x03\xee\x00\x80\x00bA\x17X\xb7\xfe\xc8\xff\xdf\xbf\xff0\xfc\xfe\xf5\x97\x81\x91\x91\x81\xe1\xcf\x9f\xbf@\x0c\xe4\xffF\xd0\xa8\xec?`5\x08\x1aU\x0c\xc4\x7f\xf5\xe6#\xc3\xfbw\x9f\x19.\x9c\x9f\xc9\x88n\x1f@\x00\xa18`\xfd\xfa\xa3\xffm\xed\xf5\x81\x9a\xff1\xfc\xfd\xf7\x8fAFB\x10,~\xf9\xe6\x13\x14M\xba\xea2$\xf9r\xfb\xc1\xcb\x0c\x7f~\xfdfpr.\xf9\xbfoo\x0f\x8a#\x00\x02\x08\xc5\x01\xbf\x81\xbe\xfa\xf1\xf37\xc3\xd7o?\x19\xfe\xfcE8\xc0\xd4\xbf\x91ART\x80\x81\x83\x83\x95\x81\x83\x9d\x95\xe1\xfc\x96F\x92\x1cp\xe7\xe1+\x86\xbf\x7f\xff28\xb9\x9a0HJ\x86\xfe\x7f\xfe|5\xdc\x11\x00\x01\x84\xea\x00`p\xfd\x05Z\xfc\xfb\x0f\x84\x86\x01n.v\x06#\x1dy\x06A>.\x06\x01~.\x92\xe3\xf9\x0f\xd4\xbc_\xbf~1\xb0\xb0\xa0&;\x80\x00bAW\x08\xf29\x18\x03\xd90\xc0\xc6\xca\xc2 )&\xc0 \x00r\x00\x1fy\x0e\x00\x99\xf9\xe1\xc3\'\x86\x7f\xff\xfe\xa1\xc8\x01\x04\x10Z\x08\xfc\x01\xc7=8$\x90\x14J\x88\xf2\x03\x1d\xc0\x0fu\x007\xc9\x0e\x00\x85\xe8\xa7\x8f\x9f\x19\xbe\x7f\xfb\x01t\x00j\xb9\x03\x10@\x18!\xf0\xf7\x0f(\x04P\xa3 \xd0\xcd\x98A_S\x8e\x81\x07\x18\x15<\xdc\x1c$;\x00\xe4\xf3o\x9f\xbf2\xfc\x04&D\xf4\x82\x0f \x800\x12!\xc8rX\x90\xc1@]\x9e\x1fYy\x1c\x14\xdc\xaf^}`\xf8\xf2\xe9\x0b\xd8\xec\xdf@\x07\xa0G\x01@\x00\xa1\x86\x008\x11\xfe\x07*\xfe\x07\x0e\x81\xdb\x0f^\x82\x83\xec\x1f\xd0\xd5\xff\xa14\xc8\x00\x90\' \xe2\xff\xc0>\xfa\x07\x97\xfb\x0f\xe7\xff\xfe\xfd\x9b\xe1\xcd\xeb\x0f\x0c_\xbf\xfe\x00&\xbe?\xe0r\xe3\x17\x96\x10\x00\x08 \xcc\\\xf0\x0f\x92\x00A\xf4\xf5;\xcfQ\xf8\x7f\xa1\t\x14\x99\x86\xb0!\x0e\x07\xd1\xa0t\xf4\xf9\xd3W\x86\xaf_\xbe"\n0P\x81\x04r\xc0\xef\xdf\x18i\x00 \x800\xa3\x00\x1c\xfc\x7f\xe1\x85\x11.\x8b\xfe\xa29\x04\x14\xbf_\xbf|c\xf8\xf6\xf5\x1b\xb4$\x84\x94\xa6\x103\xa1\xfc\xdf\x98!\x00\x10@\x98Q\x00\xca\x05\xe0(\xf8\x8b\xd5\xc7\x7f\x90\x1c\xf3\xf3\xe7/0\x06\xa5\xee\x9f\xc0\x02\x0cn1\x88\xfe\x8d\xb0\x1c\xe6\xb1\xdf\xc0\xa8@w\x00@\x00\xb1\xa0g\x17X\x19\x00\xb2DX\x90\x07\x1c\xe7\x7f\xff\xfd\x87\xd3\xbf\x80\x16\xfd\xf8\x01\xb4\xf4\xfb\x0f\x06VFV\x06vfF\x06.Vf\x88%\xbf\xff"\xd5\x0bPK\x81\xf4\x83\'\xaf\xc0\xd1\xf0\x0bK\x08\x00\x04\x10f9\x00\xf5\x1d(\n\\\xac\xb5\xe0r \xf1o\xc0"\x1a\xe4cH\x05\x05Q\x03q\xec_$\xb1\xbf\x18\xf2=\xb3\xd6C\x1d\x86\x99\x0b\x00\x02\x88\x05[\x91\x89^\x10\x81\x82\xf7\x1b0\x98\x91\r\x85\xe1\xbf\x7f\xffB\x8b\xf0\xbfX\xe5\x91kJP(\xa0\x87\x00@\x00a\xe4\x82?H\xf1\x0cR\x0c\xc9F\xbf\xb1\x1a\x8c\xea\x10\xdc\xf2`\x07\xfc\x85D\x0b\xba\x03\x00\x02\x08{\x14@5~\xf9\xf2\x9d\xe1\xf4\xe9\xc7\x90\x1c\xf1\xf7/\x8c\r\xc2\xbc\xbc\xec@\xfeox\xcb\n\xdd\x01\x00\x01\x84\x11\x02\xa0`\xfa\xf2\xe5\x1b\xbc9\xf5\xe1\xc3w\x94`E\x0ej\xe4\xa8A\x15G\xb098\x98\xa1\xb5,v\x07\x00\x04\x10F"\x04\x17*\xc0\x86\x03(\xd8@e\xb8\xac,\x1f\xd6\xac\x85\x9e\x13p%JH\xc2\xfe\xc3\xf0\x0f\xe4P,\x0e\x00\x08 T\x07\xfc\x02\x152?\x81\x85\xcd\x1fxar\xf1\xe2s\xb0\x05\xff\xfe!\x07\xed?\xb4PA\x84\x04\xb8\xc0B\x12\x93\x96\xe6\x07\'@P\x1a\x00a\x06\x06T\x07\x00\x04\x10\x8a\x03@\xe5\xf9o\xb0\xcf\x7fC*\x10 \x96\x96\xe6\xc5\xc8\xe3\xc8>FNp\xc8\xc1\x8f(#\xfe\x80\xd3\x00\xac\x80C\x0f\x01\x80\x00\xc2\xc8\x86\xe0"\x13\x9c\xef!i\x80\x8d\x8d\t\xc8\xfe\x0fl\xa2\xc30#\x103A}\x02\x11c``\x04c\x90\x1c\x8c\xfd\xff?\x04C\xa2\x00\x182\x7f`Q\xc0\x8c\xe2\x00\x80\x00Bq\xc0\xaf\xef\xbf\x18\xbe\xbc}\xcf\xf0\xe9\xf9+pb\xbc{\xf7\x0eF\x1e\xff\xf3\xe7\x1f\x96\xc4\xf6\x0fky\x00\x8b\x86\xaf\xaf^\x80\xab\xe1??\x7f\x02\x1d\x80\xda\xa6\x04\x08 F\xf4 10H\xfd\xff\xf1\xe3\x17p\x02\x14\x10\xe0\x827\xcd@\xea \x98\x01\x1e\x8c\xa8|\x04\x1b]\xec\xe5\xcb7P\xf5\xa0\xe2\xfe\x00J\xbf\x00 \x80\x18\x07\xbas\n\x10@\x03\xde7\x04\x08\xa0\x01w\x00@\x80\x01\x00\x80p\xef\x0c\xb7\x02\x84R\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x07{\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\x19tEXtSoftware\x00www.inkscape.org\x9b\xee<\x1a\x00\x00\x07\rIDATX\x85\xc5\x97Il\x1ce\x16\xc7\x7f\xef\xab\xea\xcdn\xdb\xe9\xb6\xe3q\x1c\xdb11m\x07\x05\xc5\tK4\xc9D\x80f\xc4\xa2DB9p\xe4\x80\x10 \x84\x10R\x0e\x13\x0e a\tD\x16\x89\x1c\xb8\xc0\x81+B\x82\x03\x17\x92\x81d2\x08ec\x11\x0e&\x13[J<\xce\x82\xdbY\xecv\xa7\xbb\xdd]\xd5\xdd\xb5\xcc\xa1\xaa\xab\x17[s\x8b\xe6\x93J_-\xaf\xde\xff_\xff\xf7\xbe\xf7\xbd\x12\xd7u9(\xb2\x17\x98\x00\xc6\x810\xf7wT\x80)`\xe2\xa8\xeb\x9e\x90\xbf\xc3\xde\xaeX\xec\xf8\xdf\x1ez\x88\x1dCCDt\xfd\xbe\xa2\x97-\x8b\x8b7orzf\x86\x9ca\xec\xd3\x81\x89\xbfn\xd9\xc2\xf8\xc6\x8d\\\x99\x9fg>\x93\xa1jYk\xbe,"h"(\xa5\xd0\xfcC)\x85&\x12\x9c+\xa5P\xbeM\xeb\xac+E"\x1e\xe7\xd1\xa1!\\\xd7\xe5\xeb\x8b\x17\'t`||p\x90\xab\xe94\xf9\xe1aR\xaf\xbe\x8a\x16\x89\xac\x85\x8e\x00J\x04DP\xfe=%\x82\xf8\xcf\xa4\xe5\x9c\xc6\xfb\x00\xd5*\xa53g\xc8\xcd\xce2>8\xc8\xd7\x17/\x8e\xeb@8\xaci\xa43\x19R\xaf\xbd\x86\x1e\x8f\xaf\xc6np\x12\xea\xea"\xdc\xddM(\x91@\xeb\xea\xc2\xb2m\xccL\x06)\x14\xd0VVpVV\x02\xb5\xa4u\x0e\x85\x88?\xf1\x04\xf9\xcb\x97Y\xe7\xe1\x84u\x00\xd7u\xa9\xda6\xaemc\xf9\x0eZ\xc1\xe3##$w\xedB\x8f\xc5V\x11\xec\xec\xef\xaf\xc7\xb8X\xe4\xc6\xe9\xd3$\x0b\x05\x10\t\xd4\x0bf\xc7\x01\x11\\\xd7\x05 \x00`\x15\x8b\x88\xa65\xc7<\x16\xa3\xf7\xa9\xa7\xe8\x18\x1d]3/ZG\xa4\xbd\x9d\xd1\xe7\x9f\xe7\xc6\xe4$29I\xbbRup\x11\xc4qP\xad\x04\x1c\xff\xc2.\x16\xc1\' @|x\x98\xfe\xfd\xfb\t5\x84\xc5\xb1m\x96\xe6\xe7\xb937\xc7\xdd\xb99\xda"\x11\x12CCt\x0f\x0f\xd3=0\x80\xf2\x017=\xf2\x08\xc5\xcd\x9b\xb9\xf6\xd5W\xf4W*\x01\x01\xd7qPJ\x05\x98\x1e\x01\xc7\x01\xa0\x9a\xcf#\xa1\x10J\x04=\x1e_\x05~\xed\xb7\xdf\xf8\xd7\xa7\x9f\xb2)\x14b}<\xceH,\x86R\n\xb9q\x83\xdc\xf7\xdfs+\x12\xa1o\xff~z\xb7l\x01\xa0}\xdd:\x1ex\xe1\x05\xa6>\xfa\x88-\x89\x84\xa7\x80\xeb\xa2D\x02L\x05`\xfb\x17\xb7N\x9e\xa4\xba\xbc\x8c]*\xd1\xbfo_\x00^5M\xfe\xf1\xf1\xc7\x9c;r\x84?\xb7\xb7\xf3@{;\x1d\x80k\x9a\xb8\x86\x81k\x18D,\x8bd\xa9\x84\xf5\xc5\x17\\\xff\xf2K\xaa\xe5\xb2G"\x91`\xfds\xcf\x91\xcbf\xc14\x11\xd3DD\x02L\xd5\x14\x82\\\x8e\xa5\x1f~\xa0cd\x84u\xdb\xb7\x07_~\xea\x93O\xa8^\xb8\xc0c==\x84,\xcb\x035M"\x03\x03D\x06\x07q\r\xc3s\xee\xcf\x91\xc9I\xf2\xdf|\x13\xbc\x9f\xda\xb3\x87tw7\xf8d\x95H\x80\x19(\xa0\xc0\x93\xb3Ze\xe8\xc5\x17\xeb\xb2\xff\xfa+7O\x9c`$\x16\xf3\x80K%\x1c\xc3 \xf9\xec\xb3\xf4\xbf\xf1\x06}\xaf\xbfNa\xd7.\x8c\\\x0e\xd74\xa1T\x02\xc3\xc0:s\x86\xc2\xccL\xe0\xe7\xd1\x97_\xe6\xf2\xfc\xbc\xa7@\x83\xea\xaa\x96\x03\xb5\x8a\xd6\x91J\x11N&\x83\x84;\xfe\xc1\x07\xec\xe8\xec\xf4\xd8\x97J\x01\x89\xf8\xce\x9d\x81\xf3MO>\xc9\xd5;w\xa0T\xf2H\x18\x06\x18\x06\xe5\xcf?\xc7\xb5m\x00b]]d\xc3a\x9cL\x06Y\x95\x03\xae\x1b\x94\xd3u\xdb\xb6\x05\x8e\xef^\xb9Bxf\x86h\x0b8\xa6\x894T\xcbp,F\xaeP\x80\x1a\xb8i\x82i\xe2\xcc\xcfSM\xa7\x03\xbb\xe8\x86\rT\xd3i\x94\x08vc\x08\x1c\xc7\tjyW\x03\x81\xf4\xd4\x14]\x8eC5\x9d\xc6ZZ\xf2\xe4\xad\x814\x0e\xd7\x85J\x05\xcae\xa4\\\x0e\x08\x88i\xe2\xcc\xcd\x05f\xbd\xa9\x14\xf7,k\r\x05j!P\x8a\x8e\x87\x1f\x0e^X\xf8\xfdw\x92\xa1\x90\xb7\xb6\r\x03{y\x19\xf7\xde=\xdcb\xd1\x03m\x1c\x95J\xf0\xf5R*A>\x8f\x9b\xcdb]\xba\x14\x98\xfci\xebV2\xd5*J\xa9 \x07t\x00\xdb\xb6\xd1\x94BjU\xcb\x1f"B\\\xd7\x83\xddL\x03\xc4\xb6\xbd\xafl\x19R.#\x86Q\xdf\x90\xfc\x8d\xaa\xc5!+\xb6\xed-C?7\x14\x80\xe5\x87@S\ncz:\xb0\xdf8>N\xb1A\x9d\xc6\xed\xb6u(\x1fP5\x80\x8b\x08\xa1\xb1\xb1\xc0f\xf1\xf2e\x12\xe10J\x04\xab)\x04\xb6\x8d\xf8\xab\xa0\xd8@\xa0\x7f\xdb6\n\xb5\xfch\xd9\xdbW)\xb0\x06\xb8\x12AO\xa5\xea\x04\xa6\xa7Y\x1f\x89\xacV\xc0v\x9c\xa0\xd10\x1a\xd6\xee\xfaT\n\xab\xafo\xcd\x06\xa3U\x83F\xd0\xda\xa1\xf5\xf5\xa1\x86\x86\x02\x9b\xcc\xccL\x9d@k\x12\x8a/o\xe5\xfau*\xd9\xac\xf7P\xd3x\xfc\xfd\xf7)\xf8;X#\x89F\xa2w.]"\xa2i\xcd!P\x8a\xb6\x03\x07\x82\xdd\xd5\xc8fQ\xe94\xbaR\xab\x0b\x91e\xdbu\xe7"\xa4\x8f\x1e\r\x9c\x0f\xef\xde\x8d\xb1o_\xd0\xfd\xd4\xecJ\x9f}\xc6\xad\x1f\x7f\xe4\xe6\xf9\xf3\x9c?v\x8c\x91\xb6\xb6&\xf0\xf0\xde\xbd\xe8\xe3\xe3\x81\x9fs\x87\x0e1\x16\x8f{\xca\x89`\xf9!\xd0k\n\xa8Z_\'B\xe9\xf4i\x16O\x9db\xfd\xd3O\x03\xb0\xfb\xed\xb7\xf9\xb7\xae\x938y2 a\xcf\xce"\xef\xbcC\xbeZeO(D[4\xda\x04\x1ey\xe5\x95\x00|\xf6\xdbo)\x9f=\xcbXoo\xd0\xa6\xad\nAk\xa2\xe5\x8e\x1d\xc3\xccd\x00\x08\xc5b\xecx\xf7]\xc2\x87\x0fS\xee\xe9\xa9\xc7Y)\xfa\xa2Q\xdat\xddk^6l\xa0\xfd\xc3\x0f\x89\xbd\xf9&*\x1a\x05\xa0\xb4\xb8\xc8\xcfG\x8e\xf0\x97d\xd2\x03o!\xa0\xd7B\x10\r\x87\x9bb\xec\xe6r\xdc}\xef=z&&h\xeb\xe9\x01\xa0\x7f\xf7n\x9c\x9d;)^\xbbF\xe5\xca\x15\xe4\xeaU"\x9a\x866:\x8aJ\xa5\x08m\xda\xd4\xd4Q\x95\x16\x17\xf9\xe7\xc1\x83l\xd74\xdaC\xa1\x00\xdcm\rAS\x0e4\xcc\xf6\xd4\x14\x0b/\xbdD\xe4\xad\xb7\x18|\xe6\x19O2]\xa7#\x95\x82\x86\xe5\xb5\xd6\xf8\xcfw\xdf1y\xf4(\x8f\xe9:\x03\x1d\x1d\xf5\xce\xd8oJV\x13\x80\xb5{\xf9\x95\x15\xd4\xe1\xc3\xcc\x9e=\xcb\xc6\x03\x07\x88%\x12\xff\x13\xd8\xc8f9w\xe8\x10\xea\xc2\x05\xf6&\x12\x845\xad\x19\xdc\xb7k&\xe08\xb8\xb0\xe6z\xd7\x94BD\xe88\x7f\x9e\xc5s\xe7\xb8\xdd\xdb\x8b\x1a\x1d%66F\xf7\xd6\xad\x80W\xe12\xd3\xd3Tfg\x89.,0\x12\x8b1\xd0\xdd\xdd\x14\xf3\xc6\x7f\x84\xaam\x07\x95P\x07*\xa6e\x85\x8b\xa6I\xb4\xb3sM\xf0Z\xd2\xb5)\xc5\x83\xcb\xcb\xc8O?\xa1~\xf9\x05\xd3q\xc8Y\x16\tMcs8\xec\xad\xf1d\xb2\x0e\xb8\x06\xb8\x88\x90^Z\xc2\xf4\xfe\xbe*:0u\xbbPx\\\xc3\xeb\x84\x93\x9d\x9d(\xd7E\xfc\xd6\xb9&Ym\xefs\xfc\xbf"\xc7u\x89*E\x9b_\xd9\xc4\xbf\'\xae[\x07\xac\x9d\xfb\xfel\xdbf~q\x91\xab\x0b\x0b\xdc.\x14\x00\xa6t`\xe2f>\x7f\xdc\x05\xca\xb6\xcd\x82_\x05\xef\xd7\xb0]\x97\xc5R\x89?\xf2y\x80\t\xf9\x7f\xff\x9e\xff\x17\xc5\xd6=\x9a\xb0\xf3k\xe8\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x07\xa0\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\tpHYs\x00\x00\x0b\x12\x00\x00\x0b\x12\x01\xd2\xdd~\xfc\x00\x00\x00\x07tIME\x07\xd3\x08\x1c\x13\x19\x0c\xfe\x17\x9f\xdd\x00\x00\x07-IDATx\xda\xc5\x97\x7flUg\x19\xc7?\xe7\xdc\xdb\xdb\xde\xb6\xb7@\xa1\x80H\x87e\x8b\xc2\n\xadts\xb0a\x1d\xc3e\x03-nf1\x04\xd0\x88&\x1a\xb3\xd6hb\x98FgL\xa78\x05\x9c[\x06\x99?\xc3\x1f\xca\xfc\xc3,f\x9b\x19\xe2\xc6\xac\x94\xe2\xa0c\xd8\n\xf2c\xfcl{)\xed-\xed\xfd}~\xbc\xbf\xfc\xe3\xdc[\xa8\xa3":\xe5M\xde\x9c\xf7\x9c\x93\xf3>\xdf\xe7\xfb|\x9f\xe7<\xafe\x8c\xe1f\x0e\x9b\x9b<\xc2\x00\x96e\xbd+\x9b=\xbe\xf9\xe5\xba\x10%;\x1d\xdf\xeb\xda\xd2\xfe\xd0w\x01\x1f\xd0\xff\x17\x06\xda\x7f\xb8\xa7\xbd\xa2\xbc\xe2l\xcb\xc7\x1a\xee\xad\xac\xac\xf8\xe6\x9aG\x1e[\tD\x01\xeb\xba\x0c\xfcW\x86\xb7\xfca\tX;\xeb\xe6\xcdh\xfc\xc4\xaa\xc5\x94F\xc2\x94FB$F\x92O\x03+\x0b,\x88I7\xf8OE\xf8\xe4\x8f\xf7N\xdd\xfc\xa3W\xdb\xb7m\xef0g\xce\x8d\x19!\x8c\xb9|\xd93\xc3\xc3yc\x8c1\xcf\xed.\x10\xad\xa9\xe2\xec\x85\x04\xb7\xdd^\x83g\xc0\x17\xe0\nH\xa6!\x9e0\x8ce4\xfd\x83\x1e\xc9\xb4&\x95Qd\xb2\x127\xef#\\\x0f\x99\xc91\x1a\x1fet,\x8frD\nW$\x08\x990\xb6)%u\xb0\x1b\xc8\x17D\x08\xb2\xc0\xc0\xdb}\x92\xc1D\x9e\x96e\xd5x\x1at\x04\xa8\x9a\xc2\xb1\xb3\x19\xaag\xc58\x1d\x87\xfe!M2\xadH\xa6\x15\xa9\x8c"\x99Q\xa4R\x92\xd1\xb4"\x97\xf5\x90\x8e\x8f\xcc\xe5\x19\x19\xbc\x8c\x92\x1ae\x97\x81\xf0\x83\nXJ\x052\x7f\x9a\xd1\x8e> o\x8f3P\x00\xb0\xbb3N\xcb\xd2\x1a\xca# \x0cx\x80(\x8fpj\x18\xbaO\x18\x86\xc7\xc0\x13\x06_\x04Z\x10\xca \x04\xf82X\x1b\x03\xe9\xb4\xc3\xa5D\x16\x1d\x89bUT\xe2|\xf13\xe3\xe1\x9dS\xa3+\xf1/\xf7\x10l\xed\xda\xc5,(\xd6\x81}\x87\x87X\xb3t&\x1e\x90\xf1\xa1o\x14\xe2I\xd0\x91\x18C\x89\x1c\xbe\x08\x0cJ\x05\xbe\x04!\x021Jm\x91w\x14\xf1x\x9a\xacg\x08W\xc6\xb0\xc2a\x92k\x1f\xa1\xac\xb5\x06\xe7\xb1\xd6j\x80\x8bi\x15%\xd9\xf5\n\x90\xbfJ\x84\x06\xa9\xa1\xef\x82$\x9f\xf3\xf9\xf8\xdd\xd3\x19\xc8\xc2@\x16r~\xf0\xd316H+\xc4h\xca\xc5\xb2#\xf8\xd2 \xa5\t2@\xc1`"\xc7P\xc2\xc3\x8a\x96\x93\xbc\xff#\x00L\xfb\xed\xef\n~\xdf\t\xec\x86RS\xe1|i\x13\xc0/\xa3m\xcc\x1d\x07\xa0\nu\xe07\xbb\xcf\xf3\xf0\xb2\x99$<\xc8z\x10\xb5\x82\x14\xb2m\x08\x85\xc0T\x95\x12\x1f\xc8\x10-\x0f\x11A\x12\xb1\x14\x11#\xc8\x8df\x88\x86`\xf6\x8c2\x8e\xdfq\x0fe\xad\n\xb77\xc4\x18\x9f\x84f\x80&h\xde\x8d\xc3W\xe7\xd0\x0ce\r\n\x87\xda\x81h[\xbf\x1d0P\xc8\xe7\x8e\xeeA\x9e\xdf\xd4\xc8\xc2\x18\x10\xbb\x92\x96J\x81\x10\n)\x15ra\tBx\xc1ZJ\xa4\xd4\x08\x11)\xac%\xc7\xc4\x9f\xa8\xdfq\x1fe\xad+\xa0\xa1\x11\xb8\x1d\x98IY\xc3O\xa1\xe1\xef@\x0f\xee\x8e\x0e\xa2m\xfd1\x02b\x03\r\xbcv(M\x08\xc3\xaa\xa6\xaawv\xae6\x84B\x16\xb6]\x9c6\xb6mcY6\xb6m\xfd\xd3;\x8b\xbf\xdd\xf5:\xee\x8e\x0e\xdc\xdeg\x80\x99\xc0\x1d\xc0L\xdc\xdeg\x8a\xc6\xe7\x17\x9b\x93\x02\x00C\xe7\x9b\x83|\xfe\x81k\xd7\xfd \x0cE\xc3\xa1q\x83\xa1\x90\x8de\x15\r\x87\xb0m\x9bP(\x00u\x9d\x91/\x02\x18\xaf\x84Gz/\xf1\xb3/\xdc3\xe9\x17\x96\x15x\xaa\xf5;\x99\xd0\xda\x10\n\x99\xf1w\xf5o\x14B@#0\x0c\x1c\x06\x86)k\xf8\n4\xf4\xe0\xd0q)\xda\xd6o\x8d\x038}\xf62\xb7\xde\x12c\xc1\x9c\x92\xc9\x0f\x10v\xa1dk\x81\xe7\xfb\xb8\xae\x87\xe7\xb9\xb8\xae\x87\xeb\xfa8\xae\x8b\xeby4\x1f_W\x10a\x07tv\x10\x88\xee[\xb8\xbd\x9b\xa1\x93\xe0\xbeU\xe1Pk\xa2m\xfdV\xb8\xc8\xf1XZ\xf0\xd1\xaf\x1f\x06\x13\xa4e\xd0\x1d\x07\xed\x9a.\xfc\xf9\xb4Vh\xa9\x91J\xa1\x95F+\x85,\\\xfb\x13\x1e\x99\x84\x00\xbd\x15\x87M\x00D\x9f\xfd\x01\x0e\xdf\x80\x86\xb7\xa0\x13\xa2m\xfd\xcd\xce\xf6\xdaN\xb73D\x91\x01\xcb\x18\x83eYU@-0\xe5\xdd>\xfb9\xdbk\xbb\xcaZkpw$\x88\xb6\xf5\xd7\x03q\x82\x1e\xd8\\\r\xa0\xa4p\x8c*\xf9_\x1c@\x9d\xed\xb5#\xd1\xb6\xfe\xe9\x05\xe1M\xe8\t\xad\x9b}<\xff\x07\x19\xbf\x1f\xed\x82\xbbD\xa7\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x06\x96\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04gAMA\x00\x00\xaf\xc87\x05\x8a\xe9\x00\x00\x06MIDATx\x9c\xc5\x97\xcb\x8f\x1dG\x15\xc6\x7f\xa7\xbbo\xdf\xbe\x8f\xf1\xdc;\xef\x19\x13O\x1ef\x14a\x8c1D\x02\x19\x10\x08\t\t\x161\xb0d\x91\x90%b\xc3\x82\r\xfc\x15\xd9\xb0\x8b\x88@\x08\xd8\x07\xd8!!$X\xb0\x08\x8bH\x16\x1eB&\xd2\x8d\xc7\x9e\x19\x8f\xedd\xe6\xbe\xa6\xbb\xea\x1c\x16\xd5\xf7\xe5y\xf0\x10\x12uU\xb7\xaa\xab\xaa\xab\xbes\xcew\xce\xa9\x86\xffs\x11\x16on\\z\xe6\xdb\xbf\xcc*\xdc\xc4\x0c\x1b\xcd\x18\x93~90\xf3\xac\xb3\xf3\x06`\xb3o\x00\xe4\xc3\'w{;\xbfz\x85\xfc\xf0\xdd\xb3\x00$\x91\xd5^\xfb\xee7?\xff\x95\xaf\xbe\xf41\xba\xfd\x1c\xe7<\xb97\x9cW\x9c\x0b5w\x8a\xf3\x86/\xc7\n\xa7\x14S\xf3\x85\xd3\xb0\xde[\xb9VQ\xaf\x14\xce\xf3\xf7\xce\x83\xcf\xbd\xf7\xe8\xc5\x1f\xfa\x87\x7f\xfa\xde\x99\x00\xe2(\x9e\xbf\xbc2O-K\xf1\xde(\xe2\x88\xc8[8X\x94H\x14\x13E\xf0\x08\x02&\xa8\t\xaa\x82\x17A\x04\xa4\xd4\x80\x99\xa2*\xa8\x82\xf7\xe0\xbc\x80A$\xc93\x1eb\xc0\x9f\x02@$\xdane,\xb6+T3C\xbd\xe2\x15\xbc*\xde\x1b\xaa\x16\xa4WE\x15\xb4\x1c\xf7\x1a\xaa\xa9\x85\xf5f\xa8\xb7\xd0j\xa8I\x12\xf3\xf6\x1d\xe1\xfdwT\t8Ok\x00`e%\xe3\xb9\xcd\x06\xd5li$M+\xac\xad\xad\x03\xd0\xedv\xe9\xf5\xfa4\x1aM\xd2\xb4\n\x10\xc0\x10\xc0\xe4\x85\x83\xb2\x7f.\x00\x00;\x83\xc1O\x97\xe3\xe3.\x9dN\x87,\xcbXYY\xc5\xcc\xd8\xd9\xd9\xe1\xf8\xb8G\x92$\xbc\xf0\xc2\xc7\x99\x9bk\xe2\xbd\x0f\xfbY0\x19\xe6<\xe0.\x04pV13\x1e?~L\x14E\xb4Z-\x00*\x95\nI\x12^\xebt>\xa0\xd7\xeb#",--\xd3l6\xf0^1\x03\xd5\xf0\xbe\xa9\xc7\xa2\xfa\x12\xcd\xeb_\xca.\x7f\xc3c\xb1\x00\x0cw\x7f\xf7.\xbdw\x0e.\x04\xe0\x9c\xa3\xd3\xe9\xe0\x9c\xa3V\xab\x11E\xd1\xd8\xe6\x0f\x1e\xec\xb1\xbf\x7f\x80\x99\xd1j\xb5\xd9\xd8\xb8\\\x1el\xe1`3L\xa1\xc8\xfb\xac^y\xe9\xd6\xda\xc6\xd5?\xa8w\xa8z\xf2\xc2\xc9\x9e|\xe1\x1fG\xdb\xef\xbf|!\x80J\xa5\xc2\xea\xea*\x9dN\x87\xb9\xb99\xe28\xa6\xdb\xedR\x14\x05\xf7\xef\xdf\xc7Li4\xe6\xb8r\xe5YD\x04\xe7\xfc\x18\x80\xaab\xa68\xe7XY\x98\x97\xcf|\xe2\xd9x8\xccq^\xe9\x0fO\x18\x0e{[G\xb5\xf6\xd7\xa2\x8b\x00\xa8*y\x9e\xd3n\xb7\xd9\xdc\xdc$MST5\xb8\xa6\xf3\x80\x91e\x19"B\x9e\xe7\x13\xc9\xcd\x826\x0c,\xfca\xa6\x94\xd1\x02\x11\x88D\xc1\xfb\xf4\\\r\x1c\x1e\x1er\xef\xde=\xf2<\xe7\xea\xd5\xab\x00\xe4y1\xf6\xefz\xbd\xc1\xd1\xd1G<~\xfc\x08\xe7<\xfd~\x9f\xf5\xf5\xcb\xcc\xcd]\n }0\xc1\xf0\xa4\xe0\xfaV\x9b\x1f\xbc\xf2)\x86\'\x05\x06\xcc\xcf\xd7y\xfd\x8d\x13\xde\xf8sa\t\x8c|~\xd6\xf3\x07\x83\x01\xfd~\x9f$I\x10\ts#\xe9D\x84\xb5\xb5uz\xbd\x1ey^\xd0\xebu\x89\xe3\x04\xe7\xdcD\x03\xe5\xaf(\x1c\xab\xcb\rn\\\xdf\xc0\x15\x0eU#\xadVXY\xac\x01\x8e(\x1c-D2\x0b`}}\x9dk\xd7\xae\xd1l69::.\x01\x04\x92y\xef\xa8\xd5\xea\xe3X0\x18\x0c\x10\x11\x1a\x8d\xb9\xd2D\xa0\xa5\x19\xac\x8c\x8c@\xc8!.\xc4\x84\xa2\x08Q9\x00\x88\x848\x9e\x05\x90$\t\xf3\xf3\xf3\xb4\xdbm\xf6\xf7\xf7y\xf2\xe4#D\xa4t\xc3\x94~\xbf\xcf`0\xa4Vk\x90$I\xc9\x8bbBB_\xda\x1f\xc0\xb4\xe4T\xa8a(\x00H\x00\xa2H\x88\xa2\xd3|\x1c\x0eO\xd8\xdf?\xa0(\x1c\xdb\xdb\xdbT\xabUZ\xad\x05T\x95\x9d\x9d\xf7\x18\x0c\x86dY\xc6\xea\xea\x06\x0b\x0bKc\x82\x8eA`@I\xc0\xa7\xb4\x11H\xe9\x03\x00\x91\xd3\x00F\x8bE"\x96\x96\x96XXX\xe4\xf0\xf0\x90\x87\x0f\x0f\x88\xe3\x98\xf5\xf5\xcb\xa8*{{{\xc4qRJh3\x00\xcc\xcaLi:\x13#\xc2\xda)\r\x04\x00\x13\x13\x8c6I\xd3\x94\xad\xad- \x04\xa08\xaeppp@\xa3\xd1dqq\x19U\xe5\xd2\xa5\x16"\x11E\xe1\xcbtl\x13I5\xb8\x9dY\xc8\x98\x01\xc8T\x88\x9e\x98 \x1ak`\xda\x97\x83\x06b\xcc\x02\x9b\x93$faq\x89ZV\xc7{EU\x11\x89\xcb\xa0c\xc1\xef\xcd\xc6\xb66\xa650\x19G\xc1\xac\xd4\x80*I\xa5\x92 \xa5\x1aE\x02!\xe3\xf8\x14%\x80\x94\xeb\x9f|\xb1\x8c\':V\xf3\xb8\x06\t0\x043\xa3\x9a%`FQ\x14c\x8f\x18q#\x10TI\xfc\xf0\xd1\xdd\x9f\xfc\xfc\x8f\xdc\xd9~\x9en\xf7u&\xa9Y\x81\xea\xdab\xe3\xc6\xab\xdf\xba\xb9\xbc\xbc\xd2\xa4\x0c\x17\xffV1\x9dJ\xc5\x06\xceyz\xfd\x93\tOF\xb1\xa1\x14i:\x17L_\x18\n\x03\x86\xb9c8\xc8\xc9j\xd9\xe4\x00c\xca\xd5&\x9bN\xb3\x7fD\xb8\xd3s:\x1e\xa7\x8c\x11\xe7%\xa3\xc8\x80H\x04\x99\x8a\x0fV\xba\xcf\xc4KFc\xd3\xed\xec\xe1\xb3^Ujf\xb4\x19\xff\xe2F$\xe5\xe5cV\xf2)\xd6\xdb\xd9\x92O\x1f|\x96v\xc2\xd9\x17k\x80H\xe2(\xab&\xa4I\xf0\xc7p\x03\x0e\x01+\xdcv\x0c\x8d\x98\xf4\xa7\xee\x01\x93\xe7\x12L\xf9<\x02\x90\xa6\xf1(\xf7\xc8y\x00\xf4\xc3\x0f\x8f\xfd\xee\xc1\x804M\xf0NK\xdf\x9d\nT3\x87N\xf5U1\xb5\xd9\x0f\xb9\xa9O>\x01\xee\xed\x0e\xb9\xbf\xf7\x04@\xcf\x03\xe0v\xb7\x7f\xf3\xd3\xdb\xaf\xb1\xb9\xd0\xaa\xd7\xbd\xd3\xf1\x16#\xd5\x87o\xc7Q\x0b\x98G\xd5\xc186\x84j6\xe9\x87\xaax\xef\xe5\x83\xce\xdd\x0e\x0c\xde>\xf3k\xa5,1\xf0Y\xa0\xcdE\x17\xfb\xff\xae\x08\xb0\x0f\xdc\xf9\x1f\xef\xfb\x9f\x97\x7f\x02\x9b\xb3@_LT\xf2u\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x06,\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\tpHYs\x00\x00\x0b\r\x00\x00\x0b\r\x01\xed\x07\xc0,\x00\x00\x00\x07tIME\x07\xd3\n\t\x13"6\x19\xae]\x9a\x00\x00\x05\xb9IDATx\xda\xc5\x97[\x8c\x13U\x18\xc7\x7fs\xa63mw\x97\xee\x85U`W\x04\x14\t\x88\x98eG\x8d\x11Q1\xf1\x12c\xe2%\xea\x93w\xad\xca\x83>)/&&\xfa\xea\x83\x89\xbe\xa8\x8d(\xea\x8b\x9ax{0FA\x8c(jB\x0b\xbb\xc4K\x90\x1a\x16]\xba\xb0\x97v\x97\xb63\xed\xcc\x9c\xe3C\xa7\xdb\x96m\xddKL\x9c\xe4\x9f^\xbes\xe6\xfb\x7f\xff\x99\xefr\xe0\x7f\xbe\xb4\xc5,\x1e\xdc9\xb4\x0e\xd4\x0e\x90\x03\xc0\x00J\xd6\xddC\r\xa3\xe40\xd2\xddo\xb1\'\r\xc8D"\xa1\xfe\x13\x02\x83;\x87\x1e\x01\x1e\x06\xae\x03\x05H\x10&\x88He\x81t\xc0w\xea\xb7\x1cDz\xef[\xea\xad\xdd\x80\x9bH$\xe4\x92\x08\x0c\xee\x1c\xda\x8a&^A\xc9\xeb\x11:\x98]`\xf6`\x86\xa3\xac\x8e\xcdp\xe5\x05Y\x00\xf2\x0e\xec;\xb1\x06\xdb)Ci\x1c\x9cIP.\xa0l|\xe7Y\x8bw\xdf\x01\x9cfD\xb4y\xa2\xde\r@t%f\xc7\xf9\xf1\xeb_\x01\t\xce\xd5\xf4m\xf0!\xb6\x85G\xb7O\x12kk\xa3X\xaae\xd2\x97\x87\xb2\xdczE\xf7\xa2s\xfd\xc1\x1d1N\x9f58\xfeg\x1e\xcc\xae\x17\x91\x1c\x06\\\xc0\xd5k\xd1\xa7\x1e\x01\xf5$\xd1>\x1e\xb8*\xcb\xa65\x1d\xb8\xbej\xc0}\xd7\xf7\xf2\xee\xde3\xf4-7\xe7\xd8\\_\xb1\xef\xc84\xc7O9\x1c?\xe54\xacQ\xc0\xda^\xc9w\xe9.pgVe\xe4\xa6\\\x9f6|\xd8\xb2\xacrM\x01%\x1fF3X\xd1\xbb\x8c\x8dk\x1c\nN\xf3\xd4}\xee\xde~^\xfeh\x14\xeb\x92\x8e\xa6\xb6\xea\xf5\xcd\x91\xe9\x06[\xac\xdd\xe0\xae\x81\t>9h\x80\x1e\xb9\x1b\xc9{\x80-\x00\x06\x9f:\xb4\x0e\xb8\x8e\xc8rn\\?\x89\xe7C\xb1\xe4\xcfA\xbd\xa3\xe4\x1f\xf9\x96vh\xdc?]\xf0\xf83SD\xa1Cd9h\xfa@\xb2t\xdb& RU`\x07\x00f\x0f\xbd\xb1\x19\n\xb6\x9c\xf7\xb9V\x95\xb8\xf0\xbcpS{\xc1\x96\x8cM9\x9c\x9c\xd2\xf8y\xb4\xa6\x0c\xa6\r\xf6\x18\x18\x9d\xdb\x80\xc3\xd5j2\x00\xb0\xb2S\xa2h\x1e\xfd\xb9\x11VI\x9c\x1c/\xb5T`*\xef7:\x07\xccp\xb4\xf2E\x98\x1b\x81hh\x96\x80\x1e\xa1;Z&\xbf\x80\xe8\x9b)\x111\x1a+\xe3\xf7\x7f\x18\x80\x81VmUA2\xe9\x02\xd0\x0c\x10\xfez$\x91\xda.\x11!\x16.S(\xc9Y,\x86\x84\xe36\xae?6\xd5\xc3\xb1\xa9\x9eY\xe7Z}\xa1\x0c\xb5\x83R\x1a`\x84\xeaKr\xc159k\xd7Ju{xqJ\xb4\xecx\xad[\x9e\xa8\xa5\xa1t\xc8\xda\x11B\xa2Vx\xc6\xf2\x8d\x11=}gk\x02\xdb_\x82\x03/\xcc\xd3\xfb\xabD\xbcBM\x8c\xd9a\xc2w\xae\xcd\x95\xc2x\xaay\xc3Yf\xba\x80\xd1\xd2\xf9B\xae\x90\x00\xd7\xa7\xd2\xaa\x95\x9b\x06d((B\xc3h:\x05\xdb\xc3\xd0C-\xba\x9dX\xb2s\xa3\xae\xe3\xd8N9h\xd1\xa54:n\xc5\x9bt\xf7\xa3\xebP\x9eD\x88U\x0b~\xee\x0b\x8d\\\xaf\xe7^\x9e\x0c>\xb3)\xa28\x02 \x98\xe1\x0eb\x8fch.\xd1Ps,\xc6yw\xd4\x9dEu\xbf\xa1\xb9`\x8f\x83\xf4\x8eZ\xd1\xafF\x00\xbb\xaa\xb7Dz\xef#\xb8f&7\xc1\xc5\xfd\xed\xad\xc4\x04\xe0\xa1\xd7f\xb8\xa8iS\x8c\xd5\x08D\xec9\xd6\xf4h\xa1\xf2\xfc\xbd\xfc\xd7\xe8\x14\x00{6A\xe2\xf1x8\xa9?\xf1-hW_\xbaa-\xdd\xeds\x07\xdaW\x9f\xe8\xe5\x997\'\x964~g\x0b\x1a\xbf\x1e;Q\x89^\xbd\xf540\x02d\xea\xdf8\x17\xdf\xd9\x85\x1e\xfd.=2\xca\xb5\x97\x9f\x87\xa17\x92x~\xcf)\x96\x85\x17\xef\xdc\xf55\xd2#\xe3\x95\x1fN\xe6u\xc2\xe4\x80\\\xc3<\x90J\xa5\xd4\xedV(\x93Q\x97e})n\x99\xc8\x95X\xdfgb\x1a:\x86\xae-\x19\x02\x8f\x1f\x86\xb3\x14\x1d\x17\xca\xd9W,\xe3\xd3}@\x06\xc8%\x12\t\xff\xdc\xdc\xf2,\xf6\xbc\x81o\xef:[,\xb37\x99\xc5-\xd9\x84\r\xb1$\xb8%\x9b\xbd\xc9,g\x8b\xe5\x8as\xfd\xc3\x8f\x81\xd3@\x16\xf0\xe6\xcc\x84\xa9T\n\xcb\xb2\xfc>\x86\x862j\xf3\xb4+\xf5\x9b\x8e\x8d:\xb8R\xb0z\xb9\xc0\x08\tB\x82y\xa1)\x8f\xe4\xf1"?\xfe\x92\xc3\xf5d\xbd\xf3\x0cp\x06\xb0\xab\xa7\xa6\xa6U:\x1e\x8f\x0b\xa0-\xe9\xdds\x03f\xd7\x8bh\xfa`\xd8\x10\\\xb8\xb2\x8d\xcd}\x92\x9e\x9eNt\xbd\xb1*\xfa\xbe\xcb\xd4\xd44\xbf\x9c\x12\x9c\x1c+Rr%H\xef(N\xe6u+\xfc\xc5\xe1 \xf23@\xb1~,o\xd9&\x02\x12\x11\xa0;\xa9\xee\x7f\x14=r7\x9a>P\xb5GM\xe8\xed\xac\xbc\xc3\x13\xd3\x1ev\xb9n\xb3\xf4\x8e\xe2\xe5\xbf\xb6\xf4\x0f>\x0f^\xb6\x89@\xf69\xa7\xa3\x7f=\x9a\xc5\xe3q-\xe8\x17\xed@W\xb2t\xdb&\x8c\xcem\x08s#\xc2X\x1f\xb4\xd4\xa0V\xbbi\xfcR\x9ar6\x15\x14\x99\x020\x1d\x10(\x00^\xb3\xc3\xea\x82\x0e\xa7\x81\x1aF\xa0H4@$\xf8O\xcc\x16\xb3\xca\xa8\xed\x00v\x00g\xbe\xc3\xe9?\x1b\x12\x1d\x02\xc3k\x0bv\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\x06o\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\tpHYs\x00\x00\x0b\r\x00\x00\x0b\r\x01\xed\x07\xc0,\x00\x00\x00\x07tIME\x07\xd3\t\t\x14\x14\x16\xe93\x80r\x00\x00\x05\xfcIDATx\xda\xc5\x97]l\x1cW\x15\xc7\x7f\xf3\xb5\xbbc\xc7k\xeffi\x12;\xa9\x93\xe2V\x0e!\x91\xe3\x81\x08\x11\x12\x1a T\x8d""\xaaJ}i\xa1\x1fX`\xc9\xad\xfaPU\x08$\xa4 @H<\x14\t\x1eJWN\t\xa4B\xedC\x0b\x08\xf5!%J\x95\xb6)\x95\xeaIm\xb7)_\x8b\x92\xa6\xce\xba\xf1\xc7\xee\xba\xbb;\xb3;3\xf7\xf2\xb0\xb3\xf6n\xbdk\xa7\x10\xc4\x95\xfeZ\xcd\x9es\xe7\xfc\xcf\xb9g\xce9\x17\xfe\xcfK\xf98\xca\xc3\xa3\x93;@\x1e\x021\x04\x0c!E\xc3;\xe4\x14RL!\xbc\xb3\x16\'3\x80H\xa7\xd3\xf2\x86\x10\x18\x1e\x9d|\x00\xb8\x1f8\x08\x12\x10\xa0F@\x8d\xd5\x14\x84\x0b\x81\xdb\xb8\xe5<\xc2?e\xc9\xf1\x13\x80\x97N\xa7\xc5\x7fD`xtr/\x8a\xfa\x04R|\x11U\x83H\x0fD\x92D\xa2&\xdb\xe2K|vk\x0e\x80\xa2\x0bg.\xf5\xe3\xb8U\xa8\xcc\x81\xbb\x00\xd2\x03\xa4C\xe0>f\xf1\x9b_\x03n+"\xca:^\x9f\x00\xc0\xdcLd\xc3M<\xb4o\x86\xdd\xb7l\xe0\xb6\xad\x1d\xc4"\xea\xaa=3\xf3\x15\xfe\xf2n\x81W\xfe\no^2\xa0t\xb9&\x08\xaa/X<\xfd-`)\x9dN\xfb\xeb\x12X6\xaeE!~\x1b\xf7\xee}\x9fc\xfbS$6\xe8m\xa3%?\xf2\xaaW\xa6\xf3\xfc\xea\xac\xc1\x07\xb3\xb3\xe0\x17AxS\x96<\xf1U`\xae1\x12Z[\xe3z\x07\xdb\xb6m\xe1\xb1;\x8a\x1c\xfeL\x12CW\xf1\x05M\xf8\xee\xa9"\xa7\'\xab\x1c\xdc\x15!\x10\xb2\t}\xa9(\x07\x06!W\xf4\xb94\xa7\x80\x0c6e\xe5\xaeO\xf52\xf9\x07\xcb\xb2|\xdb\xb6\xe5*\x02\xc3\xa3o\xed\x05\xe5E4\x83\xbe\xbe>\x1e?*\xd9\xbe)\x86\xe7\xcbU8\xfe\\\x99\xf1\xb1$\xc7\xf6\x99<:^\xe0s\xb7j\xabttMa\xf7v\x93kK\x82+\x0b\x00\xf2\xd6\xac\xb7\xe3\xf5^\xf5\xe2\x95\x90\x04\x1f=\xc8\xa7!\x80\xf8 \x0f\x1ep\x89w\xe8\x94+\xb2%\xc6\xc7\x92\xcb\x9b\xc6\xc7\x92\xfc\xe4y\xa7\xa5\x9e\x90\xf0\x8dCq\x06nN\xd4\x94#=\xc7\x81\x04\xa07E`x\xd4~\x00\xe4\xb71{\xb9o_\x8e\x9d\xfd\x1b\xf0\x02\xd9\x16[S\xd1&\xe6\xc7\xf6\x99|\xef\x99\x0f\xd9\xd3\xaf\xac\xd2\x95\xc0\xf6\x94\xe0\\\xa6\x07\xbc\xa5-Y\xb13\xdf\xabL]\xb0,\xab\xba\x12\x01)\xee\x07\x8dM\xa9.\x06\xfb;)\xb9bM\xb4Z\xe3cI\x9e\xfa\xb3\xd7R?\xdei\xf0\xf5\xa1\x02(\x06h\xb1\xbb\x80\x1e\xc0P\x01\x86\xbf\xf3\xe6\x0e\xe0 \xb1\x8d|i`\x01?\x80r%X\x13\x7fzc\xb1-\x89g^m\xd6-\x94|\xfe\x95-#\xd1 \xb6\x11\x14mh\xa2rd\'\x10\xab\x7fW\x87j\xe7\x93$\x15_\xa2\xe4\x88\xeb*\xcd\xcf\xbe<\xcf=\xb7\xa7Z\x92x\xe8\x97\x8b\xec\xe9-\xf3\xde\xa2\xc2\x1b3}+\xc2\x88\x03\xce,\x18\xdd\xfb\x81\x0bu\x02C\x00\x9b\xbb\x05\x92\x9a\xf7\x00\xaf\xfe\xc3X\x97\xc4\xe9\xb7\x17\x9b\x12\xb2\x99\x04\xfcm\xa1Y\x16\x89\x9aT\x01\xd4\xc8 `\xae\x10\xd0b$\xcc*\xc5\xd0\xfb\xb7\xde\x8f\xb6|\xf1\xc7Y\xe3cI\x0e\xfc0L\xb1\xb0-i*\xb5\x86\xb6\x12\x94/\xffX4t\xbb\xe6\xaa\xed\x05\xcd\xe7\xbc\x96q\xa3\xa1\xe38n5l\xd1\x95\x0c\x1a^\xcd\x9a\xf0\xce\xa2iP]@U\xb7\\\x97gu\x02\xeb\x19_\xce\xfc\xfa\xaa.\x84\xbf9\x1b\x13W\x05\x08g\xb8\xf38s\x18\x8a\x87\xa9\xb7\x87\xeb\x81\xeb\xadm\xfck?\xf3H\x98+\xa8\xef5\x14\x0f\x9c9\x10\xfe\xb4e\x9e\xbe\x0c8\xf5x\x0b\x84\x7f\n\x95\xcf/\xe5\xe7\xf9d_g[\xcf\x131\x07\x80\x93\x0f\xc7[\xca\xbf\xf9\x8b%\x12\xb1\xd6{33\xa5\xda\xf9\xfb\xc5\x97\xd0(\x01\x8e\x06`\xdb6G\x87\x95\xe9\xacj}\xc5\xaf\x14\xb7\xa6\x12qz\xcc\x80\x98\xde\x1ewZ\x1d\xab\x0c<\xf2\xd4|[}\xa7"\xc8^\xbdR\xf3^\xf9\xed\xcf\x81\x0f\x80|\xe3\x8c\xe5\x11\xb8\x8f\xa3\x99\xe72\x97g\xf8\xc2\x9eO`h\xd7\xffI~\xff\xe4U\xba\xa2\xed\xf2E!sy\xae\xf6\xe0f\x9f$J\x1e\xc8\x03\xder~\xda\xb6-\x8fZz6+?\x9d\x0b\x84z\xc7|\xbe\xc2@o\x84\x88\xa1ah\xca*\x9c{\xbb\xc8\xc1\xdd]\x00\xfc\xe8w\xd9\x96:\x86\xa6\xa0\xe2\xf3\xdaT\x8e\xb2\xebA5\xf7\x84e\xfc\xfe\x0c\x90\x05\xf2\xe9t:h\x1a\xc9,\xcb\x92\xbdLNf\xe5\xaeB5P\x0f_\x99\xab\xd2\x9fR\xe90\xa3\xe8\x9a\xb2\n\xe7/\x968\x7f\xb1\xd4R\xa6k\n\xaeS\xe6\xcc\x85\x02%\'4\xae=\xf7<0\x0b\xcc\x03U\xdb\xb6\x9bgB\xdb\xb6\xb1,+\xa8\x93\xf0\x84v\xf8\xef3.\x9eP\xd9\xb6Q\xc5\xd0Ut\x95u\xa1H\x9f\x89\x7f\x96y\xfd\x9d<\x9e/\x1a\x8dg\x81k\x80S\xbf5\xb5\xac\xd2###*\xd01\xe1\xdf};\x91\x9e\xe3(\xdap\xd4P\xb9ys\x07\xbbz\x05\xc9d7\x9a\xd6\xdc\xaa\x83\xc0cq\xb1\xc0;WU\xde\x9b-S\xf1\x04\x08\x7f\x1a7\xfb\xa4\x15}\xf1B\x98t\xd7\x80r\xe3X\xde\xb6M\x84$b@bB\xde\xfb Z\xec.\x14m\xa8.7#\x90\xea\xae\xe5\xf0|\xc1\xc7\xa96l\x16\xfe4~\xf1%K{\xf6\x8fa\xb2\xcd\x03\xb9V\xb7\xa35\xaff###J8\xbdv\x02=\x13\x95#;1\xba\xf7\xa3F\x06Q\x8d\x81\xb0\xa5\x86\xb5\xda\xcb\x10T2TsvXdJ@!$P\x02\xfcV\x97\xd5\xeb\xba\x9c\x86\xd10\xc2\x88\x98!b\xe1\x7f\xear1\x03\x0fp\x01\'\x84\xbb\xde\xe5\xf4\xdf\xbb2F\xa9\x19V~L\x00\x00\x00\x00IEND\xaeB`\x82\x00\x00\t\xa3\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04gAMA\x00\x00\xaf\xc87\x05\x8a\xe9\x00\x00\x00\x19tEXtSoftware\x00Adobe ImageReadyq\xc9e<\x00\x00\t5IDATx\xdab\xfc\xff\xff?\xc3@\x02\x80\x00b\xa4Ds\xe7\xb4\xa3\x86\xcc\xcc,\xe7N\x1d\xdd,\xbdjQ\xcbk\xa0\xd0oR\xcd\x00\x08 &J\x1c\xc0\xc4\xc4\xdc\xaf\xa2 \xc8\xa0\xa0\xac\x9b\r\xe4\xf2\x0313\xa9f\x00\x04\x10\x93\xe5\x94\'\x0f\x8c\x9aN\x98\x03\xd9l\xa4\x84H\xf7\x8c\xe3\x85:\xea\xa2\xf6\x1e\x0eJ\x0c\x82\xc2\x92I@!A f%\xd5\x01\x00\x01\x04\x0c\x81\xff\x8cl\x82\x92k\xc4m\xe3\x14\xcb\x1aW\xaa\xb6O>h\x04\r\x19\x9c\x8e\xe9\x98rX\x91\x83\x9d\xb5\xde\xd1J\x9e\x81\x9d\x8d\x99\xc1@[Z""\xa1\xce\x11(\xc5Ej\xb4\x02\x04\x10\xd3\x9f\xef\x9f\xa7\x0b\xf3\xb2\xcb\xc4\xa5\xd6\xdc\x10\x15\x97;\xcd\xc2\xca\xbe\xaf\xb8v\xa9\x0fP\x8e\x1d\x97a\xcc,\xac\xfd@\x9f\xf3\x83,\xff\xf7\xef?\x03(\x1a\x94\xd4\x8c\x02\x80R\xdc@\xcc\x02R#\x97z$P6\xf9\xf0F\xe9\xf8=S\x80\\\x0e\\\xd1\r\x10@\xcc|J&\xb7\x19\x84\x94J|\x8d\x04\x19\xbe>\x7f\xc7\xce\xc8\xc8\xc8\xc1\xc9\xc5c\xff\xf1\xc3\xeb-\xcf\x1e\xdf\xfa\x04T\xf3\x17YC\xd7\xf4\xe3\x81\xf22\x02\xf5\xb6f\xb2\x0c\xa0\x0c\x04r\x80\x90\x00\'\xc3\xfd\xa7?U\xd9\xd9y\x8e\xc5\xa5\xb5\xc4x\x04\xe7\xacy\xfb\x8b9^ZZ@\xfd\xc5\x9b\x9ff\x0cLl;\x7f=?\xfb\x06\xa8\xfd\x0f\xba\x03\x00\x02\x88\xf9\xcd\xd9\x8d?\xa4\x9c\xd3\xd4EE\xf8t\x04\xff|c\xe0`eb\xe0\xe4d\xe7\x95\x94\xd1\xd2>\xb0k\xc9f\xa0\x9a\x9f@\xfc\x0f\xa4\xb8g\xe6I\x01\x0ev\x96\x03\xc1\x9e\xea\x1c\xec\xec,\x0c\xa0,\x0cr\xc0\xdf\xbf\xff\x80\xf8?\x83\xbc\xb2v\x98\xbb\x83\x9a\x8d\xb4\x18\x0f\x07\xeb\xd7\xcf\x0c\xd6V\x8a\x0cW\xef\x7fb\xf8\xfc\x83\xe5\xff\xb7\xdb\x9b\x8e\x02\x8d\xf8\x013\x0b\x06\x00\x02\x08\x14,\x7f\xff\xfe\xfc\xb6\xf1\xe4\xfdo\x0cR*\x12\x0c?\x7f\xfea\xe0\xe7eg\xb0\xb3\xd2t(\xaa]R\x0c\x94\xe7\x81\x05\xdf\xff\xff\xff\x1a\xac\x8c\xa5\xf9\xf9\x80\xf20\xcba\x0e\xd0P\x11f\xf8\xf2\xe57\x83\x10?\x07\x83\x92,?\x03\xd0\x1f\x0c/\xaf\xdecp4\x97f`\xe4\x96\xf4\x06j\xe7\xc3\x96H\x01\x02\x08\x9cm\x9e\xef\x9dyK\xc8!;QY\x86\x8f\x8f\xf3\xfb\x17\x066\x16&\x06a\x01\x0e\x06\x11Q1\xeb\x7fL\xfc\xc7\xaf^<\xf4\xb8k\xfa1\x1by\x19\xc1\xe9.\xb6\n`\x8d0\xcba\x18\x94\x1e\x9e\xbe\xfc\xc2\xc0\xc7\xcd\xc6\xc0\xc1\xce\xcc\xf0\xf3\xf7?\x86\xe7\xcf?1\xc8\xaaI2\x1c\xbd\xf0\x96\xe7?\xb7\xe2\xa3\x9f\x8f\x0f\\\x81\x86(\xbc\xf4\x03\x08 X\xbe\xfd/n\x97"\xfe\x8f\x99\xddZ\x89\xf7?\xc3\xd7\x8f\xdf\x18~\xfe\xfa\xcb\xe0\xe3\xac\xc2\xf0\xe1\x07\x9f\x03\x0b+\xcfAy%\x9d%\xfe\xeej\xfc\xdc\\\xacP\xdf3@}\x0fq\xc0o\xa0\x85<@\xcb\xaf\xdez\xc3 \'\xc5\xc7 \x08\x0c\x89\xcb7\xdf00\x03C\xe2\xe3\x7f6\x86\xc7/\xffp\xfd\xb8\xb3v+\xd0\xaeo\xc8\xe9\n \x80`)\xf3\xdf\x8f7\x0f\xe6_|\xf0\x95\x81IH\x00\x1e<\x8f\x9f}b\x08\xf2\xd4\x96\xb4v\x0c\xdbim"+\'&\xcc\x85\xe4\xfb\x7f`\x1a\xe4\x18\x88\x83\xfe1\xc8H\xf00<\x7f\xfd\x15\xe8\xf8?\x0c\x1c\xc0\x10\x11\x11\xe2d\xf8\xf6\xfa=\x83\x83\x99\x14\x030\xaf\xdb\xb0\x88\x1aICs\x17\x1c\x00\x04\x10\x02}\x0cJ\x88 l\xa4#\x0e\xce\x19\xd8|\x0eq\x080\\\x81\x85\xd8\x8b7\xdf\xc0\x06\x89\x02\xb3!H\x0c\x14" \xf0\xe3\xcd{\x06\x17\'\x15`\xd5$\x07O\x8c\x00\x01\x84\xcd\x01\xff\xef\xcep_\xf3\xea\xed\xd7\'\xaf\xff\xb3\x83\x13"(\xd8A\x16\x83\x82\x92\x9f\x8f\x1d\\>`s\x04\x08\xf0\xf2q2\x1c?\xf7\x94\xc1\\_\x1cQW\x00}\xaf\xae$\xc4\xf0\xf3\xed{\x06\x0bc)`e\xc0*\xc1 \x9f\x0eN\x8c\x00\x01\x84\xabE\xf4\xe7\xdf\x8f/\xcb\xce\x00\x13#\x8f0\x1f8G\x80\x12 \x08h\xa9\x8a0<{\xf5\x05#\xf8A\x80\x87\x87\x9d\xe1\xdc\xd5W\x0c\x12"\\\xc0\xb8g\x85\xcb\x83\x00H\x0c\xdc\x06\xfc\xfc\x11XI\x01\x8bs^\rpb\x04\x08 \\\x0e\xf8\xf7\xf3\xfd\x93\xf9G/\x02\xf3>\x1f/\xb8L\x00gI\xa0#\x14\xe5\x04\x19\x9e\xbd\xfc\xcc\xf0\xeb\xf7?\x94\xe0gbbd\xf8\xf6\xf3\x1f\xc3\xc3\xc7\x1f\x18tT\x85\xe1Q\x02\x03\x12"\x9c\xe0\x10\xfc\xf9\xea\r\x83\xb5\xad\x12\xb0\xfd%\xea\xc9\xc0\xa7/\r\x10@8\xdb\x84\xcfV\xc5\xdd\xf9\xf7\xeb\xc7\xb1\xb3O~3\xb0\t\xf2\x01\x0b\xa5\x9f\x0c\'\xcf?\x05\x17\xb3\x8a\xb2\x02\x0cO^|B\tz\x11\x11\x1e\x86\xe3g\x1f3\x98\xe9\x89\xa3\x84\x0e,d^\x7f\xf8\t\xf6\x047\xb0\x08R\x14c\x03\xaa\x07\xa6A\xc9\x80\x08\x80\x00\xc2\xd7\x88\xfc\xcf\xa9\xe0p\xe3\xf63\xc6P#S9v\xae?\xdf\x19\xfe\x02-\x7f\r\xcc\x92\xa6\xfa\xd2\x0c\xe7\xae\x9c^\x0b\x10@\x8cD\xf6\x1d\xb8E\x826\xed\xb16S2\x0b7\xe4`\xf8\xfb\xe5\x0b\xd07\x7f\x19XY\x18\x19t5$\x81Y\xf4-\xd8\xf2\x97\xaf\xbf\x01}\xcf\xc4\xf0\xf5\xdb\x1f\x86\xbf\xc0\xe8`bgg\xe0\x92\x93f8u\xf5=\xc3\xee\xbd\xb7\x19\x1e=\x00\x06\xc7\x8f\'{\x18^n]\xcd\xf0\xee\xd8\x03\xa0\xb9\x9f\x00\x02\x88\xd8&4\x13\xa7f\x94<\xa7z\xcc\xc5\xc4Pm^c\x9eO\x0cL\xc0h\x00E\x050\xaa\xc1\t\x91\x91\t\x14\xbf\x7f\x19\xfe\x00\x83\xf9?\x17\x0f\xc3\x07&n\x86\xfd\xa7^2\x1c>t\x8f\xe1\xdb\xe7\x0f\xf7\x18>_\xdb\xc0po\xc2\x16\xa0Y_A\x16\x03\xf1G\x10\x1b \x80Hi\xc3\xb3p[6\xdb\xf3\xc9\x98\xef)N\xd0b\x90\xf8\xf1\n\x1c\xff\xff\xfe\xfd\x05W\xbd \x8b\xff\xf1\t1\xdcx\xcb\xcc\xb0s\xdf=\x863\xa7\x1f\x03\x1b_/\xf60\xbc9\xb0\x96\xe1\xe5\x96\xab\xa0$\x05\xb5\xf4\x13\xb4U\xf4\x0b\x94,\x00\x02\x88\xd4\xbe!;\x8f\xc3\xdcJ\x11)\xf9\xfa\x86\x02S\x06.6&p\xe3\xee\xdb\xa7\xaf\x0c\x07\xcf\xbfc\xd8\xbe\xeb.\xc3\xeb\x17o^\xfd\xff\xfah\xf7\xffG\x0bV3|\xbb\xff\n\xc9\xb7 \x07|\x87\xf6\x1f\xe1-c\x80\x00"\xd5\x01 \xf5\\\\\xf6\x8b\x16\xfdg\xe6\r\xfa\x0fj\x96\x01[\xc4\xa0\xec\xf7\xff\xc7\xfb\xcb\x7f\xdf\x9d[\xff\xff\xfe\xcc}\xe8\xc1\x0cm\x88\xfeAn\x8c\xc2\x00@\x00\x91\xd3;\x06%J^ \x16\x07b\x01X\xbd\x0emh~\x87Z\xfc\t\xca\xfe\x85\xde\xb1A\x07\x00\x01\x06\x00MUx_,\x92\xe0`\x00\x00\x00\x00IEND\xaeB`\x82' 9 | qt_resource_name = b'\x00\x08\x0bcX\x07\x00s\x00t\x00o\x00p\x00.\x00p\x00n\x00g\x00\x0c\x05h\x0eg\x00f\x00i\x00l\x00e\x00s\x00a\x00v\x00e\x00.\x00p\x00n\x00g\x00\x0c\t\xa7\x0eG\x00f\x00i\x00l\x00e\x00q\x00u\x00i\x00t\x00.\x00p\x00n\x00g\x00\x0c\x0b!\x0f\x87\x00f\x00i\x00l\x00e\x00o\x00p\x00e\x00n\x00.\x00p\x00n\x00g\x00\x08\naZ\xa7\x00i\x00c\x00o\x00n\x00.\x00p\x00n\x00g\x00\x08\n\xc3X\x07\x00s\x00t\x00e\x00p\x00.\x00p\x00n\x00g\x00\x07\t\xc1W\xa7\x00r\x00u\x00n\x00.\x00p\x00n\x00g\x00\x0b\x04\x14R\xc7\x00f\x00i\x00l\x00e\x00n\x00e\x00w\x00.\x00p\x00n\x00g' 10 | qt_resource_struct = b'\x00\x00\x00\x00\x00\x02\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x01\x00\x00-h\x00\x00\x00\x16\x00\x00\x00\x00\x00\x01\x00\x00\x05\xc0\x00\x00\x004\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x08\x00\x00\x00\x9c\x00\x00\x00\x00\x00\x01\x00\x00&\xf5\x00\x00\x00p\x00\x00\x00\x00\x00\x01\x00\x00\x1a+\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00 \xc5\x00\x00\x00R\x00\x00\x00\x00\x00\x01\x00\x00\x12\x87\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00' 11 | 12 | def qInitResources(): 13 | QtCore.qRegisterResourceData(1, qt_resource_struct, qt_resource_name, qt_resource_data) 14 | 15 | 16 | def qCleanupResources(): 17 | QtCore.qUnregisterResourceData(1, qt_resource_struct, qt_resource_name, qt_resource_data) 18 | 19 | 20 | qInitResources() 21 | # okay decompiling resources_rc.pyc 22 | --------------------------------------------------------------------------------