From fbb6de2e3c5c7a8c5f5a67ce878ba68d9448d85c Mon Sep 17 00:00:00 2001 From: Jareth Gomes Date: Mon, 17 Apr 2023 04:29:43 +0000 Subject: [PATCH] Removed other spim library references --- spim-jsspim/CPU/data.cpp | 348 - spim-jsspim/CPU/data.h | 54 - spim-jsspim/CPU/display-utils.cpp | 290 - spim-jsspim/CPU/dump_ops.cpp | 129 - spim-jsspim/CPU/exceptions.s | 195 - spim-jsspim/CPU/inst.cpp | 1638 ----- spim-jsspim/CPU/inst.h | 273 - spim-jsspim/CPU/mem.cpp | 778 --- spim-jsspim/CPU/mem.h | 161 - spim-jsspim/CPU/op.h | 525 -- spim-jsspim/CPU/parser.h | 50 - spim-jsspim/CPU/parser.y | 2956 --------- spim-jsspim/CPU/reg.h | 245 - spim-jsspim/CPU/run.cpp | 1872 ------ spim-jsspim/CPU/run.h | 36 - spim-jsspim/CPU/scanner.h | 58 - spim-jsspim/CPU/scanner.l | 733 --- spim-jsspim/CPU/spim-syscall.h | 52 - spim-jsspim/CPU/spim-utils.cpp | 628 -- spim-jsspim/CPU/spim-utils.h | 67 - spim-jsspim/CPU/spim.h | 260 - spim-jsspim/CPU/string-stream.cpp | 142 - spim-jsspim/CPU/string-stream.h | 48 - spim-jsspim/CPU/sym-tbl.cpp | 518 -- spim-jsspim/CPU/sym-tbl.h | 76 - spim-jsspim/CPU/syscall.cpp | 337 - spim-jsspim/CPU/syscall.h | 62 - spim-jsspim/CPU/version.h | 1 - spim-jsspim/spim.cpp | 218 - spim-qtbase/CPU/data.cpp | 347 - spim-qtbase/CPU/data.h | 54 - spim-qtbase/CPU/display-utils.cpp | 287 - spim-qtbase/CPU/dump_ops.cpp | 129 - spim-qtbase/CPU/exceptions.s | 195 - spim-qtbase/CPU/inst.cpp | 1700 ----- spim-qtbase/CPU/inst.h | 280 - spim-qtbase/CPU/mem.cpp | 778 --- spim-qtbase/CPU/mem.h | 161 - spim-qtbase/CPU/op.h | 525 -- spim-qtbase/CPU/parser.h | 50 - spim-qtbase/CPU/parser.y | 2967 --------- spim-qtbase/CPU/reg.h | 240 - spim-qtbase/CPU/run.cpp | 1849 ------ spim-qtbase/CPU/run.h | 36 - spim-qtbase/CPU/scanner.h | 58 - spim-qtbase/CPU/scanner.l | 733 --- spim-qtbase/CPU/spim-syscall.h | 52 - spim-qtbase/CPU/spim-utils.cpp | 625 -- spim-qtbase/CPU/spim-utils.h | 67 - spim-qtbase/CPU/spim.h | 260 - spim-qtbase/CPU/string-stream.cpp | 142 - spim-qtbase/CPU/string-stream.h | 48 - spim-qtbase/CPU/sym-tbl.cpp | 518 -- spim-qtbase/CPU/sym-tbl.h | 76 - spim-qtbase/CPU/syscall.cpp | 337 - spim-qtbase/CPU/syscall.h | 62 - spim-qtbase/CPU/version.h | 1 - spim-qtbase/QtSpim/NewIcon.icns | Bin 96341 -> 0 bytes spim-qtbase/QtSpim/QtSpim.pro | 256 - spim-qtbase/QtSpim/README | 56 - spim-qtbase/QtSpim/breakpoint.ui | 115 - spim-qtbase/QtSpim/changevalue.ui | 102 - spim-qtbase/QtSpim/console.cpp | 155 - spim-qtbase/QtSpim/console.h | 64 - spim-qtbase/QtSpim/datatextedit.h | 57 - spim-qtbase/QtSpim/datawin.cpp | 415 -- spim-qtbase/QtSpim/exception.qrc | 39 - spim-qtbase/QtSpim/help/Fig10_1.jpg | Bin 53679 -> 0 bytes spim-qtbase/QtSpim/help/Fig10_2.jpg | Bin 175832 -> 0 bytes spim-qtbase/QtSpim/help/Fig1_1.jpg | Bin 34474 -> 0 bytes spim-qtbase/QtSpim/help/Fig1_6.jpg | Bin 22713 -> 0 bytes spim-qtbase/QtSpim/help/Fig2_1.jpg | Bin 16842 -> 0 bytes spim-qtbase/QtSpim/help/Fig3_1.jpg | Bin 35515 -> 0 bytes spim-qtbase/QtSpim/help/Fig5_1.jpg | Bin 18651 -> 0 bytes spim-qtbase/QtSpim/help/Fig6_2.jpg | Bin 19368 -> 0 bytes spim-qtbase/QtSpim/help/Fig6_3.jpg | Bin 22336 -> 0 bytes spim-qtbase/QtSpim/help/Fig6_3a.jpg | Bin 6705 -> 0 bytes spim-qtbase/QtSpim/help/Fig7_1.jpg | Bin 14836 -> 0 bytes spim-qtbase/QtSpim/help/Fig7_2.jpg | Bin 14591 -> 0 bytes spim-qtbase/QtSpim/help/Fig8_1.jpg | Bin 42403 -> 0 bytes spim-qtbase/QtSpim/help/HP_AppA.html | 6210 ------------------ spim-qtbase/QtSpim/help/main_windows.jpg | Bin 379586 -> 0 bytes spim-qtbase/QtSpim/help/qtspim.qhc | Bin 163840 -> 0 bytes spim-qtbase/QtSpim/help/qtspim.qhcp | 27 - spim-qtbase/QtSpim/help/qtspim.qhp | 72 - spim-qtbase/QtSpim/help/qtspim_help.html | 164 - spim-qtbase/QtSpim/help/settings_dialog.jpg | Bin 52497 -> 0 bytes spim-qtbase/QtSpim/help/settings_dialog2.jpg | Bin 52243 -> 0 bytes spim-qtbase/QtSpim/macinfo.plist | 22 - spim-qtbase/QtSpim/main.cpp | 268 - spim-qtbase/QtSpim/menu.cpp | 875 --- spim-qtbase/QtSpim/printwindows.ui | 150 - spim-qtbase/QtSpim/qtspim.rc | 1 - spim-qtbase/QtSpim/regtextedit.h | 61 - spim-qtbase/QtSpim/regwin.cpp | 619 -- spim-qtbase/QtSpim/runparams.ui | 172 - spim-qtbase/QtSpim/savelogfile.ui | 224 - spim-qtbase/QtSpim/settablecheckbox.h | 47 - spim-qtbase/QtSpim/settings.ui | 616 -- spim-qtbase/QtSpim/spim_settings.h | 110 - spim-qtbase/QtSpim/spim_support.cpp | 172 - spim-qtbase/QtSpim/spimview.cpp | 280 - spim-qtbase/QtSpim/spimview.h | 306 - spim-qtbase/QtSpim/spimview.ui | 593 -- spim-qtbase/QtSpim/state.cpp | 232 - spim-qtbase/QtSpim/texttextedit.h | 59 - spim-qtbase/QtSpim/textwin.cpp | 290 - spim-qtbase/QtSpim/windows_images.qrc | 51 - spim-qtbase/README | 49 - spim-qtbase/Tests/read.s | 50 - spim-qtbase/Tests/time.s | 57 - spim-qtbase/Tests/timer.s | 50 - spim-qtbase/Tests/tt.alu.bare.s | 1852 ------ spim-qtbase/Tests/tt.bare.s | 519 -- spim-qtbase/Tests/tt.be.s | 556 -- spim-qtbase/Tests/tt.core.s | 4862 -------------- spim-qtbase/Tests/tt.dir.s | 167 - spim-qtbase/Tests/tt.fpu.bare.s | 2239 ------- spim-qtbase/Tests/tt.in | 6 - spim-qtbase/Tests/tt.io.s | 209 - spim-qtbase/Tests/tt.le.s | 546 -- spim-qtbase/helloworld.s | 45 - spim-qtbase/spim.cpp | 1277 ---- spim-qtspimbot/CPU/data.cpp | 336 - spim-qtspimbot/CPU/data.h | 54 - spim-qtspimbot/CPU/display-utils.cpp | 295 - spim-qtspimbot/CPU/dump_ops.cpp | 129 - spim-qtspimbot/CPU/exceptions.s | 195 - spim-qtspimbot/CPU/inst.cpp | 1606 ----- spim-qtspimbot/CPU/inst.h | 280 - spim-qtspimbot/CPU/mem.cpp | 882 --- spim-qtspimbot/CPU/mem.h | 158 - spim-qtspimbot/CPU/op.h | 525 -- spim-qtspimbot/CPU/parser.h | 50 - spim-qtspimbot/CPU/parser.y | 2957 --------- spim-qtspimbot/CPU/reg.h | 268 - spim-qtspimbot/CPU/run.cpp | 1731 ----- spim-qtspimbot/CPU/run.h | 36 - spim-qtspimbot/CPU/scanner.h | 58 - spim-qtspimbot/CPU/scanner.l | 738 --- spim-qtspimbot/CPU/spim-syscall.h | 52 - spim-qtspimbot/CPU/spim-utils.cpp | 658 -- spim-qtspimbot/CPU/spim-utils.h | 92 - spim-qtspimbot/CPU/spim.h | 267 - spim-qtspimbot/CPU/string-stream.cpp | 142 - spim-qtspimbot/CPU/string-stream.h | 52 - spim-qtspimbot/CPU/sym-tbl.cpp | 522 -- spim-qtspimbot/CPU/sym-tbl.h | 76 - spim-qtspimbot/CPU/syscall.cpp | 373 -- spim-qtspimbot/CPU/syscall.h | 66 - spim-qtspimbot/CPU/vasm.cpp | 162 - spim-qtspimbot/CPU/vasm.h | 8 - spim-qtspimbot/CPU/version.h | 1 - spim-qtspimbot/README | 49 - spim-qtspimbot/spim.cpp | 1277 ---- 155 files changed, 64786 deletions(-) delete mode 100755 spim-jsspim/CPU/data.cpp delete mode 100755 spim-jsspim/CPU/data.h delete mode 100755 spim-jsspim/CPU/display-utils.cpp delete mode 100644 spim-jsspim/CPU/dump_ops.cpp delete mode 100755 spim-jsspim/CPU/exceptions.s delete mode 100755 spim-jsspim/CPU/inst.cpp delete mode 100755 spim-jsspim/CPU/inst.h delete mode 100755 spim-jsspim/CPU/mem.cpp delete mode 100755 spim-jsspim/CPU/mem.h delete mode 100755 spim-jsspim/CPU/op.h delete mode 100755 spim-jsspim/CPU/parser.h delete mode 100755 spim-jsspim/CPU/parser.y delete mode 100755 spim-jsspim/CPU/reg.h delete mode 100755 spim-jsspim/CPU/run.cpp delete mode 100755 spim-jsspim/CPU/run.h delete mode 100755 spim-jsspim/CPU/scanner.h delete mode 100755 spim-jsspim/CPU/scanner.l delete mode 100644 spim-jsspim/CPU/spim-syscall.h delete mode 100755 spim-jsspim/CPU/spim-utils.cpp delete mode 100755 spim-jsspim/CPU/spim-utils.h delete mode 100755 spim-jsspim/CPU/spim.h delete mode 100755 spim-jsspim/CPU/string-stream.cpp delete mode 100755 spim-jsspim/CPU/string-stream.h delete mode 100755 spim-jsspim/CPU/sym-tbl.cpp delete mode 100755 spim-jsspim/CPU/sym-tbl.h delete mode 100755 spim-jsspim/CPU/syscall.cpp delete mode 100755 spim-jsspim/CPU/syscall.h delete mode 100644 spim-jsspim/CPU/version.h delete mode 100644 spim-jsspim/spim.cpp delete mode 100755 spim-qtbase/CPU/data.cpp delete mode 100755 spim-qtbase/CPU/data.h delete mode 100755 spim-qtbase/CPU/display-utils.cpp delete mode 100644 spim-qtbase/CPU/dump_ops.cpp delete mode 100755 spim-qtbase/CPU/exceptions.s delete mode 100755 spim-qtbase/CPU/inst.cpp delete mode 100755 spim-qtbase/CPU/inst.h delete mode 100755 spim-qtbase/CPU/mem.cpp delete mode 100755 spim-qtbase/CPU/mem.h delete mode 100755 spim-qtbase/CPU/op.h delete mode 100755 spim-qtbase/CPU/parser.h delete mode 100755 spim-qtbase/CPU/parser.y delete mode 100755 spim-qtbase/CPU/reg.h delete mode 100755 spim-qtbase/CPU/run.cpp delete mode 100755 spim-qtbase/CPU/run.h delete mode 100755 spim-qtbase/CPU/scanner.h delete mode 100755 spim-qtbase/CPU/scanner.l delete mode 100644 spim-qtbase/CPU/spim-syscall.h delete mode 100755 spim-qtbase/CPU/spim-utils.cpp delete mode 100755 spim-qtbase/CPU/spim-utils.h delete mode 100755 spim-qtbase/CPU/spim.h delete mode 100755 spim-qtbase/CPU/string-stream.cpp delete mode 100755 spim-qtbase/CPU/string-stream.h delete mode 100755 spim-qtbase/CPU/sym-tbl.cpp delete mode 100755 spim-qtbase/CPU/sym-tbl.h delete mode 100755 spim-qtbase/CPU/syscall.cpp delete mode 100755 spim-qtbase/CPU/syscall.h delete mode 100644 spim-qtbase/CPU/version.h delete mode 100644 spim-qtbase/QtSpim/NewIcon.icns delete mode 100644 spim-qtbase/QtSpim/QtSpim.pro delete mode 100644 spim-qtbase/QtSpim/README delete mode 100644 spim-qtbase/QtSpim/breakpoint.ui delete mode 100644 spim-qtbase/QtSpim/changevalue.ui delete mode 100644 spim-qtbase/QtSpim/console.cpp delete mode 100644 spim-qtbase/QtSpim/console.h delete mode 100644 spim-qtbase/QtSpim/datatextedit.h delete mode 100644 spim-qtbase/QtSpim/datawin.cpp delete mode 100644 spim-qtbase/QtSpim/exception.qrc delete mode 100644 spim-qtbase/QtSpim/help/Fig10_1.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig10_2.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig1_1.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig1_6.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig2_1.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig3_1.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig5_1.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig6_2.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig6_3.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig6_3a.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig7_1.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig7_2.jpg delete mode 100644 spim-qtbase/QtSpim/help/Fig8_1.jpg delete mode 100644 spim-qtbase/QtSpim/help/HP_AppA.html delete mode 100644 spim-qtbase/QtSpim/help/main_windows.jpg delete mode 100644 spim-qtbase/QtSpim/help/qtspim.qhc delete mode 100644 spim-qtbase/QtSpim/help/qtspim.qhcp delete mode 100644 spim-qtbase/QtSpim/help/qtspim.qhp delete mode 100644 spim-qtbase/QtSpim/help/qtspim_help.html delete mode 100644 spim-qtbase/QtSpim/help/settings_dialog.jpg delete mode 100644 spim-qtbase/QtSpim/help/settings_dialog2.jpg delete mode 100644 spim-qtbase/QtSpim/macinfo.plist delete mode 100644 spim-qtbase/QtSpim/main.cpp delete mode 100644 spim-qtbase/QtSpim/menu.cpp delete mode 100644 spim-qtbase/QtSpim/printwindows.ui delete mode 100644 spim-qtbase/QtSpim/qtspim.rc delete mode 100644 spim-qtbase/QtSpim/regtextedit.h delete mode 100644 spim-qtbase/QtSpim/regwin.cpp delete mode 100644 spim-qtbase/QtSpim/runparams.ui delete mode 100644 spim-qtbase/QtSpim/savelogfile.ui delete mode 100644 spim-qtbase/QtSpim/settablecheckbox.h delete mode 100644 spim-qtbase/QtSpim/settings.ui delete mode 100644 spim-qtbase/QtSpim/spim_settings.h delete mode 100644 spim-qtbase/QtSpim/spim_support.cpp delete mode 100644 spim-qtbase/QtSpim/spimview.cpp delete mode 100644 spim-qtbase/QtSpim/spimview.h delete mode 100644 spim-qtbase/QtSpim/spimview.ui delete mode 100644 spim-qtbase/QtSpim/state.cpp delete mode 100644 spim-qtbase/QtSpim/texttextedit.h delete mode 100644 spim-qtbase/QtSpim/textwin.cpp delete mode 100644 spim-qtbase/QtSpim/windows_images.qrc delete mode 100644 spim-qtbase/README delete mode 100644 spim-qtbase/Tests/read.s delete mode 100644 spim-qtbase/Tests/time.s delete mode 100644 spim-qtbase/Tests/timer.s delete mode 100755 spim-qtbase/Tests/tt.alu.bare.s delete mode 100755 spim-qtbase/Tests/tt.bare.s delete mode 100755 spim-qtbase/Tests/tt.be.s delete mode 100755 spim-qtbase/Tests/tt.core.s delete mode 100644 spim-qtbase/Tests/tt.dir.s delete mode 100755 spim-qtbase/Tests/tt.fpu.bare.s delete mode 100755 spim-qtbase/Tests/tt.in delete mode 100755 spim-qtbase/Tests/tt.io.s delete mode 100755 spim-qtbase/Tests/tt.le.s delete mode 100644 spim-qtbase/helloworld.s delete mode 100755 spim-qtbase/spim.cpp delete mode 100755 spim-qtspimbot/CPU/data.cpp delete mode 100755 spim-qtspimbot/CPU/data.h delete mode 100755 spim-qtspimbot/CPU/display-utils.cpp delete mode 100644 spim-qtspimbot/CPU/dump_ops.cpp delete mode 100755 spim-qtspimbot/CPU/exceptions.s delete mode 100755 spim-qtspimbot/CPU/inst.cpp delete mode 100755 spim-qtspimbot/CPU/inst.h delete mode 100755 spim-qtspimbot/CPU/mem.cpp delete mode 100755 spim-qtspimbot/CPU/mem.h delete mode 100755 spim-qtspimbot/CPU/op.h delete mode 100755 spim-qtspimbot/CPU/parser.h delete mode 100755 spim-qtspimbot/CPU/parser.y delete mode 100755 spim-qtspimbot/CPU/reg.h delete mode 100755 spim-qtspimbot/CPU/run.cpp delete mode 100755 spim-qtspimbot/CPU/run.h delete mode 100755 spim-qtspimbot/CPU/scanner.h delete mode 100755 spim-qtspimbot/CPU/scanner.l delete mode 100644 spim-qtspimbot/CPU/spim-syscall.h delete mode 100755 spim-qtspimbot/CPU/spim-utils.cpp delete mode 100755 spim-qtspimbot/CPU/spim-utils.h delete mode 100755 spim-qtspimbot/CPU/spim.h delete mode 100755 spim-qtspimbot/CPU/string-stream.cpp delete mode 100755 spim-qtspimbot/CPU/string-stream.h delete mode 100755 spim-qtspimbot/CPU/sym-tbl.cpp delete mode 100755 spim-qtspimbot/CPU/sym-tbl.h delete mode 100755 spim-qtspimbot/CPU/syscall.cpp delete mode 100755 spim-qtspimbot/CPU/syscall.h delete mode 100644 spim-qtspimbot/CPU/vasm.cpp delete mode 100644 spim-qtspimbot/CPU/vasm.h delete mode 100644 spim-qtspimbot/CPU/version.h delete mode 100644 spim-qtspimbot/README delete mode 100755 spim-qtspimbot/spim.cpp diff --git a/spim-jsspim/CPU/data.cpp b/spim-jsspim/CPU/data.cpp deleted file mode 100755 index 815a27f..0000000 --- a/spim-jsspim/CPU/data.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to manipulate data segment directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser.h" -#include "run.h" -#include "data.h" - - -/* The first 64K of the data segment are dedicated to small data - segment, which is pointed to by $gp. This register points to the - middle of the segment, so we can use the full offset field in an - instruction. */ - -static mem_addr next_data_pc; /* Location for next datum in user process */ - -static mem_addr next_k_data_pc; /* Location for next datum in kernel */ - -static bool in_kernel = 0; /* => data goes to kdata, not data */ - -#define DATA_PC (in_kernel ? next_k_data_pc : next_data_pc) - -static mem_addr next_gp_item_addr; /* Address of next item accessed off $gp */ - -static bool auto_alignment = true; /* => align literal to natural bound*/ - - - -/* If TO_KERNEL is true, subsequent data will be placed in the - kernel data segment. If false, data will go to the user's data - segment.*/ - -void -user_kernel_data_segment (bool to_kernel) -{ - in_kernel = to_kernel; -} - - -void -end_of_assembly_file () -{ - in_kernel = false; - auto_alignment = true; -} - - -/* Set the point at which the first datum is stored to be ADDRESS + - 64K. The 64K increment allocates an area pointed to by register - $gp, which is initialized. */ - -void -data_begins_at_point (mem_addr addr) -{ - if (bare_machine) - next_data_pc = addr; - else - { - next_gp_item_addr = addr; - gp_midpoint = addr + 32*K; - R[REG_GP] = gp_midpoint; - next_data_pc = addr + 64 * K; - } -} - - -/* Set the point at which the first datum is stored in the kernel's - data segment. */ - -void -k_data_begins_at_point (mem_addr addr) -{ - next_k_data_pc = addr; -} - - -/* Arrange that the next datum is stored on a memory boundary with its - low ALIGNMENT bits equal to 0. If argument is 0, disable automatic - alignment.*/ - -void -align_data (int alignment) -{ - if (alignment == 0) - auto_alignment = false; - else if (in_kernel) - { - next_k_data_pc = - (next_k_data_pc + (1 << alignment) - 1) & (-1 << alignment); - fix_current_label_address (next_k_data_pc); - } - else - { - next_data_pc = (next_data_pc + (1 << alignment) - 1) & (-1 << alignment); - fix_current_label_address (next_data_pc); - } -} - - -void -set_data_alignment (int alignment) -{ - if (auto_alignment) - align_data (alignment); -} - - -void -enable_data_alignment () -{ - auto_alignment = true; -} - - -/* Set the location (in user or kernel data space) for the next datum. */ - -void -set_data_pc (mem_addr addr) -{ - if (in_kernel) - next_k_data_pc = addr; - else - next_data_pc = addr; -} - - -/* Return the address at which the next datum will be stored. */ - -mem_addr -current_data_pc () -{ - return (DATA_PC); -} - - -/* Bump the address at which the next data will be stored by DELTA - bytes. */ - -void -increment_data_pc (int delta) -{ - if (in_kernel) - { - next_k_data_pc += delta; - if (k_data_top <= next_k_data_pc) - expand_k_data(ROUND_UP(next_k_data_pc - k_data_top + 1, 64*K)); - } - else - { - next_data_pc += delta; - if (data_top <= next_data_pc) - expand_data(ROUND_UP(next_data_pc - data_top + 1, 64*K)); - } -} - - -/* Process a .extern NAME SIZE directive. */ - -void -extern_directive (char *name, int size) -{ - label *sym = make_label_global (name); - - if (!bare_machine - && !sym->gp_flag // Not already a global symbol - && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE - && next_gp_item_addr + size < gp_midpoint + 32*K) - { - sym->gp_flag = 1; - sym->addr = next_gp_item_addr; - next_gp_item_addr += size; - } -} - - -/* Process a .lcomm NAME SIZE directive. */ - -void -lcomm_directive (char *name, int size) -{ - if (!bare_machine - && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE - && next_gp_item_addr + size < gp_midpoint + 32*K) - { - label *sym = record_label (name, next_gp_item_addr, 1); - sym->gp_flag = 1; - - next_gp_item_addr += size; - /* Don't need to initialize since memory starts with 0's */ - } - else - { - (void)record_label (name, next_data_pc, 1); - - for ( ; size > 0; size --) - { - store_byte (0); - } - } -} - - -/* Process a .ascii STRING or .asciiz STRING directive. */ - -void -store_string (char *string, int length, bool null_terminate) -{ - for ( ; length > 0; string ++, length --) { - store_byte (*string); - } - if (null_terminate) - { - store_byte (0); - } -} - - -/* Process a .byte EXPR directive. */ - -void -store_byte (int value) -{ - set_mem_byte (DATA_PC, value); - increment_data_pc (1); -} - - -/* Process a .half EXPR directive. */ - -void -store_half (int value) -{ - if ((DATA_PC & 0x1) != 0) - { -#ifdef SPIM_BIGENDIAN - store_byte ((value >> 8) & 0xff); - store_byte (value & 0xff); -#else - store_byte (value & 0xff); - store_byte ((value >> 8) & 0xff); -#endif - } - else - { - set_mem_half (DATA_PC, value); - increment_data_pc (BYTES_PER_WORD / 2); - } -} - - -/* Process a .word EXPR directive. */ - -void -store_word (int value) -{ - if ((DATA_PC & 0x3) != 0) - { -#ifdef SPIM_BIGENDIAN - store_half ((value >> 16) & 0xffff); - store_half (value & 0xffff); -#else - store_half (value & 0xffff); - store_half ((value >> 16) & 0xffff); -#endif - } - else - { - set_mem_word (DATA_PC, value); - increment_data_pc (BYTES_PER_WORD); - } -} - - -/* Process a .double EXPR directive. */ - -void -store_double (double *value) -{ - if ((DATA_PC & 0x7) != 0) - { - store_word (* ((mem_word *) value)); - store_word (* (((mem_word *) value) + 1)); - } - else - { - set_mem_word (DATA_PC, *((mem_word *) value)); - increment_data_pc (BYTES_PER_WORD); - set_mem_word (DATA_PC, *(((mem_word *) value) + 1)); - increment_data_pc (BYTES_PER_WORD); - } -} - - -/* Process a .float EXPR directive. */ - -void -store_float (double *value) -{ - float val = (float)*value; - float *vp = &val; - - if ((DATA_PC & 0x3) != 0) - { - store_half (*(mem_word *) vp & 0xffff); - store_half ((*(mem_word *) vp >> 16) & 0xffff); - } - else - { - set_mem_word (DATA_PC, *((mem_word *) vp)); - increment_data_pc (BYTES_PER_WORD); - } -} diff --git a/spim-jsspim/CPU/data.h b/spim-jsspim/CPU/data.h deleted file mode 100755 index c058f88..0000000 --- a/spim-jsspim/CPU/data.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to code to manipulate data segment directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -void align_data (int alignment); -mem_addr current_data_pc (); -void data_begins_at_point (mem_addr addr); -void enable_data_alignment (); -void end_of_assembly_file (); -void extern_directive (char *name, int size); -void increment_data_pc (int value); -void k_data_begins_at_point (mem_addr addr); -void lcomm_directive (char *name, int size); -void set_data_alignment (int); -void set_data_pc (mem_addr addr); -void set_text_pc (mem_addr addr); -void store_byte (int value); -void store_double (double *value); -void store_float (double *value); -void store_half (int value); -void store_string (char *string, int length, bool null_terminate); -void store_word (int value); -void user_kernel_data_segment (bool to_kernel); diff --git a/spim-jsspim/CPU/display-utils.cpp b/spim-jsspim/CPU/display-utils.cpp deleted file mode 100755 index 12ee33a..0000000 --- a/spim-jsspim/CPU/display-utils.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* SPIM S20 MIPS simulator. - Utilities for displaying machine contents. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "data.h" -#include "reg.h" -#include "mem.h" -#include "run.h" -#include "sym-tbl.h" - - -char* int_reg_names[32] = - {"r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"}; - - -static mem_addr format_partial_line (str_stream *ss, mem_addr addr); - - -/* Write to the stream the contents of the machine's registers, in a wide - variety of formats. */ - -void -format_registers (str_stream *ss, int print_gpr_hex, int print_fpr_hex) -{ - int i; - char *grstr, *fpstr; - char *grfill, *fpfill; - - ss_printf (ss, " PC = %08x ", PC); - ss_printf (ss, "EPC = %08x ", CP0_EPC); - ss_printf (ss, " Cause = %08x ", CP0_Cause); - ss_printf (ss, " BadVAddr= %08x\n", CP0_BadVAddr); - ss_printf (ss, " Status = %08x ", CP0_Status); - ss_printf (ss, "HI = %08x ", HI); - ss_printf (ss, " LO = %08x\n", LO); - - if (print_gpr_hex) - grstr = "R%-2d (%2s) = %08x", grfill = " "; - else - grstr = "R%-2d (%2s) = %-10d", grfill = " "; - - ss_printf (ss, "\t\t\t\t General Registers\n"); - for (i = 0; i < 8; i++) - { - ss_printf (ss, grstr, i, int_reg_names[i], R[i]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+8, int_reg_names[i+8], R[i+8]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+16, int_reg_names[i+16], R[i+16]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+24, int_reg_names[i+24], R[i+24]); - ss_printf (ss, "\n"); - } - - ss_printf (ss, "\n FIR = %08x ", FIR); - ss_printf (ss, " FCSR = %08x ", FCSR); - ss_printf (ss, " FCCR = %08x ", FCCR); - ss_printf (ss, " FEXR = %08x\n", FEXR); - ss_printf (ss, " FENR = %08x\n", FENR); - - ss_printf (ss, "\t\t\t Double Floating Point Registers\n"); - - if (print_fpr_hex) - fpstr = "FP%-2d=%08x,%08x", fpfill = " "; - else - fpstr = "FP%-2d = %#-13.6g", fpfill = " "; - - if (print_fpr_hex) - for (i = 0; i < 4; i += 1) - { - int *r1, *r2; - - /* Use pointers to cast to ints without invoking float->int conversion - so we can just print the bits. */ - r1 = (int *)&FPR[i]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)&FPR[i+4]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+8, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)&FPR[i+8]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+16, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)&FPR[i+12]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+24, *r1, *r2); - ss_printf (ss, "\n"); - } - else for (i = 0; i < 4; i += 1) - { - ss_printf (ss, fpstr, 2*i, FPR[i]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+8, FPR[i+4]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+16, FPR[i+8]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+24, FPR[i+12]); - ss_printf (ss, "\n"); - } - - if (print_fpr_hex) - fpstr = "FP%-2d=%08x", fpfill = " "; - else - fpstr = "FP%-2d = %#-13.6g", fpfill = " "; - - ss_printf (ss, "\t\t\t Single Floating Point Registers\n"); - - if (print_fpr_hex) - for (i = 0; i < 8; i += 1) - { - /* Use pointers to cast to ints without invoking float->int conversion - so we can just print the bits. */ - ss_printf (ss, fpstr, i, *(int *)&FPR_S(i)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+8, *(int *)&FPR_S(i+8)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+16, *(int *)&FPR_S(i+16)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+24, *(int *)&FPR_S(i+24)); - ss_printf (ss, "\n"); - } - else for (i = 0; i < 8; i += 1) - { - ss_printf (ss, fpstr, i, FPR_S(i)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+8, FPR_S(i+8)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+16, FPR_S(i+16)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+24, FPR_S(i+24)); - ss_printf (ss, "\n"); - } -} - - - -/* Write to the stream a printable representation of the instructions in - memory addresses: FROM...TO. */ - -void -format_insts (str_stream *ss, mem_addr from, mem_addr to) -{ - instruction *inst; - mem_addr i; - - for (i = from; i < to; i += 4) - { - inst = read_mem_inst (i); - if (inst != NULL) - { - format_an_inst (ss, inst, i); - } - } -} - - -/* Write to the stream a printable representation of the data and stack - segments. */ - -void -format_data_segs (str_stream *ss) -{ - ss_printf (ss, "\tDATA\n"); - format_mem (ss, DATA_BOT, data_top); - - ss_printf (ss, "\n\tSTACK\n"); - format_mem (ss, ROUND_DOWN (R[29], BYTES_PER_WORD), STACK_TOP); - - ss_printf (ss, "\n\tKERNEL DATA\n"); - format_mem (ss, K_DATA_BOT, k_data_top); -} - - -#define BYTES_PER_LINE (4*BYTES_PER_WORD) - - -/* Write to the stream a printable representation of the data in memory - address: FROM...TO. */ - -void -format_mem (str_stream *ss, mem_addr from, mem_addr to) -{ - mem_word val; - mem_addr i = ROUND_UP (from, BYTES_PER_WORD); - int j; - - i = format_partial_line (ss, i); - - for ( ; i < to; ) - { - /* Count consecutive zero words */ - for (j = 0; (i + (uint32) j * BYTES_PER_WORD) < to; j += 1) - { - val = read_mem_word (i + (uint32) j * BYTES_PER_WORD); - if (val != 0) - { - break; - } - } - - if (j >= 4) - { - /* Block of 4 or more zero memory words: */ - ss_printf (ss, "[0x%08x]...[0x%08x] 0x00000000\n", - i, - i + (uint32) j * BYTES_PER_WORD); - - i = i + (uint32) j * BYTES_PER_WORD; - i = format_partial_line (ss, i); - } - else - { - /* Fewer than 4 zero words, print them on a single line: */ - ss_printf (ss, "[0x%08x] ", i); - do - { - val = read_mem_word (i); - ss_printf (ss, " 0x%08x", (unsigned int)val); - i += BYTES_PER_WORD; - } - while (i % BYTES_PER_LINE != 0); - - ss_printf (ss, "\n"); - } - } -} - - -/* Write to the stream a text line containing a fraction of a - quadword. Return the address after the last one written. */ - -static mem_addr -format_partial_line (str_stream *ss, mem_addr addr) -{ - if ((addr % BYTES_PER_LINE) != 0) - { - ss_printf (ss, "[0x%08x] ", addr); - - for (; (addr % BYTES_PER_LINE) != 0; addr += BYTES_PER_WORD) - { - mem_word val = read_mem_word (addr); - ss_printf (ss, " 0x%08x", (unsigned int)val); - } - - ss_printf (ss, "\n"); - } - - return addr; -} diff --git a/spim-jsspim/CPU/dump_ops.cpp b/spim-jsspim/CPU/dump_ops.cpp deleted file mode 100644 index 873acf3..0000000 --- a/spim-jsspim/CPU/dump_ops.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* SPIM S20 MIPS simulator. - Dump the op.h file in a readable format to allow checking of encodings. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include - -typedef struct inst_t -{ - char *opcode; - - union - { - unsigned int x; - struct - { - unsigned int funct:6; - unsigned int pad:10; - unsigned int rt:5; - unsigned int rs:5; - unsigned int op:6; - } f; - }; -} inst; - - -#define OP(a, b, c, d) {a, d}, - -inst ops [] = { -#include "op.h" -}; - - -int -compare_ops (inst *p1, inst *p2) -{ - if (p1->f.op < p2->f.op) - return (-1); - else if (p1->f.op > p2->f.op) - return (1); - else - { - if (p1->f.rs < p2->f.rs) - return (-1); - else if (p1->f.rs > p2->f.rs) - return (1); - else - { - if (p1->f.rt < p2->f.rt) - return (-1); - else if (p1->f.rt > p2->f.rt) - return (1); - else - { - if (p1->f.funct < p2->f.funct) - return (-1); - else if (p1->f.funct > p2->f.funct) - return (1); - else - return 0; - } - } - } -} - - -main (int argc, char** argv) -{ - /* Remove pseudo ops (opcode == -1) from table */ - int empty, next; - for (empty = 0, next = 0; next < (sizeof(ops) / sizeof(ops[0])); next += 1) - { - if (-1 == ops[next].x) - { - } - else - { - ops[empty] = ops[next]; - empty += 1; - } - } - - /* Radix sort instructions by field: op, rs, rt, funct */ - qsort (ops, empty, sizeof(ops[0]), compare_ops); - - /* Print related instructions in groups */ - int i; - for (i = 0; i < empty; i += 1) - { - if (0 < i && ops[i - 1].f.op != ops[i].f.op) - printf ("\n"); - - printf ("%10s op=%2d rs=%2d rt=%2d funct=%02x 0x%08x\n", - ops[i].opcode, - ops[i].f.op, - ops[i].f.rs, - ops[i].f.rt, - ops[i].f.funct, - ops[i].x); - } -} diff --git a/spim-jsspim/CPU/exceptions.s b/spim-jsspim/CPU/exceptions.s deleted file mode 100755 index 1abc5c4..0000000 --- a/spim-jsspim/CPU/exceptions.s +++ /dev/null @@ -1,195 +0,0 @@ -# SPIM S20 MIPS simulator. -# The default exception handler for spim. -# -# Copyright (c) 1990-2010, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -# Define the exception handling code. This must go first! - - .kdata -__m1_: .asciiz " Exception " -__m2_: .asciiz " occurred and ignored\n" -__e0_: .asciiz " [Interrupt] " -__e1_: .asciiz " [TLB]" -__e2_: .asciiz " [TLB]" -__e3_: .asciiz " [TLB]" -__e4_: .asciiz " [Address error in inst/data fetch] " -__e5_: .asciiz " [Address error in store] " -__e6_: .asciiz " [Bad instruction address] " -__e7_: .asciiz " [Bad data address] " -__e8_: .asciiz " [Error in syscall] " -__e9_: .asciiz " [Breakpoint] " -__e10_: .asciiz " [Reserved instruction] " -__e11_: .asciiz "" -__e12_: .asciiz " [Arithmetic overflow] " -__e13_: .asciiz " [Trap] " -__e14_: .asciiz "" -__e15_: .asciiz " [Floating point] " -__e16_: .asciiz "" -__e17_: .asciiz "" -__e18_: .asciiz " [Coproc 2]" -__e19_: .asciiz "" -__e20_: .asciiz "" -__e21_: .asciiz "" -__e22_: .asciiz " [MDMX]" -__e23_: .asciiz " [Watch]" -__e24_: .asciiz " [Machine check]" -__e25_: .asciiz "" -__e26_: .asciiz "" -__e27_: .asciiz "" -__e28_: .asciiz "" -__e29_: .asciiz "" -__e30_: .asciiz " [Cache]" -__e31_: .asciiz "" -__excp: .word __e0_, __e1_, __e2_, __e3_, __e4_, __e5_, __e6_, __e7_, __e8_, __e9_ - .word __e10_, __e11_, __e12_, __e13_, __e14_, __e15_, __e16_, __e17_, __e18_, - .word __e19_, __e20_, __e21_, __e22_, __e23_, __e24_, __e25_, __e26_, __e27_, - .word __e28_, __e29_, __e30_, __e31_ -s1: .word 0 -s2: .word 0 - -# This is the exception handler code that the processor runs when -# an exception occurs. It only prints some information about the -# exception, but can server as a model of how to write a handler. -# -# Because we are running in the kernel, we can use $k0/$k1 without -# saving their old values. - -# This is the exception vector address for MIPS-1 (R2000): -# .ktext 0x80000080 -# This is the exception vector address for MIPS32: - .ktext 0x80000180 -# Select the appropriate one for the mode in which SPIM is compiled. - .set noat - move $k1 $at # Save $at - .set at - sw $v0 s1 # Not re-entrant and we can't trust $sp - sw $a0 s2 # But we need to use these registers - - mfc0 $k0 $13 # Cause register - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - - # Print information about exception. - # - li $v0 4 # syscall 4 (print_str) - la $a0 __m1_ - syscall - - li $v0 1 # syscall 1 (print_int) - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - syscall - - li $v0 4 # syscall 4 (print_str) - andi $a0 $k0 0x3c - lw $a0 __excp($a0) - nop - syscall - - bne $k0 0x18 ok_pc # Bad PC exception requires special checks - nop - - mfc0 $a0 $14 # EPC - andi $a0 $a0 0x3 # Is EPC word-aligned? - beq $a0 0 ok_pc - nop - - li $v0 10 # Exit on really bad PC - syscall - -ok_pc: - li $v0 4 # syscall 4 (print_str) - la $a0 __m2_ - syscall - - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - bne $a0 0 ret # 0 means exception was an interrupt - nop - -# Interrupt-specific code goes here! -# Don't skip instruction at EPC since it has not executed. - - -ret: -# Return from (non-interrupt) exception. Skip offending instruction -# at EPC to avoid infinite loop. -# - mfc0 $k0 $14 # Bump EPC register - addiu $k0 $k0 4 # Skip faulting instruction - # (Need to handle delayed branch case here) - mtc0 $k0 $14 - - -# Restore registers and reset procesor state -# - lw $v0 s1 # Restore other registers - lw $a0 s2 - - .set noat - move $at $k1 # Restore $at - .set at - - mtc0 $0 $13 # Clear Cause register - - mfc0 $k0 $12 # Set Status register - ori $k0 0x1 # Interrupts enabled - mtc0 $k0 $12 - -# Return from exception on MIPS32: - eret - -# Return sequence for MIPS-I (R2000): -# rfe # Return from exception handler - # Should be in jr's delay slot -# jr $k0 -# nop - - - -# Standard startup code. Invoke the routine "main" with arguments: -# main(argc, argv, envp) -# - .text - .globl __start -__start: - lw $a0 0($sp) # argc - addiu $a1 $sp 4 # argv - addiu $a2 $a1 4 # envp - sll $v0 $a0 2 - addu $a2 $a2 $v0 - jal main - nop - - li $v0 10 - syscall # syscall 10 (exit) - - .globl __eoth -__eoth: diff --git a/spim-jsspim/CPU/inst.cpp b/spim-jsspim/CPU/inst.cpp deleted file mode 100755 index 0f7e1c5..0000000 --- a/spim-jsspim/CPU/inst.cpp +++ /dev/null @@ -1,1638 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to build assembly instructions and resolve symbolic labels. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser.h" -#include "scanner.h" -#include "parser_yacc.h" -#include "data.h" - - -/* Local functions: */ - -static int compare_pair_value (name_val_val *p1, name_val_val *p2); -static void format_imm_expr (str_stream *ss, imm_expr *expr, int base_reg); -static void i_type_inst_full_word (int opcode, int rt, int rs, imm_expr *expr, - int value_known, int32 value); -static void inst_cmp (instruction *inst1, instruction *inst2); -static instruction *make_r_type_inst (int opcode, int rd, int rs, int rt); -static instruction *mk_i_inst (int32 value, int opcode, int rs, int rt, int offset); -static instruction *mk_j_inst (int32, int opcode, int target); -static instruction *mk_r_inst (int32, int opcode, int rs, int rt, int rd, int shamt); -static void produce_immediate (imm_expr *expr, int rt, int value_known, int32 value); -static void sort_a_opcode_table (); -static void sort_i_opcode_table (); -static void sort_name_table (); - - -/* Local variables: */ - -/* True means store instructions in kernel, not user, text segment */ - -static bool in_kernel = 0; - -/* Instruction used as breakpoint by SPIM: */ - -static instruction *break_inst = NULL; - - -/* Locations for next instruction in user and kernel text segments */ - -static mem_addr next_text_pc; - -static mem_addr next_k_text_pc; - - -#define INST_PC (in_kernel ? next_k_text_pc : next_text_pc) - - - -/* Set ADDRESS at which the next instruction is stored. */ - -void -text_begins_at_point (mem_addr addr) -{ - next_text_pc = addr; -} - - -void -k_text_begins_at_point (mem_addr addr) -{ - next_k_text_pc = addr; -} - - -/* Set the location (in user or kernel text space) for the next instruction. */ - -void -set_text_pc (mem_addr addr) -{ - if (in_kernel) - next_k_text_pc = addr; - else - next_text_pc = addr; -} - - -/* Return address for next instruction, in appropriate text segment. */ - -mem_addr -current_text_pc () -{ - return (INST_PC); -} - - -/* Increment the current text segement PC. */ - -void -increment_text_pc (int delta) -{ - if (in_kernel) - { - next_k_text_pc += delta; - if (k_text_top <= next_k_text_pc) - run_error("Can't expand kernel text segment\n"); - } - else - { - next_text_pc += delta; - if (text_top <= next_text_pc) - run_error("Can't expand text segment\n"); - } -} - - -/* If FLAG is true, next instruction goes to kernel text segment, - otherwise it goes to user segment. */ - -void -user_kernel_text_segment (bool to_kernel) -{ - in_kernel = to_kernel; -} - - -/* Store an INSTRUCTION in memory at the next location. */ - -void -store_instruction (instruction *inst) -{ - if (data_dir) - { - store_word (inst_encode (inst)); - free_inst (inst); - } - else if (text_dir) - { - exception_occurred = 0; - set_mem_inst (INST_PC, inst); - if (exception_occurred) - error ("Invalid address (0x%08x) for instruction\n", INST_PC); - else - increment_text_pc (BYTES_PER_WORD); - if (inst != NULL) - { - SET_SOURCE (inst, source_line ()); - if (ENCODING (inst) == 0) - SET_ENCODING (inst, inst_encode (inst)); - } - } -} - - - -void -i_type_inst_free (int opcode, int rt, int rs, imm_expr *expr) -{ - i_type_inst (opcode, rt, rs, expr); - free (expr); -} - - -/* Produce an immediate instruction with the OPCODE, RT, RS, and IMM - fields. NB, because the immediate value may not fit in the field, - this routine may produce more than one instruction. On the bare - machine, we resolve symbolic address, but they better produce values - that fit into instruction's immediate field. */ - -void -i_type_inst (int opcode, int rt, int rs, imm_expr *expr) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_EXPR (inst, copy_imm_expr (expr)); - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* Evaluate the instruction's expression. */ - int32 value = eval_imm_expr (expr); - - if (!bare_machine - && (((opcode == Y_ADDI_OP - || opcode == Y_ADDIU_OP - || opcode == Y_SLTI_OP - || opcode == Y_SLTIU_OP - || opcode == Y_TEQI_OP - || opcode == Y_TGEI_OP - || opcode == Y_TGEIU_OP - || opcode == Y_TLTI_OP - || opcode == Y_TLTIU_OP - || opcode == Y_TNEI_OP - || (opcode_is_load_store (opcode) && expr->bits == 0)) - // Sign-extended immediate values: - ? ((value & 0xffff8000) != 0 && (value & 0xffff8000) != 0xffff8000) - // Not sign-extended: - : (value & 0xffff0000) != 0))) - { - // Non-immediate value - free_inst (inst); - i_type_inst_full_word (opcode, rt, rs, expr, 1, value); - return; - } - else - resolve_a_label (expr->symbol, inst); - } - else if (bare_machine || expr->bits != 0) - /* Don't know expression's value, but only needed upper/lower 16-bits - anyways. */ - record_inst_uses_symbol (inst, expr->symbol); - else - { - /* Don't know the expressions's value and want all of its bits, - so assume that it will not produce a small result and generate - sequence for 32 bit value. */ - free_inst (inst); - - i_type_inst_full_word (opcode, rt, rs, expr, 0, 0); - return; - } - - store_instruction (inst); -} - - -/* The immediate value for an instruction will (or may) not fit in 16 bits. - Build the value from its piece with separate instructions. */ - -static void -i_type_inst_full_word (int opcode, int rt, int rs, imm_expr *expr, - int value_known, int32 value) -{ - if (opcode_is_load_store (opcode)) - { - int32 offset; - - if (expr->symbol != NULL - && expr->symbol->gp_flag - && rs == 0 - && (int32)IMM_MIN <= (offset = expr->symbol->addr + expr->offset) - && offset <= (int32)IMM_MAX) - { - i_type_inst_free (opcode, rt, REG_GP, make_imm_expr (offset, NULL, false)); - } - else if (value_known) - { - int low, high; - - high = (value >> 16) & 0xffff; - low = value & 0xffff; - - if (!(high == 0 && !(low & 0x8000)) && - !(high == 0xffff && (low & 0x8000))) - { - /* Some of high 16 bits are non-zero */ - if (low & 0x8000) - { - /* Adjust high 16, since load sign-extends low 16*/ - high += 1; - } - - i_type_inst_free (Y_LUI_OP, 1, 0, const_imm_expr (high)); - if (rs != 0) /* Base register */ - { - r_type_inst (Y_ADDU_OP, 1, 1, rs); - } - i_type_inst_free (opcode, rt, 1, lower_bits_of_expr (const_imm_expr (low))); - } - else - { - /* Special case, sign-extension of low 16 bits sets high to 0xffff */ - i_type_inst_free (opcode, rt, rs, const_imm_expr (low)); - } - } - else - { - /* Use $at */ - /* Need to adjust if lower bits are negative */ - i_type_inst_free (Y_LUI_OP, 1, 0, upper_bits_of_expr (expr)); - if (rs != 0) /* Base register */ - { - r_type_inst (Y_ADDU_OP, 1, 1, rs); - } - i_type_inst_free (opcode, rt, 1, lower_bits_of_expr (expr)); - } - } - else if (opcode_is_branch (opcode)) - { - /* This only allows branches +/- 32K, which is not correct! */ - i_type_inst_free (opcode, rt, rs, lower_bits_of_expr (expr)); - } - else - /* Computation instruction */ - { - int offset; - - if (expr->symbol != NULL - && expr->symbol->gp_flag && rs == 0 - && (int32)IMM_MIN <= (offset = expr->symbol->addr + expr->offset) - && offset <= (int32)IMM_MAX) - { - i_type_inst_free ((opcode == Y_LUI_OP ? Y_ADDIU_OP : opcode), - rt, REG_GP, make_imm_expr (offset, NULL, false)); - } - else - { - /* Use $at */ - if ((opcode == Y_ORI_OP - || opcode == Y_ADDI_OP - || opcode == Y_ADDIU_OP - || opcode == Y_LUI_OP) - && rs == 0) - { - produce_immediate(expr, rt, value_known, value); - } - else - { - produce_immediate(expr, 1, value_known, value); - r_type_inst (imm_op_to_op (opcode), rt, rs, 1); - } - } - } -} - - -static void -produce_immediate (imm_expr *expr, int rt, int value_known, int32 value) -{ - if (value_known && (value & 0xffff) == 0) - { - i_type_inst_free (Y_LUI_OP, rt, 0, upper_bits_of_expr (expr)); - } - else if (value_known && (value & 0xffff0000) == 0) - { - i_type_inst_free (Y_ORI_OP, rt, 0, lower_bits_of_expr (expr)); - } - else - { - i_type_inst_free (Y_LUI_OP, 1, 0, upper_bits_of_expr (expr)); - i_type_inst_free (Y_ORI_OP, rt, 1, lower_bits_of_expr(expr)); - } -} - - -/* Return a jump-type instruction with the given OPCODE and TARGET - fields. NB, even the immediate value may not fit in the field, this - routine will not produce more than one instruction. */ - -void -j_type_inst (int opcode, imm_expr *target) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE(inst, opcode); - target->offset = 0; /* Not PC relative */ - target->pc_relative = false; - SET_EXPR (inst, copy_imm_expr (target)); - if (target->symbol == NULL || SYMBOL_IS_DEFINED (target->symbol)) - resolve_a_label (target->symbol, inst); - else - record_inst_uses_symbol (inst, target->symbol); - store_instruction (inst); -} - - -/* Return a register-type instruction with the given OPCODE, RD, RS, and RT - fields. */ - -static instruction * -make_r_type_inst (int opcode, int rd, int rs, int rt) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE(inst, opcode); - SET_RS(inst, rs); - SET_RT(inst, rt); - SET_RD(inst, rd); - SHAMT(inst) = 0; - return (inst); -} - - -/* Return a register-type instruction with the given OPCODE, RD, RS, and RT - fields. */ - -void -r_type_inst (int opcode, int rd, int rs, int rt) -{ - store_instruction (make_r_type_inst (opcode, rd, rs, rt)); -} - - -/* Return a register-type instruction with the given OPCODE, FD, FS, and FT - fields. */ - -void -r_co_type_inst (int opcode, int fd, int fs, int ft) -{ - instruction *inst = make_r_type_inst (opcode, fs, 0, ft); - SET_FD (inst, fd); - store_instruction (inst); -} - - -/* Return a register-shift instruction with the given OPCODE, RD, RT, and - SHAMT fields.*/ - -void -r_sh_type_inst (int opcode, int rd, int rt, int shamt) -{ - instruction *inst = make_r_type_inst (opcode, rd, 0, rt); - SET_SHAMT(inst, shamt & 0x1f); - store_instruction (inst); -} - - -/* Return a floating-point compare instruction with the given OPCODE, - FS, FT, and CC fields.*/ - -void -r_cond_type_inst (int opcode, int fs, int ft, int cc) -{ - instruction *inst = make_r_type_inst (opcode, fs, 0, ft); - SET_FD(inst, cc << 2); - switch (opcode) - { - case Y_C_EQ_D_OP: - case Y_C_EQ_S_OP: - { - SET_COND(inst, COND_EQ); - break; - } - - case Y_C_LE_D_OP: - case Y_C_LE_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_EQ); - break; - } - - case Y_C_LT_D_OP: - case Y_C_LT_S_OP: - { - SET_COND(inst, COND_IN | COND_LT); - break; - } - - case Y_C_NGE_D_OP: - case Y_C_NGE_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_UN); - break; - } - - case Y_C_NGLE_D_OP: - case Y_C_NGLE_S_OP: - { - SET_COND(inst, COND_IN | COND_UN); - break; - } - - case Y_C_NGL_D_OP: - case Y_C_NGL_S_OP: - { - SET_COND(inst, COND_IN | COND_EQ | COND_UN); - break; - } - - case Y_C_NGT_D_OP: - case Y_C_NGT_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_EQ | COND_UN); - break; - } - - case Y_C_OLT_D_OP: - case Y_C_OLT_S_OP: - { - SET_COND(inst, COND_LT); - break; - } - - case Y_C_OLE_D_OP: - case Y_C_OLE_S_OP: - { - SET_COND(inst, COND_LT | COND_EQ); - break; - } - - case Y_C_SEQ_D_OP: - case Y_C_SEQ_S_OP: - { - SET_COND(inst, COND_IN | COND_EQ); - break; - } - - case Y_C_SF_D_OP: - case Y_C_SF_S_OP: - { - SET_COND(inst, COND_IN); - break; - } - - case Y_C_F_D_OP: - case Y_C_F_S_OP: - { - SET_COND(inst, 0); - break; - } - - case Y_C_UEQ_D_OP: - case Y_C_UEQ_S_OP: - { - SET_COND(inst, COND_EQ | COND_UN); - break; - } - - case Y_C_ULT_D_OP: - case Y_C_ULT_S_OP: - { - SET_COND(inst, COND_LT | COND_UN); - break; - } - - case Y_C_ULE_D_OP: - case Y_C_ULE_S_OP: - { - SET_COND(inst, COND_LT | COND_EQ | COND_UN); - break; - } - - case Y_C_UN_D_OP: - case Y_C_UN_S_OP: - { - SET_COND(inst, COND_UN); - break; - } - } - store_instruction (inst); -} - - -/* Make and return a deep copy of INST. */ - -instruction * -copy_inst (instruction *inst) -{ - instruction *new_inst = (instruction *) xmalloc (sizeof (instruction)); - - *new_inst = *inst; - /*memcpy ((void*)new_inst, (void*)inst , sizeof (instruction));*/ - SET_EXPR (new_inst, copy_imm_expr (EXPR (inst))); - return (new_inst); -} - - -void -free_inst (instruction *inst) -{ - if (inst != break_inst) - /* Don't free the breakpoint insructions since we only have one. */ - { - if (EXPR (inst)) - free (EXPR (inst)); - free (inst); - } -} - - - -/* Maintain a table mapping from opcode to instruction name and - instruction type. - - Table must be sorted before first use since its entries are - alphabetical on name, not ordered by opcode. */ - - -/* Sort all instruction table before first use. */ - -void -initialize_inst_tables () -{ - sort_name_table (); - sort_i_opcode_table (); - sort_a_opcode_table (); -} - - -/* Map from opcode -> name/type. */ - -static name_val_val name_tbl [] = { -#undef OP -#define OP(NAME, OPCODE, TYPE, R_OPCODE) {NAME, OPCODE, TYPE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the opcode value). */ - -static void -sort_name_table () -{ - qsort (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - -/* Compare the VALUE1 field of two NAME_VAL_VAL entries in the format - required by qsort. */ - -static int -compare_pair_value (name_val_val *p1, name_val_val *p2) -{ - if (p1->value1 < p2->value1) - return (-1); - else if (p1->value1 > p2->value1) - return (1); - else - return (0); -} - - -/* Print the instruction stored at the memory ADDRESS. */ - -void -print_inst (mem_addr addr) -{ - char* inst_str = inst_to_string (addr); - write_output (message_out, inst_str); - free (inst_str); -} - - -char* -inst_to_string(mem_addr addr) -{ - str_stream ss; - instruction *inst; - - exception_occurred = 0; - inst = read_mem_inst (addr); - - if (exception_occurred) - { - error ("Can't print instruction not in text segment (0x%08x)\n", addr); - return ""; - } - - ss_init (&ss); - format_an_inst (&ss, inst, addr); - return ss_to_string (&ss); -} - - -void -format_an_inst (str_stream *ss, instruction *inst, mem_addr addr) -{ - name_val_val *entry; - int line_start = ss_length (ss); - - if (inst_is_breakpoint (addr)) - { - delete_breakpoint (addr); - ss_printf (ss, "*"); - format_an_inst (ss, read_mem_inst (addr), addr); - add_breakpoint (addr); - return; - } - - ss_printf (ss, "[0x%08x]\t", addr); - if (inst == NULL) - { - ss_printf (ss, "\n"); - return; - } - - entry = map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - OPCODE (inst)); - if (entry == NULL) - { - ss_printf (ss, "\n", OPCODE (inst)); - return; - } - - ss_printf (ss, "0x%08x %s", (uint32)ENCODING (inst), entry->name); - switch (entry->value2) - { - case BC_TYPE_INST: - ss_printf (ss, "%d %d", CC (inst), IDISP (inst)); - break; - - case B1_TYPE_INST: - ss_printf (ss, " $%d %d", RS (inst), IDISP (inst)); - break; - - case I1s_TYPE_INST: - ss_printf (ss, " $%d, %d", RS (inst), IMM (inst)); - break; - - case I1t_TYPE_INST: - ss_printf (ss, " $%d, %d", RT (inst), IMM (inst)); - break; - - case I2_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RT (inst), RS (inst), IMM (inst)); - break; - - case B2_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RS (inst), RT (inst), IDISP (inst)); - break; - - case I2a_TYPE_INST: - ss_printf (ss, " $%d, %d($%d)", RT (inst), IMM (inst), BASE (inst)); - break; - - case R1s_TYPE_INST: - ss_printf (ss, " $%d", RS (inst)); - break; - - case R1d_TYPE_INST: - ss_printf (ss, " $%d", RD (inst)); - break; - - case R2td_TYPE_INST: - ss_printf (ss, " $%d, $%d", RT (inst), RD (inst)); - break; - - case R2st_TYPE_INST: - ss_printf (ss, " $%d, $%d", RS (inst), RT (inst)); - break; - - case R2ds_TYPE_INST: - ss_printf (ss, " $%d, $%d", RD (inst), RS (inst)); - break; - - case R2sh_TYPE_INST: - if (ENCODING (inst) == 0) - { - ss_erase (ss, 3); /* zap sll */ - ss_printf (ss, "nop"); - } - else - ss_printf (ss, " $%d, $%d, %d", RD (inst), RT (inst), SHAMT (inst)); - break; - - case R3_TYPE_INST: - ss_printf (ss, " $%d, $%d, $%d", RD (inst), RS (inst), RT (inst)); - break; - - case R3sh_TYPE_INST: - ss_printf (ss, " $%d, $%d, $%d", RD (inst), RT (inst), RS (inst)); - break; - - case FP_I2a_TYPE_INST: - ss_printf (ss, " $f%d, %d($%d)", FT (inst), IMM (inst), BASE (inst)); - break; - - case FP_R2ds_TYPE_INST: - ss_printf (ss, " $f%d, $f%d", FD (inst), FS (inst)); - break; - - case FP_R2ts_TYPE_INST: - ss_printf (ss, " $%d, $f%d", RT (inst), FS (inst)); - break; - - case FP_CMP_TYPE_INST: - if (FD (inst) == 0) - ss_printf (ss, " $f%d, $f%d", FS (inst), FT (inst)); - else - ss_printf (ss, " %d, $f%d, $f%d", FD (inst) >> 2, FS (inst), FT (inst)); - break; - - case FP_R3_TYPE_INST: - ss_printf (ss, " $f%d, $f%d, $f%d", FD (inst), FS (inst), FT (inst)); - break; - - case MOVC_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RD (inst), RS (inst), RT (inst) >> 2); - break; - - case FP_MOVC_TYPE_INST: - ss_printf (ss, " $f%d, $f%d, %d", FD (inst), FS (inst), CC (inst)); - break; - - case J_TYPE_INST: - ss_printf (ss, " 0x%08x", TARGET (inst) << 2); - break; - - case NOARG_TYPE_INST: - break; - - default: - fatal_error ("Unknown instruction type in print_inst\n"); - } - - if (EXPR (inst) != NULL && EXPR (inst)->symbol != NULL) - { - ss_printf (ss, " ["); - if (opcode_is_load_store (OPCODE (inst))) - format_imm_expr (ss, EXPR (inst), BASE (inst)); - else - format_imm_expr (ss, EXPR (inst), -1); - ss_printf (ss, "]"); - } - - if (SOURCE (inst) != NULL) - { - /* Comment is source line text of current line. */ - int gap_length = 57 - (ss_length (ss) - line_start); - for ( ; 0 < gap_length; gap_length -= 1) - { - ss_printf (ss, " "); - } - - ss_printf (ss, "; "); - ss_printf (ss, "%s", SOURCE (inst)); - } - - ss_printf (ss, "\n"); -} - - - -/* Return true if SPIM OPCODE (e.g. Y_...) represents a conditional - branch. */ - -bool -opcode_is_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1F_OP: - case Y_BC1FL_OP: - case Y_BC1T_OP: - case Y_BC1TL_OP: - case Y_BC2F_OP: - case Y_BC2FL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - case Y_BEQ_OP: - case Y_BEQL_OP: - case Y_BEQZ_POP: - case Y_BGE_POP: - case Y_BGEU_POP: - case Y_BGEZ_OP: - case Y_BGEZAL_OP: - case Y_BGEZALL_OP: - case Y_BGEZL_OP: - case Y_BGT_POP: - case Y_BGTU_POP: - case Y_BGTZ_OP: - case Y_BGTZL_OP: - case Y_BLE_POP: - case Y_BLEU_POP: - case Y_BLEZ_OP: - case Y_BLEZL_OP: - case Y_BLT_POP: - case Y_BLTU_POP: - case Y_BLTZ_OP: - case Y_BLTZAL_OP: - case Y_BLTZALL_OP: - case Y_BLTZL_OP: - case Y_BNE_OP: - case Y_BNEL_OP: - case Y_BNEZ_POP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE represents a nullified (e.g., Y_...L_OP) - conditional branch. */ - -bool -opcode_is_nullified_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1FL_OP: - case Y_BC1TL_OP: - case Y_BC2FL_OP: - case Y_BC2TL_OP: - case Y_BEQL_OP: - case Y_BGEZALL_OP: - case Y_BGEZL_OP: - case Y_BGTZL_OP: - case Y_BLEZL_OP: - case Y_BLTZALL_OP: - case Y_BLTZL_OP: - case Y_BNEL_OP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE (e.g. Y_...) represents a conditional - branch on a true condition. */ - -bool -opcode_is_true_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1T_OP: - case Y_BC1TL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE (e.g. Y_...) is a direct unconditional - branch (jump). */ - -bool -opcode_is_jump (int opcode) -{ - switch (opcode) - { - case Y_J_OP: - case Y_JAL_OP: - return true; - - default: - return false; - } -} - -/* Return true if SPIM OPCODE (e.g. Y_...) is a load or store. */ - -bool -opcode_is_load_store (int opcode) -{ - switch (opcode) - { - case Y_LB_OP: - case Y_LBU_OP: - case Y_LH_OP: - case Y_LHU_OP: - case Y_LL_OP: - case Y_LDC1_OP: - case Y_LDC2_OP: - case Y_LW_OP: - case Y_LWC1_OP: - case Y_LWC2_OP: - case Y_LWL_OP: - case Y_LWR_OP: - case Y_SB_OP: - case Y_SC_OP: - case Y_SH_OP: - case Y_SDC1_OP: - case Y_SDC2_OP: - case Y_SW_OP: - case Y_SWC1_OP: - case Y_SWC2_OP: - case Y_SWL_OP: - case Y_SWR_OP: - return true; - - default: - return false; - } -} - - -/* Return true if a breakpoint is set at ADDR. */ - -bool -inst_is_breakpoint (mem_addr addr) -{ - if (break_inst == NULL) - break_inst = make_r_type_inst (Y_BREAK_OP, 1, 0, 0); - - return (read_mem_inst (addr) == break_inst); -} - - -/* Set a breakpoint at ADDR and return the old instruction. If the - breakpoint cannot be set, return NULL. */ - -instruction * -set_breakpoint (mem_addr addr) -{ - instruction *old_inst; - - if (break_inst == NULL) - break_inst = make_r_type_inst (Y_BREAK_OP, 1, 0, 0); - - exception_occurred = 0; - old_inst = read_mem_inst (addr); - if (old_inst == break_inst) - return (NULL); - - set_mem_inst (addr, break_inst); - if (exception_occurred) - return (NULL); - else - return (old_inst); -} - - - -/* An immediate expression has the form: SYMBOL +/- IOFFSET, where either - part may be omitted. */ - -/* Make and return a new immediate expression */ - -imm_expr * -make_imm_expr (int offs, char *sym, bool is_pc_relative) -{ - imm_expr *expr = (imm_expr *) xmalloc (sizeof (imm_expr)); - - expr->offset = offs; - expr->bits = 0; - expr->pc_relative = is_pc_relative; - if (sym != NULL) - expr->symbol = lookup_label (sym); - else - expr->symbol = NULL; - return (expr); -} - - -/* Return a shallow copy of the EXPRESSION. */ - -imm_expr * -copy_imm_expr (imm_expr *old_expr) -{ - imm_expr *expr = (imm_expr *) xmalloc (sizeof (imm_expr)); - - *expr = *old_expr; - /*memcpy ((void*)expr, (void*)old_expr, sizeof (imm_expr));*/ - return (expr); -} - - -/* Return a shallow copy of an EXPRESSION that only uses the upper - sixteen bits of the expression's value. */ - -imm_expr * -upper_bits_of_expr (imm_expr *old_expr) -{ - imm_expr *expr = copy_imm_expr (old_expr); - - expr->bits = 1; - return (expr); -} - - -/* Return a shallow copy of the EXPRESSION that only uses the lower - sixteen bits of the expression's value. */ - -imm_expr * -lower_bits_of_expr (imm_expr *old_expr) -{ - imm_expr *expr = copy_imm_expr (old_expr); - - expr->bits = -1; - return (expr); -} - - -/* Return an instruction expression for a constant VALUE. */ - -imm_expr * -const_imm_expr (int32 value) -{ - return (make_imm_expr (value, NULL, false)); -} - - -/* Return a shallow copy of the EXPRESSION with the offset field - incremented by the given amount. */ - -imm_expr * -incr_expr_offset (imm_expr *expr, int32 value) -{ - imm_expr *new_expr = copy_imm_expr (expr); - - new_expr->offset += value; - return (new_expr); -} - - -/* Return the value of the EXPRESSION. */ - -int32 -eval_imm_expr (imm_expr *expr) -{ - int32 value; - - if (expr->symbol == NULL) - value = expr->offset; - else if (SYMBOL_IS_DEFINED (expr->symbol)) - { - value = expr->offset + expr->symbol->addr; - } - else - { - error ("Evaluated undefined symbol: %s\n", expr->symbol->name); - value = 0; - } - if (expr->bits > 0) - return ((value >> 16) & 0xffff); /* Use upper bits of result */ - else if (expr->bits < 0) - return (value & 0xffff); /* Use lower bits */ - else - return (value); -} - - -/* Print the EXPRESSION. */ - -static void -format_imm_expr (str_stream *ss, imm_expr *expr, int base_reg) -{ - if (expr->symbol != NULL) - { - ss_printf (ss, "%s", expr->symbol->name); - } - - if (expr->pc_relative) - ss_printf (ss, "-0x%08x", (unsigned int)-expr->offset); - else if (expr->offset < -10) - ss_printf (ss, "-%d (-0x%08x)", -expr->offset, (unsigned int)-expr->offset); - else if (expr->offset > 10) - ss_printf (ss, "+%d (0x%08x)", expr->offset, (unsigned int)expr->offset); - - if (base_reg != -1 && expr->symbol != NULL && - (expr->offset > 10 || expr->offset < -10)) - { - if (expr->offset == 0 && base_reg != 0) - ss_printf (ss, "+0"); - - if (expr->offset != 0 || base_reg != 0) - ss_printf (ss, "($%d)", base_reg); - } -} - - -/* Return true if the EXPRESSION is a constant 0. */ - -bool -is_zero_imm (imm_expr *expr) -{ - return (expr->offset == 0 && expr->symbol == NULL); -} - - - -/* Return an address expression of the form SYMBOL +/- IOFFSET (REGISTER). - Any of the three parts may be omitted. */ - -addr_expr * -make_addr_expr (int offs, char *sym, int reg_no) -{ - addr_expr *expr = (addr_expr *) xmalloc (sizeof (addr_expr)); - label *lab; - - if (reg_no == 0 && sym != NULL && (lab = lookup_label (sym))->gp_flag) - { - expr->reg_no = REG_GP; - expr->imm = make_imm_expr (offs + lab->addr - gp_midpoint, NULL, false); - } - else - { - expr->reg_no = (unsigned char)reg_no; - expr->imm = make_imm_expr (offs, (sym ? str_copy (sym) : sym), false); - } - return (expr); -} - - -imm_expr * -addr_expr_imm (addr_expr *expr) -{ - return (expr->imm); -} - - -int -addr_expr_reg (addr_expr *expr) -{ - return (expr->reg_no); -} - - - -/* Map between a SPIM instruction and the binary representation of the - instruction. */ - - -/* Maintain a table mapping from internal opcode (i_opcode) to actual - opcode (a_opcode). Table must be sorted before first use since its - entries are alphabetical on name, not ordered by opcode. */ - - -/* Map from internal opcode -> real opcode */ - -static name_val_val i_opcode_tbl [] = { -#undef OP -#define OP(NAME, I_OPCODE, TYPE, A_OPCODE) {NAME, I_OPCODE, (int)A_OPCODE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the interal opcode value). */ - -static void -sort_i_opcode_table () -{ - qsort (i_opcode_tbl, - sizeof (i_opcode_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - -#define REGS(R,O) (((R) & 0x1f) << O) - - -int32 -inst_encode (instruction *inst) -{ - int32 a_opcode = 0; - name_val_val *entry; - - if (inst == NULL) - return (0); - - entry = map_int_to_name_val_val (i_opcode_tbl, - sizeof (i_opcode_tbl) / sizeof (name_val_val), - OPCODE (inst)); - if (entry == NULL) - return 0; - - a_opcode = entry->value2; - entry = map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - OPCODE (inst)); - - switch (entry->value2) - { - case BC_TYPE_INST: - return (a_opcode - | REGS (CC (inst) << 2, 16) - | (IOFFSET (inst) & 0xffff)); - - case B1_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | (IOFFSET (inst) & 0xffff)); - - case I1s_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | (IMM (inst) & 0xffff)); - - case I1t_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | (IMM (inst) & 0xffff)); - - case I2_TYPE_INST: - case B2_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | (IMM (inst) & 0xffff)); - - case I2a_TYPE_INST: - return (a_opcode - | REGS (BASE (inst), 21) - | REGS (RT (inst), 16) - | (IOFFSET (inst) & 0xffff)); - - case R1s_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21)); - - case R1d_TYPE_INST: - return (a_opcode - | REGS (RD (inst), 11)); - - case R2td_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case R2st_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16)); - - case R2ds_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RD (inst), 11)); - - case R2sh_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (RD (inst), 11) - | REGS (SHAMT (inst), 6)); - - case R3_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case R3sh_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case FP_I2a_TYPE_INST: - return (a_opcode - | REGS (BASE (inst), 21) - | REGS (RT (inst), 16) - | (IOFFSET (inst) & 0xffff)); - - case FP_R2ds_TYPE_INST: - return (a_opcode - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case FP_R2ts_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (FS (inst), 11)); - - case FP_CMP_TYPE_INST: - return (a_opcode - | REGS (FT (inst), 16) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6) - | COND (inst)); - - case FP_R3_TYPE_INST: - return (a_opcode - | REGS (FT (inst), 16) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case MOVC_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case FP_MOVC_TYPE_INST: - return (a_opcode - | REGS (CC (inst), 18) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case J_TYPE_INST: - return (a_opcode - | TARGET (inst)); - - case NOARG_TYPE_INST: - return (a_opcode); - - default: - fatal_error ("Unknown instruction type in inst_encoding\n"); - return (0); /* Not reached */ - } -} - - -/* Maintain a table mapping from actual opcode to interal opcode. - Table must be sorted before first use since its entries are - alphabetical on name, not ordered by opcode. */ - - -/* Map from internal opcode -> real opcode */ - -static name_val_val a_opcode_tbl [] = { -#undef OP -#define OP(NAME, I_OPCODE, TYPE, A_OPCODE) {NAME, (int)A_OPCODE, (int)I_OPCODE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the interal opcode value). */ - -static void -sort_a_opcode_table () -{ - qsort (a_opcode_tbl, - sizeof (a_opcode_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - - -instruction * -inst_decode (int32 val) -{ - int32 a_opcode = val & 0xfc000000; - name_val_val *entry; - int32 i_opcode; - - /* Field classes: (opcode is continued in other part of instruction): */ - if (a_opcode == 0 || a_opcode == 0x70000000) /* SPECIAL or SPECIAL2 */ - a_opcode |= (val & 0x3f); - else if (a_opcode == 0x04000000) /* REGIMM */ - a_opcode |= (val & 0x001f0000); - else if (a_opcode == 0x40000000) /* COP0 */ - a_opcode |= (val & 0x03e00000) | (val & 0x1f); - else if (a_opcode == 0x44000000) /* COP1 */ - { - a_opcode |= (val & 0x03e00000); - if ((val & 0xff000000) == 0x45000000) - a_opcode |= (val & 0x00010000); /* BC1f/t */ - else - a_opcode |= (val & 0x3f); - } - else if (a_opcode == 0x48000000 /* COPz */ - || a_opcode == 0x4c000000) - a_opcode |= (val & 0x03e00000); - - - entry = map_int_to_name_val_val (a_opcode_tbl, - sizeof (a_opcode_tbl) / sizeof (name_val_val), - a_opcode); - if (entry == NULL) - return (mk_r_inst (val, 0, 0, 0, 0, 0)); /* Invalid inst */ - - i_opcode = entry->value2; - - switch (map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - i_opcode)->value2) - { - case BC_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case B1_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), 0, val & 0xffff)); - - case I1s_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), 0, val & 0xffff)); - - case I1t_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case I2_TYPE_INST: - case B2_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case I2a_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case R1s_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), 0, 0, 0)); - - case R1d_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, 0, BIN_RD(val), 0)); - - case R2td_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_RD(val), 0)); - - case R2st_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), 0, 0)); - - case R2ds_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), 0, BIN_RD(val), 0)); - - case R2sh_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_RD(val), BIN_SA(val))); - - case R3_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case R3sh_TYPE_INST: - return(mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case FP_I2a_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_BASE(val), BIN_FT(val), val & 0xffff)); - - case FP_R2ds_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_FS(val), 0, BIN_FD(val), 0)); - - case FP_R2ts_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_FS(val), 0)); - - case FP_CMP_TYPE_INST: - { - instruction *inst = mk_r_inst (val, i_opcode, BIN_FS (val), BIN_FT (val), BIN_FD(val), 0); - SET_COND (inst, val & 0xf); - return (inst); - } - - case FP_R3_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_FS(val), BIN_FT(val), BIN_FD(val), 0)); - - case MOVC_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case FP_MOVC_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_FS(val), BIN_RT(val), BIN_FD(val), 0)); - - case J_TYPE_INST: - return (mk_j_inst (val, i_opcode, val & 0x2ffffff)); - - - case NOARG_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, 0, 0, 0)); - - default: - return (mk_r_inst (val, 0, 0, 0, 0, 0)); /* Invalid inst */ - } -} - - -static instruction * -mk_r_inst (int32 val, int opcode, int rs, int rt, int rd, int shamt) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_RD (inst, rd); - SET_SHAMT (inst, shamt); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - - -static instruction * -mk_i_inst (int32 val, int opcode, int rs, int rt, int offset) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_IOFFSET (inst, offset); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - -static instruction * -mk_j_inst (int32 val, int opcode, int target) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_TARGET (inst, target); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - - - -/* Code to test encode/decode of instructions. */ - -void -test_assembly (instruction *inst) -{ - instruction *new_inst = inst_decode (inst_encode (inst)); - - inst_cmp (inst, new_inst); - free_inst (new_inst); -} - - -static void -inst_cmp (instruction *inst1, instruction *inst2) -{ - static str_stream ss; - - ss_clear (&ss); - if (memcmp (inst1, inst2, sizeof (instruction) - 4) != 0) - { - ss_printf (&ss, "=================== Not Equal ===================\n"); - format_an_inst (&ss, inst1, 0); - format_an_inst (&ss, inst2, 0); - ss_printf (&ss, "=================== Not Equal ===================\n"); - } -} diff --git a/spim-jsspim/CPU/inst.h b/spim-jsspim/CPU/inst.h deleted file mode 100755 index 809bff1..0000000 --- a/spim-jsspim/CPU/inst.h +++ /dev/null @@ -1,273 +0,0 @@ -/* SPIM S20 MIPS simulator. - Description of a SPIM S20 instruction. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Represenation of the expression that produce a value for an instruction's - immediate field. Immediates have the form: label +/- offset. */ - -typedef struct immexpr -{ - int offset; /* Offset from symbol */ - struct lab *symbol; /* Symbolic label */ - short bits; /* > 0 => 31..16, < 0 => 15..0 */ - bool pc_relative; /* => offset from label in code */ -} imm_expr; - - -/* Representation of the expression that produce an address for an - instruction. Address have the form: label +/- offset (register). */ - -typedef struct addrexpr -{ - unsigned char reg_no; /* Register number */ - imm_expr *imm; /* The immediate part */ -} addr_expr; - - - -/* Representation of an instruction. Store the instruction fields in an - overlapping manner similar to the real encoding (but not identical, to - speed decoding in C code, as opposed to hardware).. */ - -typedef struct inst_s -{ - short opcode; - - union - { - /* R-type or I-type: */ - struct - { - unsigned char rs; - unsigned char rt; - - union - { - short imm; - - struct - { - unsigned char rd; - unsigned char shamt; - } r; - } r_i; - } r_i; - - /* J-type: */ - mem_addr target; - } r_t; - - int32 encoding; - imm_expr *expr; - char *source_line; -} instruction; - - -#define OPCODE(INST) (INST)->opcode -#define SET_OPCODE(INST, VAL) (INST)->opcode = (short)(VAL) - - -#define RS(INST) (INST)->r_t.r_i.rs -#define SET_RS(INST, VAL) (INST)->r_t.r_i.rs = (unsigned char)(VAL) - -#define RT(INST) (INST)->r_t.r_i.rt -#define SET_RT(INST, VAL) (INST)->r_t.r_i.rt = (unsigned char)(VAL) - -#define RD(INST) (INST)->r_t.r_i.r_i.r.rd -#define SET_RD(INST, VAL) (INST)->r_t.r_i.r_i.r.rd = (unsigned char)(VAL) - - -#define FS(INST) RD(INST) -#define SET_FS(INST, VAL) SET_RD(INST, VAL) - -#define FT(INST) RT(INST) -#define SET_FT(INST, VAL) SET_RT(INST, VAL) - -#define FD(INST) SHAMT(INST) -#define SET_FD(INST, VAL) SET_SHAMT(INST, VAL) - - -#define SHAMT(INST) (INST)->r_t.r_i.r_i.r.shamt -#define SET_SHAMT(INST, VAL) (INST)->r_t.r_i.r_i.r.shamt = (unsigned char)(VAL) - -#define IMM(INST) (INST)->r_t.r_i.r_i.imm -#define SET_IMM(INST, VAL) (INST)->r_t.r_i.r_i.imm = (short)(VAL) - - -#define BASE(INST) RS(INST) -#define SET_BASE(INST, VAL) SET_RS(INST, VAL) - -#define IOFFSET(INST) IMM(INST) -#define SET_IOFFSET(INST, VAL) SET_IMM(INST, VAL) -#define IDISP(INST) (SIGN_EX (IOFFSET (INST) << 2)) - - -#define COND(INST) RS(INST) -#define SET_COND(INST, VAL) SET_RS(INST, VAL) - -#define CC(INST) (RT(INST) >> 2) -#define ND(INST) ((RT(INST) & 0x2) >> 1) -#define TF(INST) (RT(INST) & 0x1) - - -#define TARGET(INST) (INST)->r_t.target -#define SET_TARGET(INST, VAL) (INST)->r_t.target = (mem_addr)(VAL) - -#define ENCODING(INST) (INST)->encoding -#define SET_ENCODING(INST, VAL) (INST)->encoding = (int32)(VAL) - -#define EXPR(INST) (INST)->expr -#define SET_EXPR(INST, VAL) (INST)->expr = (imm_expr*)(VAL) - -#define SOURCE(INST) (INST)->source_line -#define SET_SOURCE(INST, VAL) (INST)->source_line = (char *)(VAL) - - -#define COND_UN 0x1 -#define COND_EQ 0x2 -#define COND_LT 0x4 -#define COND_IN 0x8 - -/* Minimum and maximum values that fit in instruction's imm field */ -#define IMM_MIN 0xffff8000 -#define IMM_MAX 0x00007fff - -#define UIMM_MIN (unsigned)0 -#define UIMM_MAX ((unsigned)((1<<16)-1)) - - - -/* Raise an exception! */ - -extern int exception_occurred; - -#define RAISE_EXCEPTION(EXCODE, MISC) \ - { \ - raise_exception(EXCODE); \ - MISC; \ - } \ - - -#define RAISE_INTERRUPT(LEVEL) \ - { \ - /* Set IP (pending) bit for interrupt level. */ \ - CP0_Cause |= (1 << ((LEVEL) + 8)); \ - } \ - -#define CLEAR_INTERRUPT(LEVEL) \ - { \ - /* Clear IP (pending) bit for interrupt level. */ \ - CP0_Cause &= ~(1 << ((LEVEL) + 8)); \ - } \ - -/* Recognized exceptions: */ - -#define ExcCode_Int 0 /* Interrupt */ -#define ExcCode_Mod 1 /* TLB modification (not implemented) */ -#define ExcCode_TLBL 2 /* TLB exception (not implemented) */ -#define ExcCode_TLBS 3 /* TLB exception (not implemented) */ -#define ExcCode_AdEL 4 /* Address error (load/fetch) */ -#define ExcCode_AdES 5 /* Address error (store) */ -#define ExcCode_IBE 6 /* Bus error, instruction fetch */ -#define ExcCode_DBE 7 /* Bus error, data reference */ -#define ExcCode_Sys 8 /* Syscall exception */ -#define ExcCode_Bp 9 /* Breakpoint exception */ -#define ExcCode_RI 10 /* Reserve instruction */ -#define ExcCode_CpU 11 /* Coprocessor unusable */ -#define ExcCode_Ov 12 /* Arithmetic overflow */ -#define ExcCode_Tr 13 /* Trap */ -#define ExcCode_FPE 15 /* Floating point */ -#define ExcCode_C2E 18 /* Coprocessor 2 (not impelemented) */ -#define ExcCode_MDMX 22 /* MDMX unusable (not implemented) */ -#define ExcCode_WATCH 23 /* Reference to Watch (not impelemented) */ -#define ExcCode_MCheck 24 /* Machine check (not implemented) */ -#define ExcCode_CacheErr 30 /* Cache error (not impelemented) */ - - - -/* Fields in binary representation of instructions: */ - -#define BIN_REG(V,O) (((V) >> O) & 0x1f) -#define BIN_RS(V) (BIN_REG(V, 21)) -#define BIN_RT(V) (BIN_REG(V, 16)) -#define BIN_RD(V) (BIN_REG(V, 11)) -#define BIN_SA(V) (BIN_REG(V, 6)) - -#define BIN_BASE(V) (BIN_REG(V, 21)) -#define BIN_FT(V) (BIN_REG(V, 16)) -#define BIN_FS(V) (BIN_REG(V, 11)) -#define BIN_FD(V) (BIN_REG(V, 6)) - - - -/* Exported functions: */ - -imm_expr *addr_expr_imm (addr_expr *expr); -int addr_expr_reg (addr_expr *expr); -imm_expr *const_imm_expr (int32 value); -imm_expr *copy_imm_expr (imm_expr *old_expr); -instruction *copy_inst (instruction *inst); -mem_addr current_text_pc (); -int32 eval_imm_expr (imm_expr *expr); -void format_an_inst (str_stream *ss, instruction *inst, mem_addr addr); -void free_inst (instruction *inst); -void i_type_inst (int opcode, int rt, int rs, imm_expr *expr); -void i_type_inst_free (int opcode, int rt, int rs, imm_expr *expr); -void increment_text_pc (int delta); -imm_expr *incr_expr_offset (imm_expr *expr, int32 value); -void initialize_inst_tables (); -instruction *inst_decode (int32 value); -int32 inst_encode (instruction *inst); -bool inst_is_breakpoint (mem_addr addr); -void j_type_inst (int opcode, imm_expr *target); -void k_text_begins_at_point (mem_addr addr); -imm_expr *lower_bits_of_expr (imm_expr *old_expr); -addr_expr *make_addr_expr (int offs, char *sym, int reg_no); -imm_expr *make_imm_expr (int offs, char *sym, bool is_pc_relative); -bool opcode_is_branch (int opcode); -bool opcode_is_nullified_branch (int opcode); -bool opcode_is_true_branch (int opcode); -bool opcode_is_jump (int opcode); -bool opcode_is_load_store (int opcode); -void print_inst (mem_addr addr); -char* inst_to_string (mem_addr addr); -void r_co_type_inst (int opcode, int fd, int fs, int ft); -void r_cond_type_inst (int opcode, int fs, int ft, int cc); -void r_sh_type_inst (int opcode, int rd, int rt, int shamt); -void r_type_inst (int opcode, int rd, int rs, int rt); -void raise_exception(int excode); -instruction *set_breakpoint (mem_addr addr); -void store_instruction (instruction *inst); -void text_begins_at_point (mem_addr addr); -imm_expr *upper_bits_of_expr (imm_expr *old_expr); -void user_kernel_text_segment (bool to_kernel); -bool is_zero_imm (imm_expr *expr); diff --git a/spim-jsspim/CPU/mem.cpp b/spim-jsspim/CPU/mem.cpp deleted file mode 100755 index 0d17111..0000000 --- a/spim-jsspim/CPU/mem.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to create, maintain and access memory. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" - -/* Exported Variables: */ - -reg_word R[R_LENGTH]; -reg_word HI, LO; -int HI_present, LO_present; -mem_addr PC, nPC; -double *FPR; /* Dynamically allocate so overlay */ -float *FGR; /* is possible */ -int *FWR; /* is possible */ -reg_word CCR[4][32], CPR[4][32]; - -instruction **text_seg; -bool text_modified; /* => text segment was written */ -mem_addr text_top; -mem_word *data_seg; -bool data_modified; /* => a data segment was written */ -short *data_seg_h; /* Points to same vector as DATA_SEG */ -BYTE_TYPE *data_seg_b; /* Ditto */ -mem_addr data_top; -mem_addr gp_midpoint; /* Middle of $gp area */ -mem_word *stack_seg; -short *stack_seg_h; /* Points to same vector as STACK_SEG */ -BYTE_TYPE *stack_seg_b; /* Ditto */ -mem_addr stack_bot; -instruction **k_text_seg; -mem_addr k_text_top; -mem_word *k_data_seg; -short *k_data_seg_h; -BYTE_TYPE *k_data_seg_b; -mem_addr k_data_top; - - -/* Local functions: */ - -static mem_word bad_mem_read (mem_addr addr, int mask); -static void bad_mem_write (mem_addr addr, mem_word value, int mask); -static instruction *bad_text_read (mem_addr addr); -static void bad_text_write (mem_addr addr, instruction *inst); -static void free_instructions (instruction **inst, int n); -static mem_word read_memory_mapped_IO (mem_addr addr); -static void write_memory_mapped_IO (mem_addr addr, mem_word value); - - -/* Local variables: */ - -static int32 data_size_limit, stack_size_limit, k_data_size_limit; - - - -/* Memory is allocated in five chunks: - text, data, stack, kernel text, and kernel data. - - The arrays are independent and have different semantics. - - text is allocated from 0x400000 up and only contains INSTRUCTIONs. - It does not expand. - - data is allocated from 0x10000000 up. It can be extended by the - SBRK system call. Programs can only read and write this segment. - - stack grows from 0x7fffefff down. It is automatically extended. - Programs can only read and write this segment. - - k_text is like text, except its is allocated from 0x80000000 up. - - k_data is like data, but is allocated from 0x90000000 up. - - Both kernel text and kernel data can only be accessed in kernel mode. -*/ - -/* The text segments contain pointers to instructions, not actual - instructions, so they must be allocated large enough to hold as many - pointers as there would be instructions (the two differ on machines in - which pointers are not 32 bits long). The following calculations round - up in case size is not a multiple of BYTES_PER_WORD. */ - -#define BYTES_TO_INST(N) (((N) + BYTES_PER_WORD - 1) / BYTES_PER_WORD * sizeof(instruction*)) - - -void -make_memory (int text_size, int data_size, int data_limit, - int stack_size, int stack_limit, int k_text_size, - int k_data_size, int k_data_limit) -{ - if (data_size <= 65536) - data_size = 65536; - data_size = ROUND_UP(data_size, BYTES_PER_WORD); /* Keep word aligned */ - - if (text_seg == NULL) - text_seg = (instruction **) xmalloc (BYTES_TO_INST(text_size)); - else - { - free_instructions (text_seg, (text_top - TEXT_BOT) / BYTES_PER_WORD); - text_seg = (instruction **) realloc (text_seg, BYTES_TO_INST(text_size)); - } - memclr (text_seg, BYTES_TO_INST(text_size)); - text_top = TEXT_BOT + text_size; - - data_size = ROUND_UP(data_size, BYTES_PER_WORD); /* Keep word aligned */ - if (data_seg == NULL) - data_seg = (mem_word *) xmalloc (data_size); - else - data_seg = (mem_word *) realloc (data_seg, data_size); - memclr (data_seg, data_size); - data_seg_b = (BYTE_TYPE *) data_seg; - data_seg_h = (short *) data_seg; - data_top = DATA_BOT + data_size; - data_size_limit = data_limit; - - stack_size = ROUND_UP(stack_size, BYTES_PER_WORD); /* Keep word aligned */ - if (stack_seg == NULL) - stack_seg = (mem_word *) xmalloc (stack_size); - else - stack_seg = (mem_word *) realloc (stack_seg, stack_size); - memclr (stack_seg, stack_size); - stack_seg_b = (BYTE_TYPE *) stack_seg; - stack_seg_h = (short *) stack_seg; - stack_bot = STACK_TOP - stack_size; - stack_size_limit = stack_limit; - - if (k_text_seg == NULL) - k_text_seg = (instruction **) xmalloc (BYTES_TO_INST(k_text_size)); - else - { - free_instructions (k_text_seg, - (k_text_top - K_TEXT_BOT) / BYTES_PER_WORD); - k_text_seg = (instruction **) realloc(k_text_seg, - BYTES_TO_INST(k_text_size)); - } - memclr (k_text_seg, BYTES_TO_INST(k_text_size)); - k_text_top = K_TEXT_BOT + k_text_size; - - k_data_size = ROUND_UP(k_data_size, BYTES_PER_WORD); /* Keep word aligned */ - if (k_data_seg == NULL) - k_data_seg = (mem_word *) xmalloc (k_data_size); - else - k_data_seg = (mem_word *) realloc (k_data_seg, k_data_size); - memclr (k_data_seg, k_data_size); - k_data_seg_b = (BYTE_TYPE *) k_data_seg; - k_data_seg_h = (short *) k_data_seg; - k_data_top = K_DATA_BOT + k_data_size; - k_data_size_limit = k_data_limit; - - text_modified = true; - data_modified = true; -} - - -/* Free the storage used by the old instructions in memory. */ - -static void -free_instructions (instruction **inst, int n) -{ - for ( ; n > 0; n --, inst ++) - if (*inst) - free_inst (*inst); -} - - -/* Expand the data segment by adding N bytes. */ - -void -expand_data (int addl_bytes) -{ - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = data_top - DATA_BOT; - int new_size = old_size + delta; - BYTE_TYPE *p; - - if ((addl_bytes < 0) || (new_size > data_size_limit)) - { - error ("Can't expand data segment by %d bytes to %d bytes\n", - addl_bytes, new_size); - run_error ("Use -ldata # with # > %d\n", new_size); - } - data_seg = (mem_word *) realloc (data_seg, new_size); - if (data_seg == NULL) - fatal_error ("realloc failed in expand_data\n"); - - data_seg_b = (BYTE_TYPE *) data_seg; - data_seg_h = (short *) data_seg; - data_top += delta; - - /* Zero new memory */ - for (p = data_seg_b + old_size; p < data_seg_b + new_size; ) - *p ++ = 0; -} - - -/* Expand the stack segment by adding N bytes. Can't use REALLOC - since it copies from bottom of memory blocks and stack grows down from - top of its block. */ - -void -expand_stack (int addl_bytes) -{ - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = STACK_TOP - stack_bot; - int new_size = old_size + MAX (delta, old_size); - mem_word *new_seg; - mem_word *po, *pn; - - if ((addl_bytes < 0) || (new_size > stack_size_limit)) - { - run_error ("Can't expand stack segment by %d bytes to %d bytes.\nUse -lstack # with # > %d\n", - addl_bytes, new_size, new_size); - } - - new_seg = (mem_word *) xmalloc (new_size); - memset(new_seg, 0, new_size); - - po = stack_seg + (old_size / BYTES_PER_WORD - 1); - pn = new_seg + (new_size / BYTES_PER_WORD - 1); - for ( ; po >= stack_seg ; ) *pn -- = *po --; - - free (stack_seg); - stack_seg = new_seg; - stack_seg_b = (BYTE_TYPE *) stack_seg; - stack_seg_h = (short *) stack_seg; - stack_bot -= (new_size - old_size); -} - - -/* Expand the kernel data segment by adding N bytes. */ - -void -expand_k_data (int addl_bytes) -{ - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = k_data_top - K_DATA_BOT; - int new_size = old_size + delta; - BYTE_TYPE *p; - - if ((addl_bytes < 0) || (new_size > k_data_size_limit)) - { - run_error ("Can't expand kernel data segment by %d bytes to %d bytes.\nUse -lkdata # with # > %d\n", - addl_bytes, new_size, new_size); - } - k_data_seg = (mem_word *) realloc (k_data_seg, new_size); - if (k_data_seg == NULL) - fatal_error ("realloc failed in expand_k_data\n"); - - k_data_seg_b = (BYTE_TYPE *) k_data_seg; - k_data_seg_h = (short *) k_data_seg; - k_data_top += delta; - - /* Zero new memory */ - for (p = k_data_seg_b + old_size / BYTES_PER_WORD; - p < k_data_seg_b + new_size / BYTES_PER_WORD; ) - *p ++ = 0; -} - - - -/* Access memory */ - -void* -mem_reference(mem_addr addr) -{ - if ((addr >= TEXT_BOT) && (addr < text_top)) - return addr - TEXT_BOT + (char*) text_seg; - else if ((addr >= DATA_BOT) && (addr < data_top)) - return addr - DATA_BOT + (char*) data_seg; - else if ((addr >= stack_bot) && (addr < STACK_TOP)) - return addr - stack_bot + (char*) stack_seg; - else if ((addr >= K_TEXT_BOT) && (addr < k_text_top)) - return addr - K_TEXT_BOT + (char*) k_text_seg; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top)) - return addr - K_DATA_BOT + (char*) k_data_seg; - else - { - run_error ("Memory address out of bounds\n"); - return NULL; - } -} - - -instruction* -read_mem_inst(mem_addr addr) -{ - if ((addr >= TEXT_BOT) && (addr < text_top) && !(addr & 0x3)) - return text_seg [(addr - TEXT_BOT) >> 2]; - else if ((addr >= K_TEXT_BOT) && (addr < k_text_top) && !(addr & 0x3)) - return k_text_seg [(addr - K_TEXT_BOT) >> 2]; - else - return bad_text_read (addr); -} - - -reg_word -read_mem_byte(mem_addr addr) -{ - if ((addr >= DATA_BOT) && (addr < data_top)) - return data_seg_b [addr - DATA_BOT]; - else if ((addr >= stack_bot) && (addr < STACK_TOP)) - return stack_seg_b [addr - stack_bot]; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top)) - return k_data_seg_b [addr - K_DATA_BOT]; - else - return bad_mem_read (addr, 0); -} - - -reg_word -read_mem_half(mem_addr addr) -{ - if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x1)) - return data_seg_h [(addr - DATA_BOT) >> 1]; - else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x1)) - return stack_seg_h [(addr - stack_bot) >> 1]; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x1)) - return k_data_seg_h [(addr - K_DATA_BOT) >> 1]; - else - return bad_mem_read (addr, 0x1); -} - - -reg_word -read_mem_word(mem_addr addr) -{ - if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x3)) - return data_seg [(addr - DATA_BOT) >> 2]; - else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x3)) - return stack_seg [(addr - stack_bot) >> 2]; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x3)) - return k_data_seg [(addr - K_DATA_BOT) >> 2]; - else - return bad_mem_read (addr, 0x3); -} - - -void -set_mem_inst(mem_addr addr, instruction* inst) -{ - text_modified = true; - if ((addr >= TEXT_BOT) && (addr < text_top) && !(addr & 0x3)) - text_seg [(addr - TEXT_BOT) >> 2] = inst; - else if ((addr >= K_TEXT_BOT) && (addr < k_text_top) && !(addr & 0x3)) - k_text_seg [(addr - K_TEXT_BOT) >> 2] = inst; - else - bad_text_write (addr, inst); -} - - -void -set_mem_byte(mem_addr addr, reg_word value) -{ - data_modified = true; - if ((addr >= DATA_BOT) && (addr < data_top)) - data_seg_b [addr - DATA_BOT] = (BYTE_TYPE) value; - else if ((addr >= stack_bot) && (addr < STACK_TOP)) - stack_seg_b [addr - stack_bot] = (BYTE_TYPE) value; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top)) - k_data_seg_b [addr - K_DATA_BOT] = (BYTE_TYPE) value; - else - bad_mem_write (addr, value, 0); -} - - -void -set_mem_half(mem_addr addr, reg_word value) -{ - data_modified = true; - if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x1)) - data_seg_h [(addr - DATA_BOT) >> 1] = (short) value; - else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x1)) - stack_seg_h [(addr - stack_bot) >> 1] = (short) value; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x1)) - k_data_seg_h [(addr - K_DATA_BOT) >> 1] = (short) value; - else - bad_mem_write (addr, value, 0x1); -} - - -void -set_mem_word(mem_addr addr, reg_word value) -{ - data_modified = true; - if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x3)) - data_seg [(addr - DATA_BOT) >> 2] = (mem_word) value; - else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x3)) - stack_seg [(addr - stack_bot) >> 2] = (mem_word) value; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x3)) - k_data_seg [(addr - K_DATA_BOT) >> 2] = (mem_word) value; - else - bad_mem_write (addr, value, 0x3); -} - - -/* Handle the infrequent and erroneous cases in memory accesses. */ - -static instruction * -bad_text_read (mem_addr addr) -{ - RAISE_EXCEPTION (ExcCode_IBE, CP0_BadVAddr = addr); - return (inst_decode (0)); -} - - -static void -bad_text_write (mem_addr addr, instruction *inst) -{ - RAISE_EXCEPTION (ExcCode_IBE, CP0_BadVAddr = addr); - set_mem_word (addr, ENCODING (inst)); -} - - -static mem_word -bad_mem_read (mem_addr addr, int mask) -{ - mem_word tmp; - - if ((addr & mask) != 0) - RAISE_EXCEPTION (ExcCode_AdEL, CP0_BadVAddr = addr) - else if (addr >= TEXT_BOT && addr < text_top) - switch (mask) - { - case 0x0: - tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = (unsigned)tmp >> (8 * (3 - (addr & 0x3))); -#else - tmp = (unsigned)tmp >> (8 * (addr & 0x3)); -#endif - return (0xff & tmp); - - case 0x1: - tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = (unsigned)tmp >> (8 * (2 - (addr & 0x2))); -#else - tmp = (unsigned)tmp >> (8 * (addr & 0x2)); -#endif - return (0xffff & tmp); - - case 0x3: - { - instruction *inst = text_seg [(addr - TEXT_BOT) >> 2]; - if (inst == NULL) - return 0; - else - return (ENCODING (inst)); - } - - default: - run_error ("Bad mask (0x%x) in bad_mem_read\n", mask); - } - else if (addr > data_top - && addr < stack_bot - /* If more than 16 MB below stack, probably is bad data ref */ - && addr > stack_bot - 16*K*K) - { - /* Grow stack segment */ - expand_stack (stack_bot - addr + 4); - return (0); - } - else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP) - return (read_memory_mapped_IO (addr)); - else - /* Address out of range */ - RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr) - return (0); -} - - -static void -bad_mem_write (mem_addr addr, mem_word value, int mask) -{ - mem_word tmp; - - if ((addr & mask) != 0) - /* Unaligned address fault */ - RAISE_EXCEPTION (ExcCode_AdES, CP0_BadVAddr = addr) - else if (addr >= TEXT_BOT && addr < text_top) - { - switch (mask) - { - case 0x0: - tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = ((tmp & ~(0xff << (8 * (3 - (addr & 0x3))))) - | (value & 0xff) << (8 * (3 - (addr & 0x3)))); -#else - tmp = ((tmp & ~(0xff << (8 * (addr & 0x3)))) - | (value & 0xff) << (8 * (addr & 0x3))); -#endif - break; - - case 0x1: - tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = ((tmp & ~(0xffff << (8 * (2 - (addr & 0x2))))) - | (value & 0xffff) << (8 * (2 - (addr & 0x2)))); -#else - tmp = ((tmp & ~(0xffff << (8 * (addr & 0x2)))) - | (value & 0xffff) << (8 * (addr & 0x2))); -#endif - break; - - case 0x3: - tmp = value; - break; - - default: - tmp = 0; - run_error ("Bad mask (0x%x) in bad_mem_read\n", mask); - } - - if (text_seg [(addr - TEXT_BOT) >> 2] != NULL) - { - free_inst (text_seg[(addr - TEXT_BOT) >> 2]); - } - text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp); - - text_modified = true; - } - else if (addr > data_top - && addr < stack_bot - /* If more than 16 MB below stack, probably is bad data ref */ - && addr > stack_bot - 16*K*K) - { - /* Grow stack segment */ - expand_stack (stack_bot - addr + 4); - if (addr >= stack_bot) - { - if (mask == 0) - stack_seg_b [addr - stack_bot] = (char)value; - else if (mask == 1) - stack_seg_h [(addr - stack_bot) >> 1] = (short)value; - else - stack_seg [(addr - stack_bot) >> 2] = value; - } - else - RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr) - - data_modified = true; - } - else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP) - write_memory_mapped_IO (addr, value); - else - /* Address out of range */ - RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr) -} - - - -/* Memory-mapped IO routines. */ - -static int recv_control = 0; /* No input */ -static int recv_buffer; -static int recv_buffer_full_timer = 0; - -static int trans_control = TRANS_READY; /* Ready to write */ -static int trans_buffer; -static int trans_buffer_full_timer = 0; - - -/* Check if input is available and output is possible. If so, update the - memory-mapped control registers and buffers. */ - -void -check_memory_mapped_IO () -{ - if (recv_buffer_full_timer > 0) - { - /* Do not check for more input until this interval expires. */ - recv_buffer_full_timer -= 1; - } - else if (console_input_available ()) - { - /* Read new char into the buffer and raise an interrupt, if interrupts - are enabled for device. */ - /* assert(recv_buffer_full_timer == 0); */ - recv_buffer = get_console_char (); - recv_control |= RECV_READY; - recv_buffer_full_timer = RECV_INTERVAL; - if (recv_control & RECV_INT_ENABLE) - { - RAISE_INTERRUPT (RECV_INT_LEVEL); - } - } - - if (trans_buffer_full_timer > 0) - { - /* Do not allow output until this interval expires. */ - trans_buffer_full_timer -= 1; - } - else if (!(trans_control & TRANS_READY)) - { - /* Done writing: empty the buffer and raise an interrupt, if interrupts - are enabled for device. */ - /* assert(trans_buffer_full_timer == 0); */ - trans_control |= TRANS_READY; - if (trans_control & TRANS_INT_ENABLE) - { - RAISE_INTERRUPT (TRANS_INT_LEVEL); - } - } -} - - -/* Invoked on a write to the memory-mapped IO area. */ - -static void -write_memory_mapped_IO (mem_addr addr, mem_word value) -{ - switch (addr) - { - case TRANS_CTRL_ADDR: - /* Program can only set the interrupt enable, not ready, bit. */ - if ((value & TRANS_INT_ENABLE) != 0) - { - /* Enable interrupts: */ - trans_control |= TRANS_INT_ENABLE; - if (trans_control & TRANS_READY) - { - /* Raise interrupt on enabling a ready transmitter */ - RAISE_INTERRUPT (TRANS_INT_LEVEL); - } - } - else - { - /* Disable interrupts: */ - trans_control &= ~TRANS_INT_ENABLE; - CLEAR_INTERRUPT (TRANS_INT_LEVEL); /* Clear IP bit in Cause */ - } - break; - - case TRANS_BUFFER_ADDR: - /* Ignore write if device is not ready. */ - if ((trans_control & TRANS_READY) != 0) - { - /* Write char: */ - trans_buffer = value & 0xff; - put_console_char ((char)trans_buffer); - /* Device is busy for a while: */ - trans_control &= ~TRANS_READY; - trans_buffer_full_timer = TRANS_LATENCY; - CLEAR_INTERRUPT (TRANS_INT_LEVEL); /* Clear IP bit in Cause */ - } - break; - - case RECV_CTRL_ADDR: - /* Program can only set the interrupt enable, not ready, bit. */ - if ((value & RECV_INT_ENABLE) != 0) - { - /* Enable interrupts: */ - recv_control |= RECV_INT_ENABLE; - if (recv_control & RECV_READY) - { - /* Raise interrupt on enabling a ready receiver */ - RAISE_INTERRUPT (RECV_INT_LEVEL); - } - } - else - { - /* Disable interrupts: */ - recv_control &= ~RECV_INT_ENABLE; - CLEAR_INTERRUPT (RECV_INT_LEVEL); /* Clear IP bit in Cause */ - } - break; - - case RECV_BUFFER_ADDR: - /* Nop: program can't change buffer. */ - break; - - default: - run_error ("Write to unused memory-mapped IO address (0x%x)\n", addr); - } -} - - -/* Invoked on a read in the memory-mapped IO area. */ - -static mem_word -read_memory_mapped_IO (mem_addr addr) -{ - switch (addr) - { - case TRANS_CTRL_ADDR: - return (trans_control); - - case TRANS_BUFFER_ADDR: - return (trans_buffer & 0xff); - - case RECV_CTRL_ADDR: - return (recv_control); - - case RECV_BUFFER_ADDR: - recv_control &= ~RECV_READY; /* Buffer now empty */ - recv_buffer_full_timer = 0; - CLEAR_INTERRUPT (RECV_INT_LEVEL); /* Clear IP bit in Cause */ - return (recv_buffer & 0xff); - - default: - run_error ("Read from unused memory-mapped IO address (0x%x)\n", addr); - return (0); - } -} - - - -/* Misc. routines */ - -void -print_mem (mem_addr addr) -{ - mem_word value; - - if ((addr & 0x3) != 0) - addr &= ~0x3; /* Address must be word-aligned */ - - if (TEXT_BOT <= addr && addr < text_top) - print_inst (addr); - else if (DATA_BOT <= addr && addr < data_top) - { - value = read_mem_word (addr); - write_output (message_out, "Data seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else if (stack_bot <= addr && addr < STACK_TOP) - { - value = read_mem_word (addr); - write_output (message_out, "Stack seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else if (K_TEXT_BOT <= addr && addr < k_text_top) - print_inst (addr); - else if (K_DATA_BOT <= addr && addr < k_data_top) - { - value = read_mem_word (addr); - write_output (message_out, - "Kernel Data seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else - error ("Address 0x%08x (%d) to print_mem is out of bounds\n", addr, addr); -} diff --git a/spim-jsspim/CPU/mem.h b/spim-jsspim/CPU/mem.h deleted file mode 100755 index 018cbd6..0000000 --- a/spim-jsspim/CPU/mem.h +++ /dev/null @@ -1,161 +0,0 @@ -/* SPIM S20 MIPS simulator. - Macros for accessing memory. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* A note on directions: "Bottom" of memory is the direction of - decreasing addresses. "Top" is the direction of increasing addresses.*/ - - -/* Type of contents of a memory word. */ - -typedef int32 /*@alt unsigned int @*/ mem_word; - - -/* The text segment and boundaries. */ - -extern instruction **text_seg; - -extern bool text_modified; /* => text segment was written */ - -#define TEXT_BOT ((mem_addr) 0x400000) - -extern mem_addr text_top; - - -/* Amount to grow text segment when we run out of space for instructions. */ - -#define TEXT_CHUNK_SIZE 4096 - - -/* The data segment and boundaries. */ - -extern mem_word *data_seg; - -extern bool data_modified; /* => a data segment was written */ - -extern short *data_seg_h; /* Points to same vector as DATA_SEG */ - -#define BYTE_TYPE signed char - - -extern BYTE_TYPE *data_seg_b; /* Ditto */ - -#define DATA_BOT ((mem_addr) 0x10000000) - -extern mem_addr data_top; - -extern mem_addr gp_midpoint; /* Middle of $gp area */ - - -/* The stack segment and boundaries. */ - -extern mem_word *stack_seg; - -extern short *stack_seg_h; /* Points to same vector as STACK_SEG */ - -extern BYTE_TYPE *stack_seg_b; /* Ditto */ - -extern mem_addr stack_bot; - -/* Exclusive, but include 4K at top of stack. */ - -#define STACK_TOP ((mem_addr) 0x80000000) - - -/* The kernel text segment and boundaries. */ - -extern instruction **k_text_seg; - -#define K_TEXT_BOT ((mem_addr) 0x80000000) - -extern mem_addr k_text_top; - - -/* Kernel data segment and boundaries. */ - -extern mem_word *k_data_seg; - -extern short *k_data_seg_h; - -extern BYTE_TYPE *k_data_seg_b; - -#define K_DATA_BOT ((mem_addr) 0x90000000) - -extern mem_addr k_data_top; - - -/* Memory-mapped IO area: */ -#define MM_IO_BOT ((mem_addr) 0xffff0000) -#define MM_IO_TOP ((mem_addr) 0xffffffff) - - -/* Read from console: */ -#define RECV_CTRL_ADDR ((mem_addr) 0xffff0000) -#define RECV_BUFFER_ADDR ((mem_addr) 0xffff0004) - -#define RECV_READY 0x1 -#define RECV_INT_ENABLE 0x2 - -#define RECV_INT_LEVEL 3 /* HW Interrupt 1 */ - - -/* Write to console: */ -#define TRANS_CTRL_ADDR ((mem_addr) 0xffff0008) -#define TRANS_BUFFER_ADDR ((mem_addr) 0xffff000c) - -#define TRANS_READY 0x1 -#define TRANS_INT_ENABLE 0x2 - -#define TRANS_INT_LEVEL 2 /* HW Interrupt 0 */ - - - - -/* Exported functions: */ - -void check_memory_mapped_IO (); -void expand_data (int addl_bytes); -void expand_k_data (int addl_bytes); -void expand_stack (int addl_bytes); -void make_memory (int text_size, int data_size, int data_limit, - int stack_size, int stack_limit, int k_text_size, - int k_data_size, int k_data_limit); -void* mem_reference(mem_addr addr); -void print_mem (mem_addr addr); -instruction* read_mem_inst(mem_addr addr); -reg_word read_mem_byte(mem_addr addr); -reg_word read_mem_half(mem_addr addr); -reg_word read_mem_word(mem_addr addr); -void set_mem_inst(mem_addr addr, instruction* inst); -void set_mem_byte(mem_addr addr, reg_word value); -void set_mem_half(mem_addr addr, reg_word value); -void set_mem_word(mem_addr addr, reg_word value); diff --git a/spim-jsspim/CPU/op.h b/spim-jsspim/CPU/op.h deleted file mode 100755 index 4b46df5..0000000 --- a/spim-jsspim/CPU/op.h +++ /dev/null @@ -1,525 +0,0 @@ -/* SPIM S20 MIPS simulator. - This file describes the MIPS instructions, the assembler pseudo - instructions, the assembler pseudo-ops, and the spim commands. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Type of each entry: */ - -#define ASM_DIR 0 -#define PSEUDO_OP 1 - -#define BC_TYPE_INST 10 -#define B1_TYPE_INST 11 -#define I1s_TYPE_INST 12 -#define I1t_TYPE_INST 13 -#define I2_TYPE_INST 14 -#define B2_TYPE_INST 15 -#define I2a_TYPE_INST 16 - -#define R1s_TYPE_INST 20 -#define R1d_TYPE_INST 21 -#define R2st_TYPE_INST 22 -#define R2ds_TYPE_INST 23 -#define R2td_TYPE_INST 24 -#define R2sh_TYPE_INST 25 -#define R3_TYPE_INST 26 -#define R3sh_TYPE_INST 27 - -#define FP_I2a_TYPE_INST 30 -#define FP_R2ds_TYPE_INST 31 -#define FP_R2ts_TYPE_INST 32 -#define FP_CMP_TYPE_INST 33 -#define FP_R3_TYPE_INST 34 -#define FP_R4_TYPE_INST 35 -#define FP_MOVC_TYPE_INST 36 -#define MOVC_TYPE_INST 37 - -#define J_TYPE_INST 40 -#define NOARG_TYPE_INST 42 - - -/* Information on each keyword token that can be read by spim. Must be - sorted in alphabetical order. */ - -OP(".alias", Y_ALIAS_DIR, ASM_DIR, -1) -OP(".align", Y_ALIGN_DIR, ASM_DIR, -1) -OP(".ascii", Y_ASCII_DIR, ASM_DIR, -1) -OP(".asciiz", Y_ASCIIZ_DIR, ASM_DIR, -1) -OP(".asm0", Y_ASM0_DIR, ASM_DIR, -1) -OP(".bgnb", Y_BGNB_DIR, ASM_DIR, -1) -OP(".byte", Y_BYTE_DIR, ASM_DIR, -1) -OP(".comm", Y_COMM_DIR, ASM_DIR, -1) -OP(".data", Y_DATA_DIR, ASM_DIR, -1) -OP(".double", Y_DOUBLE_DIR, ASM_DIR, -1) -OP(".end", Y_END_DIR, ASM_DIR, -1) -OP(".endb", Y_ENDB_DIR, ASM_DIR, -1) -OP(".endr", Y_ENDR_DIR, ASM_DIR, -1) -OP(".ent", Y_ENT_DIR, ASM_DIR, -1) -OP(".err", Y_ERR_DIR, ASM_DIR, -1) -OP(".extern", Y_EXTERN_DIR, ASM_DIR, -1) -OP(".file", Y_FILE_DIR, ASM_DIR, -1) -OP(".float", Y_FLOAT_DIR, ASM_DIR, -1) -OP(".fmask", Y_FMASK_DIR, ASM_DIR, -1) -OP(".frame", Y_FRAME_DIR, ASM_DIR, -1) -OP(".globl", Y_GLOBAL_DIR, ASM_DIR, -1) -OP(".half", Y_HALF_DIR, ASM_DIR, -1) -OP(".kdata", Y_K_DATA_DIR, ASM_DIR, -1) -OP(".ktext", Y_K_TEXT_DIR, ASM_DIR, -1) -OP(".lab", Y_LABEL_DIR, ASM_DIR, -1) -OP(".lcomm", Y_LCOMM_DIR, ASM_DIR, -1) -OP(".livereg", Y_LIVEREG_DIR, ASM_DIR, -1) -OP(".loc", Y_LOC_DIR, ASM_DIR, -1) -OP(".mask", Y_MASK_DIR, ASM_DIR, -1) -OP(".noalias", Y_NOALIAS_DIR, ASM_DIR, -1) -OP(".option", Y_OPTIONS_DIR, ASM_DIR, -1) -OP(".rdata", Y_RDATA_DIR, ASM_DIR, -1) -OP(".repeat", Y_REPEAT_DIR, ASM_DIR, -1) -OP(".sdata", Y_SDATA_DIR, ASM_DIR, -1) -OP(".set", Y_SET_DIR, ASM_DIR, -1) -OP(".space", Y_SPACE_DIR, ASM_DIR, -1) -OP(".struct", Y_STRUCT_DIR, ASM_DIR, -1) -OP(".text", Y_TEXT_DIR, ASM_DIR, -1) -OP(".verstamp",Y_VERSTAMP_DIR, ASM_DIR, -1) -OP(".vreg", Y_VREG_DIR, ASM_DIR, -1) -OP(".word", Y_WORD_DIR, ASM_DIR, -1) - -OP("abs", Y_ABS_POP, PSEUDO_OP, -1) -OP("abs.d", Y_ABS_D_OP, FP_R2ds_TYPE_INST, 0x46200005) -OP("abs.ps", Y_ABS_PS_OP, FP_R2ds_TYPE_INST, 0x46600005) /* MIPS32 Rev 2 */ -OP("abs.s", Y_ABS_S_OP, FP_R2ds_TYPE_INST, 0x46000005) - -OP("add", Y_ADD_OP, R3_TYPE_INST, 0x00000020) -OP("add.d", Y_ADD_D_OP, FP_R3_TYPE_INST, 0x46200000) -OP("add.ps", Y_ADD_PS_OP, FP_R3_TYPE_INST, 0x46600000) /* MIPS32 Rev 2 */ -OP("add.s", Y_ADD_S_OP, FP_R3_TYPE_INST, 0x46000000) -OP("addi", Y_ADDI_OP, I2_TYPE_INST, 0x20000000) -OP("addiu", Y_ADDIU_OP, I2_TYPE_INST, 0x24000000) -OP("addu", Y_ADDU_OP, R3_TYPE_INST, 0x00000021) - -OP("alnv.ps", Y_ALNV_PS_OP, FP_R4_TYPE_INST, 0x4c00001e) /* MIPS32 Rev 2 */ - -OP("and", Y_AND_OP, R3_TYPE_INST, 0x00000024) -OP("andi", Y_ANDI_OP, I2_TYPE_INST, 0x30000000) - -OP("b", Y_B_POP, PSEUDO_OP, -1) -OP("bal", Y_BAL_POP, PSEUDO_OP, -1) - -OP("bc1f", Y_BC1F_OP, BC_TYPE_INST, 0x45000000) -OP("bc1fl", Y_BC1FL_OP, BC_TYPE_INST, 0x45020000) /* MIPS32 */ -OP("bc1t", Y_BC1T_OP, BC_TYPE_INST, 0x45010000) -OP("bc1tl", Y_BC1TL_OP, BC_TYPE_INST, 0x45030000) /* MIPS32 */ - -OP("bc2f", Y_BC2F_OP, BC_TYPE_INST, 0x49000000) -OP("bc2fl", Y_BC2FL_OP, BC_TYPE_INST, 0x49020000) /* MIPS32 */ -OP("bc2t", Y_BC2T_OP, BC_TYPE_INST, 0x49010000) -OP("bc2tl", Y_BC2TL_OP, BC_TYPE_INST, 0x49030000) /* MIPS32 */ - -OP("beq", Y_BEQ_OP, B2_TYPE_INST, 0x10000000) -OP("beql", Y_BEQL_OP, B2_TYPE_INST, 0x50000000) /* MIPS32 */ -OP("beqz", Y_BEQZ_POP, PSEUDO_OP, -1) -OP("bge", Y_BGE_POP, PSEUDO_OP, -1) -OP("bgeu", Y_BGEU_POP, PSEUDO_OP, -1) -OP("bgez", Y_BGEZ_OP, B1_TYPE_INST, 0x04010000) -OP("bgezal", Y_BGEZAL_OP, B1_TYPE_INST, 0x04110000) -OP("bgezall", Y_BGEZALL_OP, B1_TYPE_INST, 0x04130000) /* MIPS32 */ -OP("bgezl", Y_BGEZL_OP, B1_TYPE_INST, 0x04030000) /* MIPS32 */ -OP("bgt", Y_BGT_POP, PSEUDO_OP, -1) -OP("bgtu", Y_BGTU_POP, PSEUDO_OP, -1) -OP("bgtz", Y_BGTZ_OP, B1_TYPE_INST, 0x1c000000) -OP("bgtzl", Y_BGTZL_OP, B1_TYPE_INST, 0x5c000000) /* MIPS32 */ -OP("ble", Y_BLE_POP, PSEUDO_OP, -1) -OP("bleu", Y_BLEU_POP, PSEUDO_OP, -1) -OP("blez", Y_BLEZ_OP, B1_TYPE_INST, 0x18000000) -OP("blezl", Y_BLEZL_OP, B1_TYPE_INST, 0x58000000) /* MIPS32 */ -OP("blt", Y_BLT_POP, PSEUDO_OP, -1) -OP("bltu", Y_BLTU_POP, PSEUDO_OP, -1) -OP("bltz", Y_BLTZ_OP, B1_TYPE_INST, 0x04000000) -OP("bltzal", Y_BLTZAL_OP, B1_TYPE_INST, 0x04100000) -OP("bltzall", Y_BLTZALL_OP, B1_TYPE_INST, 0x04120000) /* MIPS32 */ -OP("bltzl", Y_BLTZL_OP, B1_TYPE_INST, 0x04020000) /* MIPS32 */ -OP("bne", Y_BNE_OP, B2_TYPE_INST, 0x14000000) -OP("bnel", Y_BNEL_OP, B2_TYPE_INST, 0x54000000) /* MIPS32 */ -OP("bnez", Y_BNEZ_POP, PSEUDO_OP, -1) - -OP("break", Y_BREAK_OP, NOARG_TYPE_INST, 0x0000000d) - -OP("c.eq.d", Y_C_EQ_D_OP, FP_CMP_TYPE_INST, 0x46200032) -OP("c.eq.ps", Y_C_EQ_PS_OP, FP_CMP_TYPE_INST, 0x46600032) /* MIPS32 Rev 2 */ -OP("c.eq.s", Y_C_EQ_S_OP, FP_CMP_TYPE_INST, 0x46000032) -OP("c.f.d", Y_C_F_D_OP, FP_CMP_TYPE_INST, 0x46200030) -OP("c.f.ps", Y_C_F_PS_OP, FP_CMP_TYPE_INST, 0x46600030) /* MIPS32 Rev 2 */ -OP("c.f.s", Y_C_F_S_OP, FP_CMP_TYPE_INST, 0x46000030) -OP("c.le.d", Y_C_LE_D_OP, FP_CMP_TYPE_INST, 0x4620003e) -OP("c.le.ps", Y_C_LE_PS_OP, FP_CMP_TYPE_INST, 0x4660003e) /* MIPS32 Rev 2 */ -OP("c.le.s", Y_C_LE_S_OP, FP_CMP_TYPE_INST, 0x4600003e) -OP("c.lt.d", Y_C_LT_D_OP, FP_CMP_TYPE_INST, 0x4620003c) -OP("c.lt.ps", Y_C_LT_PS_OP, FP_CMP_TYPE_INST, 0x4660003c) /* MIPS32 Rev 2 */ -OP("c.lt.s", Y_C_LT_S_OP, FP_CMP_TYPE_INST, 0x4600003c) -OP("c.nge.d", Y_C_NGE_D_OP, FP_CMP_TYPE_INST, 0x4620003d) -OP("c.nge.ps", Y_C_NGE_PS_OP, FP_CMP_TYPE_INST, 0x4660003d) /* MIPS32 Rev 2 */ -OP("c.nge.s", Y_C_NGE_S_OP, FP_CMP_TYPE_INST, 0x4600003d) -OP("c.ngl.d", Y_C_NGL_D_OP, FP_CMP_TYPE_INST, 0x4620003b) -OP("c.ngl.ps", Y_C_NGL_PS_OP, FP_CMP_TYPE_INST, 0x4660003b) /* MIPS32 Rev 2 */ -OP("c.ngl.s", Y_C_NGL_S_OP, FP_CMP_TYPE_INST, 0x4600003b) -OP("c.ngle.d", Y_C_NGLE_D_OP, FP_CMP_TYPE_INST, 0x46200039) -OP("c.ngle.ps", Y_C_NGLE_PS_OP, FP_CMP_TYPE_INST, 0x46600039) /* MIPS32 Rev 2 */ -OP("c.ngle.s", Y_C_NGLE_S_OP, FP_CMP_TYPE_INST, 0x46000039) -OP("c.ngt.d", Y_C_NGT_D_OP, FP_CMP_TYPE_INST, 0x4620003f) -OP("c.ngt.ps", Y_C_NGT_PS_OP, FP_CMP_TYPE_INST, 0x4660003f) /* MIPS32 Rev 2 */ -OP("c.ngt.s", Y_C_NGT_S_OP, FP_CMP_TYPE_INST, 0x4600003f) -OP("c.ole.d", Y_C_OLE_D_OP, FP_CMP_TYPE_INST, 0x46200036) -OP("c.ole.ps", Y_C_OLE_PS_OP, FP_CMP_TYPE_INST, 0x46600036) /* MIPS32 Rev 2 */ -OP("c.ole.s", Y_C_OLE_S_OP, FP_CMP_TYPE_INST, 0x46000036) -OP("c.olt.d", Y_C_OLT_D_OP, FP_CMP_TYPE_INST, 0x46200034) -OP("c.olt.ps", Y_C_OLT_PS_OP, FP_CMP_TYPE_INST, 0x46600034) /* MIPS32 Rev 2 */ -OP("c.olt.s", Y_C_OLT_S_OP, FP_CMP_TYPE_INST, 0x46000034) -OP("c.seq.d", Y_C_SEQ_D_OP, FP_CMP_TYPE_INST, 0x4620003a) -OP("c.seq.ps", Y_C_SEQ_PS_OP, FP_CMP_TYPE_INST, 0x4660003a) /* MIPS32 Rev 2 */ -OP("c.seq.s", Y_C_SEQ_S_OP, FP_CMP_TYPE_INST, 0x4600003a) -OP("c.sf.d", Y_C_SF_D_OP, FP_CMP_TYPE_INST, 0x46200038) -OP("c.sf.ps", Y_C_SF_PS_OP, FP_CMP_TYPE_INST, 0x46600038) /* MIPS32 Rev 2 */ -OP("c.sf.s", Y_C_SF_S_OP, FP_CMP_TYPE_INST, 0x46000038) -OP("c.ueq.d", Y_C_UEQ_D_OP, FP_CMP_TYPE_INST, 0x46200033) -OP("c.ueq.ps", Y_C_UEQ_PS_OP, FP_CMP_TYPE_INST, 0x46600033) /* MIPS32 Rev 2 */ -OP("c.ueq.s", Y_C_UEQ_S_OP, FP_CMP_TYPE_INST, 0x46000033) -OP("c.ule.d", Y_C_ULE_D_OP, FP_CMP_TYPE_INST, 0x46200037) -OP("c.ule.ps", Y_C_ULE_PS_OP, FP_CMP_TYPE_INST, 0x46600037) /* MIPS32 Rev 2 */ -OP("c.ule.s", Y_C_ULE_S_OP, FP_CMP_TYPE_INST, 0x46000037) -OP("c.ult.d", Y_C_ULT_D_OP, FP_CMP_TYPE_INST, 0x46200035) -OP("c.ult.ps", Y_C_ULT_PS_OP, FP_CMP_TYPE_INST, 0x46600035) /* MIPS32 Rev 2 */ -OP("c.ult.s", Y_C_ULT_S_OP, FP_CMP_TYPE_INST, 0x46000035) -OP("c.un.d", Y_C_UN_D_OP, FP_CMP_TYPE_INST, 0x46200031) -OP("c.un.ps", Y_C_UN_PS_OP, FP_CMP_TYPE_INST, 0x46600031) /* MIPS32 Rev 2 */ -OP("c.un.s", Y_C_UN_S_OP, FP_CMP_TYPE_INST, 0x46000031) - -OP("cache", Y_CACHE_OP, I2_TYPE_INST, 0xbc000000) /* MIPS32 */ - -OP("ceil.l.d", Y_CEIL_L_D_OP, FP_R2ds_TYPE_INST, 0x4620000a) /* MIPS32 Rev 2 */ -OP("ceil.l.s", Y_CEIL_L_S_OP, FP_R2ds_TYPE_INST, 0x4600000a) /* MIPS32 Rev 2 */ -OP("ceil.w.d", Y_CEIL_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000e) /* MIPS32 */ -OP("ceil.w.s", Y_CEIL_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000e) /* MIPS32 */ - -OP("cfc0", Y_CFC0_OP, FP_R2ts_TYPE_INST, 0x40400000) -OP("cfc1", Y_CFC1_OP, FP_R2ts_TYPE_INST, 0x44400000) -OP("cfc2", Y_CFC2_OP, FP_R2ts_TYPE_INST, 0x48400000) - -OP("clo", Y_CLO_OP, R3_TYPE_INST, 0x70000021) -OP("clz", Y_CLZ_OP, R3_TYPE_INST, 0x70000020) - -OP("cop2", Y_COP2_OP, J_TYPE_INST, 0x4a000000) - -OP("ctc0", Y_CTC0_OP, FP_R2ts_TYPE_INST, 0x40c00000) -OP("ctc1", Y_CTC1_OP, FP_R2ts_TYPE_INST, 0x44c00000) -OP("ctc2", Y_CTC2_OP, FP_R2ts_TYPE_INST, 0x48c00000) - -OP("cvt.d.l", Y_CVT_D_L_OP, FP_R2ds_TYPE_INST, 0x46b00021) /* MIPS32 Rev 2 */ -OP("cvt.d.s", Y_CVT_D_S_OP, FP_R2ds_TYPE_INST, 0x46000021) -OP("cvt.d.w", Y_CVT_D_W_OP, FP_R2ds_TYPE_INST, 0x46200021) -OP("cvt.l.d", Y_CVT_L_D_OP, FP_R2ds_TYPE_INST, 0x46200025) /* MIPS32 Rev 2 */ -OP("cvt.l.s", Y_CVT_L_S_OP, FP_R2ds_TYPE_INST, 0x46000025) /* MIPS32 Rev 2 */ -OP("cvt.ps.s", Y_CVT_PS_S_OP, FP_R2ds_TYPE_INST, 0x46000026) /* MIPS32 Rev 2 */ -OP("cvt.s.d", Y_CVT_S_D_OP, FP_R2ds_TYPE_INST, 0x46200020) -OP("cvt.s.l", Y_CVT_S_L_OP, FP_R2ds_TYPE_INST, 0x46b00020) /* MIPS32 Rev 2 */ -OP("cvt.s.pl", Y_CVT_S_PL_OP, FP_R2ds_TYPE_INST, 0x46c00024) /* MIPS32 Rev 2 */ -OP("cvt.s.pu", Y_CVT_S_PU_OP, FP_R2ds_TYPE_INST, 0x46c00020) /* MIPS32 Rev 2 */ -OP("cvt.s.w", Y_CVT_S_W_OP, FP_R2ds_TYPE_INST, 0x46800020) -OP("cvt.w.d", Y_CVT_W_D_OP, FP_R2ds_TYPE_INST, 0x46200024) -OP("cvt.w.s", Y_CVT_W_S_OP, FP_R2ds_TYPE_INST, 0x46000024) - -OP("deret", Y_DERET_OP, NOARG_TYPE_INST, 0x4200001f) /* MIPS32 Rev 2 */ -OP("di", Y_DI_OP, I1t_TYPE_INST, 0x41606000) /* MIPS32 Rev 2 */ - -OP("div", Y_DIV_OP, R2st_TYPE_INST, 0x0000001a) -OP("div.d", Y_DIV_D_OP, FP_R3_TYPE_INST, 0x46200003) -OP("div.s", Y_DIV_S_OP, FP_R3_TYPE_INST, 0x46000003) -OP("divu", Y_DIVU_OP, R2st_TYPE_INST, 0x0000001b) - -OP("ehb", Y_EHB_OP, NOARG_TYPE_INST, 0x000000c0) /* MIPS32 Rev 2 */ -OP("ei", Y_EI_OP, I1t_TYPE_INST, 0x41606020) /* MIPS32 Rev 2 */ -OP("eret", Y_ERET_OP, NOARG_TYPE_INST, 0x42000018) /* MIPS32 */ -OP("ext", Y_EXT_OP, FP_R2ds_TYPE_INST, 0x7c000000) /* MIPS32 Rev 2 */ - -OP("floor.l.d", Y_FLOOR_L_D_OP, FP_R2ds_TYPE_INST, 0x4620000b) /* MIPS32 Rev 2 */ -OP("floor.l.s", Y_FLOOR_L_S_OP, FP_R2ds_TYPE_INST, 0x4600000b) /* MIPS32 Rev 2 */ -OP("floor.w.d", Y_FLOOR_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000f) /* MIPS32 */ -OP("floor.w.s", Y_FLOOR_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000f) /* MIPS32 */ - -OP("ins", Y_INS_OP, FP_R2ds_TYPE_INST, 0x7c000004) /* MIPS32 Rev 2 */ - -OP("j", Y_J_OP, J_TYPE_INST, 0x08000000) -OP("jal", Y_JAL_OP, J_TYPE_INST, 0x0c000000) -OP("jalr", Y_JALR_OP, R2ds_TYPE_INST, 0x00000009) -OP("jalr.hb", Y_JALR_HB_OP, R2ds_TYPE_INST, 0x00000409) /* MIPS32 Rev 2 */ - -OP("jr", Y_JR_OP, R1s_TYPE_INST, 0x00000008) -OP("jr.hb", Y_JR_HB_OP, R1s_TYPE_INST, 0x00000408) /* MIPS32 Rev 2 */ - -OP("l.d", Y_L_D_POP, PSEUDO_OP, -1) -OP("l.s", Y_L_S_POP, PSEUDO_OP, -1) - -OP("la", Y_LA_POP, PSEUDO_OP, -1) -OP("lb", Y_LB_OP, I2a_TYPE_INST, 0x80000000) -OP("lbu", Y_LBU_OP, I2a_TYPE_INST, 0x90000000) -OP("ld", Y_LD_POP, PSEUDO_OP, -1) -OP("ldc1", Y_LDC1_OP, FP_I2a_TYPE_INST, 0xd4000000) /* MIPS32 */ -OP("ldc2", Y_LDC2_OP, I2a_TYPE_INST, 0xd8000000) /* MIPS32 */ -OP("ldxc1", Y_LDXC1_OP, FP_R3_TYPE_INST, 0x4c000001) /* MIPS32 Rev 2 */ -OP("lh", Y_LH_OP, I2a_TYPE_INST, 0x84000000) -OP("lhu", Y_LHU_OP, I2a_TYPE_INST, 0x94000000) - -OP("li", Y_LI_POP, PSEUDO_OP, -1) -OP("li.d", Y_LI_D_POP, PSEUDO_OP, -1) -OP("li.s", Y_LI_S_POP, PSEUDO_OP, -1) - -OP("ll", Y_LL_OP, I2a_TYPE_INST, 0xc0000000) /* MIPS32 */ - -OP("lui", Y_LUI_OP, I1t_TYPE_INST, 0x3c000000) -OP("luxc1", Y_LUXC1_OP, FP_R3_TYPE_INST, 0x4c000005) /* MIPS32 Rev 2 */ - -OP("lw", Y_LW_OP, I2a_TYPE_INST, 0x8c000000) -OP("lwc1", Y_LWC1_OP, FP_I2a_TYPE_INST, 0xc4000000) -OP("lwc2", Y_LWC2_OP, I2a_TYPE_INST, 0xc8000000) -OP("lwl", Y_LWL_OP, I2a_TYPE_INST, 0x88000000) -OP("lwr", Y_LWR_OP, I2a_TYPE_INST, 0x98000000) -OP("lwxc1", Y_LWXC1_OP, FP_R3_TYPE_INST, 0x4c000000) /* MIPS32 Rev 2 */ - -OP("madd", Y_MADD_OP, R2st_TYPE_INST, 0x70000000) /* MIPS32 */ -OP("madd.d", Y_MADD_D_OP, FP_R4_TYPE_INST, 0x4c000001) /* MIPS32 Rev 2 */ -OP("madd.ps", Y_MADD_PS_OP, FP_R4_TYPE_INST, 0x4c000006) /* MIPS32 Rev 2 */ -OP("madd.s", Y_MADD_S_OP, FP_R4_TYPE_INST, 0x4c000000) /* MIPS32 Rev 2 */ -OP("maddu", Y_MADDU_OP, R2st_TYPE_INST, 0x70000001) /* MIPS32 */ - -OP("mfc0", Y_MFC0_OP, R2td_TYPE_INST, 0x40000000) -OP("mfc1", Y_MFC1_OP, FP_R2ts_TYPE_INST, 0x44000000) -OP("mfc1.d", Y_MFC1_D_POP, PSEUDO_OP, -1) -OP("mfc2", Y_MFC2_OP, R2td_TYPE_INST, 0x48000000) -OP("mfhc1", Y_MFHC1_OP, FP_R2ts_TYPE_INST, 0x44600000) /* MIPS32 Rev 2 */ -OP("mfhc2", Y_MFHC2_OP, R2td_TYPE_INST, 0x48600000) /* MIPS32 Rev 2 */ -OP("mfhi", Y_MFHI_OP, R1d_TYPE_INST, 0x00000010) -OP("mflo", Y_MFLO_OP, R1d_TYPE_INST, 0x00000012) - -OP("mov.d", Y_MOV_D_OP, FP_R2ds_TYPE_INST, 0x46200006) -OP("mov.ps", Y_MOV_PS_OP, FP_R2ds_TYPE_INST, 0x46c00006) /* MIPS32 Rev 2 */ -OP("mov.s", Y_MOV_S_OP, FP_R2ds_TYPE_INST, 0x46000006) -OP("move", Y_MOVE_POP, PSEUDO_OP, -1) - -OP("movf", Y_MOVF_OP, MOVC_TYPE_INST, 0x00000001) /* MIPS32 */ -OP("movf.d", Y_MOVF_D_OP, FP_MOVC_TYPE_INST, 0x46200011) /* MIPS32 */ -OP("movf.ps", Y_MOVF_PS_OP, FP_MOVC_TYPE_INST, 0x46c00011) /* MIPS32 Rev 2 */ -OP("movf.s", Y_MOVF_S_OP, FP_MOVC_TYPE_INST, 0x46000011) /* MIPS32 */ - -OP("movn", Y_MOVN_OP, R3_TYPE_INST, 0x0000000b) /* MIPS32 */ -OP("movn.d", Y_MOVN_D_OP, FP_MOVC_TYPE_INST, 0x46200013) /* MIPS32 */ -OP("movn.ps", Y_MOVN_PS_OP, FP_MOVC_TYPE_INST, 0x46c00013) /* MIPS32 Rev 2 */ -OP("movn.s", Y_MOVN_S_OP, FP_MOVC_TYPE_INST, 0x46000013) /* MIPS32 */ - -OP("movt", Y_MOVT_OP, MOVC_TYPE_INST, 0x00010001) /* MIPS32 */ -OP("movt.d", Y_MOVT_D_OP, FP_MOVC_TYPE_INST, 0x46210011) /* MIPS32 */ -OP("movt.ps", Y_MOVT_PS_OP, FP_MOVC_TYPE_INST, 0x46c10011) /* MIPS32 Rev 2 */ -OP("movt.s", Y_MOVT_S_OP, FP_MOVC_TYPE_INST, 0x46010011) /* MIPS32 */ - -OP("movz", Y_MOVZ_OP, R3_TYPE_INST, 0x0000000a) /* MIPS32 */ -OP("movz.d", Y_MOVZ_D_OP, FP_MOVC_TYPE_INST, 0x46200012) /* MIPS32 */ -OP("movz.ps", Y_MOVZ_PS_OP, FP_MOVC_TYPE_INST, 0x46c00012) /* MIPS32 Rev 2 */ -OP("movz.s", Y_MOVZ_S_OP, FP_MOVC_TYPE_INST, 0x46000012) /* MIPS32 */ - -OP("msub", Y_MSUB_OP, R2st_TYPE_INST, 0x70000004) /* MIPS32 */ -OP("msub.d", Y_MSUB_D_OP, FP_R4_TYPE_INST, 0x4c000021) /* MIPS32 Rev 2 */ -OP("msub.ps", Y_MSUB_PS_OP, FP_R4_TYPE_INST, 0x4c000026) /* MIPS32 Rev 2 */ -OP("msub.s", Y_MSUB_S_OP, FP_R4_TYPE_INST, 0x4c000020) /* MIPS32 Rev 2 */ -OP("msubu", Y_MSUBU_OP, R2st_TYPE_INST, 0x70000005) /* MIPS32 */ - -OP("mtc0", Y_MTC0_OP, R2td_TYPE_INST, 0x40800000) -OP("mtc1", Y_MTC1_OP, FP_R2ts_TYPE_INST, 0x44800000) -OP("mtc1.d", Y_MTC1_D_POP, PSEUDO_OP, -1) -OP("mtc2", Y_MTC2_OP, R2td_TYPE_INST, 0x48800000) -OP("mthc1", Y_MTHC1_OP, FP_R2ts_TYPE_INST, 0x44e00000) /* MIPS32 Rev 2 */ -OP("mthc2", Y_MTHC2_OP, R2td_TYPE_INST, 0x48e00000) /* MIPS32 Rev 2 */ - -OP("mthi", Y_MTHI_OP, R1s_TYPE_INST, 0x00000011) -OP("mtlo", Y_MTLO_OP, R1s_TYPE_INST, 0x00000013) - -OP("mul", Y_MUL_OP, R3_TYPE_INST, 0x70000002) /* MIPS32 */ -OP("mul.d", Y_MUL_D_OP, FP_R3_TYPE_INST, 0x46200002) -OP("mul.ps", Y_MUL_PS_OP, FP_R3_TYPE_INST, 0x46c00002) /* MIPS32 Rev 2 */ -OP("mul.s", Y_MUL_S_OP, FP_R3_TYPE_INST, 0x46000002) -OP("mulo", Y_MULO_POP, PSEUDO_OP, -1) -OP("mulou", Y_MULOU_POP, PSEUDO_OP, -1) -OP("mult", Y_MULT_OP, R2st_TYPE_INST, 0x00000018) -OP("multu", Y_MULTU_OP, R2st_TYPE_INST, 0x00000019) - -OP("neg", Y_NEG_POP, PSEUDO_OP, -1) -OP("neg.d", Y_NEG_D_OP, FP_R2ds_TYPE_INST, 0x46200007) -OP("neg.ps", Y_NEG_PS_OP, FP_R2ds_TYPE_INST, 0x46c00007) /* MIPS32 Rev 2 */ -OP("neg.s", Y_NEG_S_OP, FP_R2ds_TYPE_INST, 0x46000007) -OP("negu", Y_NEGU_POP, PSEUDO_OP, -1) - -OP("nmadd.d", Y_NMADD_D_OP, FP_R4_TYPE_INST, 0x4c000031) /* MIPS32 Rev 2 */ -OP("nmadd.ps", Y_NMADD_PS_OP, FP_R4_TYPE_INST, 0x4c000036) /* MIPS32 Rev 2 */ -OP("nmadd.s", Y_NMADD_S_OP, FP_R4_TYPE_INST, 0x4c000030) /* MIPS32 Rev 2 */ -OP("nmsub.d", Y_NMSUB_D_OP, FP_R4_TYPE_INST, 0x4c000039) /* MIPS32 Rev 2 */ -OP("nmsub.ps", Y_NMSUB_PS_OP, FP_R4_TYPE_INST, 0x4c00003e) /* MIPS32 Rev 2 */ -OP("nmsub.s", Y_NMSUB_S_OP, FP_R4_TYPE_INST, 0x4c000038) /* MIPS32 Rev 2 */ - -OP("nop", Y_NOP_POP, PSEUDO_OP, -1) -OP("nor", Y_NOR_OP, R3_TYPE_INST, 0x00000027) -OP("not", Y_NOT_POP, PSEUDO_OP, -1) -OP("or", Y_OR_OP, R3_TYPE_INST, 0x00000025) -OP("ori", Y_ORI_OP, I2_TYPE_INST, 0x34000000) - -OP("pll.ps", Y_PLL_PS_OP, FP_R3_TYPE_INST, 0x46c0002c) /* MIPS32 Rev 2 */ -OP("plu.ps", Y_PLU_PS_OP, FP_R3_TYPE_INST, 0x46c0002d) /* MIPS32 Rev 2 */ - -OP("pref", Y_PREF_OP, I2_TYPE_INST, 0xcc000000) /* MIPS32 */ -OP("prefx", Y_PREFX_OP, R2st_TYPE_INST, 0x4600000f) /* MIPS32 Rev 2 */ -OP("pul.ps", Y_PUL_PS_OP, FP_R3_TYPE_INST, 0x46c0002e) /* MIPS32 Rev 2 */ -OP("puu.ps", Y_PUU_PS_OP, FP_R3_TYPE_INST, 0x46c0002f) /* MIPS32 Rev 2 */ - -OP("rdhwr", Y_RDHWR_OP, R3_TYPE_INST, 0x7c00003b) /* MIPS32 Rev 2 */ -OP("rdpgpr", Y_RDPGPR_OP, R2td_TYPE_INST, 0x41400000) /* MIPS32 Rev 2 */ - -OP("recip.d", Y_RECIP_D_OP, FP_R2ds_TYPE_INST, 0x46200015) /* MIPS32 Rev 2 */ -OP("recip.s", Y_RECIP_S_OP, FP_R2ds_TYPE_INST, 0x46000015) /* MIPS32 Rev 2 */ - -OP("rem", Y_REM_POP, PSEUDO_OP, -1) -OP("remu", Y_REMU_POP, PSEUDO_OP, -1) - -OP("rfe", Y_RFE_OP, NOARG_TYPE_INST, 0x42000010) - -OP("rol", Y_ROL_POP, PSEUDO_OP, -1) -OP("ror", Y_ROR_POP, PSEUDO_OP, -1) -OP("rotr", Y_ROTR_OP, R2sh_TYPE_INST, 0x00200002) /* MIPS32 Rev 2 */ -OP("rotrv", Y_ROTRV_OP, R2sh_TYPE_INST, 0x00200003) /* MIPS32 Rev 2 */ - -OP("round.l.d", Y_ROUND_L_D_OP, FP_R2ds_TYPE_INST, 0x46200008) /* MIPS32 Rev 2 */ -OP("round.l.s", Y_ROUND_L_S_OP, FP_R2ds_TYPE_INST, 0x46000008) /* MIPS32 Rev 2 */ -OP("round.w.d", Y_ROUND_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000c) /* MIPS32 */ -OP("round.w.s", Y_ROUND_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000c) /* MIPS32 */ - -OP("rsqrt.d", Y_RSQRT_D_OP, FP_R2ds_TYPE_INST, 0x46200016) /* MIPS32 Rev 2 */ -OP("rsqrt.s", Y_RSQRT_S_OP, FP_R2ds_TYPE_INST, 0x46000016) /* MIPS32 Rev 2 */ - -OP("s.d", Y_S_D_POP, PSEUDO_OP, -1) -OP("s.s", Y_S_S_POP, PSEUDO_OP, -1) - -OP("sb", Y_SB_OP, I2a_TYPE_INST, 0xa0000000) -OP("sc", Y_SC_OP, I2a_TYPE_INST, 0xe0000000) /* MIPS32 */ -OP("sd", Y_SD_POP, PSEUDO_OP, -1) -OP("sdbbp", Y_SDBBP_OP, NOARG_TYPE_INST, 0x7000003f) /* MIPS32 Rev 2*/ -OP("sdc1", Y_SDC1_OP, FP_I2a_TYPE_INST, 0xf4000000) /* MIPS32 */ -OP("sdc2", Y_SDC2_OP, I2a_TYPE_INST, 0xf8000000) /* MIPS32 */ -OP("sdxc1", Y_SDXC1_OP, FP_R3_TYPE_INST, 0x46000009) /* MIPS32 Rev 2 */ - -OP("seb", Y_SEB_OP, R2td_TYPE_INST, 0x7c000420) /* MIPS32 Rev 2 */ -OP("seh", Y_SEH_OP, R2td_TYPE_INST, 0x7c000620) /* MIPS32 Rev 2 */ -OP("seq", Y_SEQ_POP, PSEUDO_OP, -1) -OP("sge", Y_SGE_POP, PSEUDO_OP, -1) -OP("sgeu", Y_SGEU_POP, PSEUDO_OP, -1) -OP("sgt", Y_SGT_POP, PSEUDO_OP, -1) -OP("sgtu", Y_SGTU_POP, PSEUDO_OP, -1) - -OP("sh", Y_SH_OP, I2a_TYPE_INST, 0xa4000000) -OP("sle", Y_SLE_POP, PSEUDO_OP, -1) -OP("sleu", Y_SLEU_POP, PSEUDO_OP, -1) -OP("sll", Y_SLL_OP, R2sh_TYPE_INST, 0x00000000) -OP("sllv", Y_SLLV_OP, R3sh_TYPE_INST, 0x00000004) - -OP("slt", Y_SLT_OP, R3_TYPE_INST, 0x0000002a) -OP("slti", Y_SLTI_OP, I2_TYPE_INST, 0x28000000) -OP("sltiu", Y_SLTIU_OP, I2_TYPE_INST, 0x2c000000) -OP("sltu", Y_SLTU_OP, R3_TYPE_INST, 0x0000002b) -OP("sne", Y_SNE_POP, PSEUDO_OP, -1) - -OP("sqrt.d", Y_SQRT_D_OP, FP_R2ds_TYPE_INST, 0x46200004) /* MIPS32 */ -OP("sqrt.s", Y_SQRT_S_OP, FP_R2ds_TYPE_INST, 0x46000004) /* MIPS32 */ - -OP("sra", Y_SRA_OP, R2sh_TYPE_INST, 0x00000003) -OP("srav", Y_SRAV_OP, R3sh_TYPE_INST, 0x00000007) -OP("srl", Y_SRL_OP, R2sh_TYPE_INST, 0x00000002) -OP("srlv", Y_SRLV_OP, R3sh_TYPE_INST, 0x00000006) - -OP("ssnop", Y_SSNOP_OP, R2sh_TYPE_INST, 0x00000040) /* MIPS32 */ - -OP("sub", Y_SUB_OP, R3_TYPE_INST, 0x00000022) -OP("sub.d", Y_SUB_D_OP, FP_R3_TYPE_INST, 0x46200001) -OP("sub.ps", Y_SUB_PS_OP, FP_R3_TYPE_INST, 0x46600001) /* MIPS32 Rev 2 */ -OP("sub.s", Y_SUB_S_OP, FP_R3_TYPE_INST, 0x46000001) -OP("subu", Y_SUBU_OP, R3_TYPE_INST, 0x00000023) - -OP("suxc1", Y_SUXC1_OP, FP_R3_TYPE_INST, 0x4600000d) /* MIPS32 Rev 2 */ - -OP("sw", Y_SW_OP, I2a_TYPE_INST, 0xac000000) -OP("swc1", Y_SWC1_OP, FP_I2a_TYPE_INST, 0xe4000000) -OP("swc2", Y_SWC2_OP, I2a_TYPE_INST, 0xe8000000) -OP("swl", Y_SWL_OP, I2a_TYPE_INST, 0xa8000000) -OP("swr", Y_SWR_OP, I2a_TYPE_INST, 0xb8000000) -OP("swxc1", Y_SWXC1_OP, FP_R3_TYPE_INST, 0x46000008) /* MIPS32 Rev 2 */ - -OP("sync", Y_SYNC_OP, NOARG_TYPE_INST, 0x0000000f) /* MIPS32 */ -OP("synci", Y_SYNCI_OP, I2_TYPE_INST, 0x04140000) /* MIPS32 Rev 2 */ -OP("syscall", Y_SYSCALL_OP, NOARG_TYPE_INST, 0x0000000c) - -OP("teq", Y_TEQ_OP, R2st_TYPE_INST, 0x00000034) /* MIPS32 */ -OP("teqi", Y_TEQI_OP, I1s_TYPE_INST, 0x040c0000) /* MIPS32 */ -OP("tge", Y_TGE_OP, R2st_TYPE_INST, 0x00000030) /* MIPS32 */ -OP("tgei", Y_TGEI_OP, I1s_TYPE_INST, 0x04080000) /* MIPS32 */ -OP("tgeiu", Y_TGEIU_OP, I1s_TYPE_INST, 0x04090000) /* MIPS32 */ -OP("tgeu", Y_TGEU_OP, R2st_TYPE_INST, 0x00000031) /* MIPS32 */ - -OP("tlbp", Y_TLBP_OP, NOARG_TYPE_INST, 0x42000008) -OP("tlbr", Y_TLBR_OP, NOARG_TYPE_INST, 0x42000001) -OP("tlbwi", Y_TLBWI_OP, NOARG_TYPE_INST, 0x42000002) -OP("tlbwr", Y_TLBWR_OP, NOARG_TYPE_INST, 0x42000006) - -OP("tlt", Y_TLT_OP, R2st_TYPE_INST, 0x00000032) /* MIPS32 */ -OP("tlti", Y_TLTI_OP, I1s_TYPE_INST, 0x040a0000) /* MIPS32 */ -OP("tltiu", Y_TLTIU_OP, I1s_TYPE_INST, 0x040b0000) /* MIPS32 */ -OP("tltu", Y_TLTU_OP, R2st_TYPE_INST, 0x00000033) /* MIPS32 */ -OP("tne", Y_TNE_OP, R2st_TYPE_INST, 0x00000036) /* MIPS32 */ -OP("tnei", Y_TNEI_OP, I1s_TYPE_INST, 0x040e0000) /* MIPS32 */ - -OP("trunc.l.d", Y_TRUNC_L_D_OP, FP_R2ds_TYPE_INST, 0x46200009) /* MIPS32 Rev 2 */ -OP("trunc.l.s", Y_TRUNC_L_S_OP, FP_R2ds_TYPE_INST, 0x46000009) /* MIPS32 Rev 2 */ -OP("trunc.w.d", Y_TRUNC_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000d) /* MIPS32 */ -OP("trunc.w.s", Y_TRUNC_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000d) /* MIPS32 */ - -OP("ulh", Y_ULH_POP, PSEUDO_OP, -1) -OP("ulhu", Y_ULHU_POP, PSEUDO_OP, -1) -OP("ulw", Y_ULW_POP, PSEUDO_OP, -1) -OP("ush", Y_USH_POP, PSEUDO_OP, -1) -OP("usw", Y_USW_POP, PSEUDO_OP, -1) - -OP("wrpgpr", Y_WRPGPR_OP, R2td_TYPE_INST, 0x41c00000) /* MIPS32 Rev 2 */ -OP("wsbh", Y_WSBH_OP, R2td_TYPE_INST, 0x7c0000a0) /* MIPS32 Rev 2 */ - -OP("xor", Y_XOR_OP, R3_TYPE_INST, 0x00000026) -OP("xori", Y_XORI_OP, I2_TYPE_INST, 0x38000000) diff --git a/spim-jsspim/CPU/parser.h b/spim-jsspim/CPU/parser.h deleted file mode 100755 index 0e120f8..0000000 --- a/spim-jsspim/CPU/parser.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to parser for instructions and assembler directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -void fix_current_label_address (mem_addr new_addr); -int imm_op_to_op (int opcode); -void initialize_parser (char *file_name); -int op_to_imm_op (int opcode); -void yyerror (char *s); -int yyparse (); - - -/* Exported Variables: */ - -extern bool data_dir; /* => item in data segment */ - -extern bool text_dir; /* => item in text segment */ - -extern bool parse_error_occurred; /* => parse resulted in error */ diff --git a/spim-jsspim/CPU/parser.y b/spim-jsspim/CPU/parser.y deleted file mode 100755 index 4e7202f..0000000 --- a/spim-jsspim/CPU/parser.y +++ /dev/null @@ -1,2956 +0,0 @@ -/* SPIM S20 MIPS simulator. - Parser for instructions and assembler directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -%expect 25 /* Supress warning about 25 shift-reduce conflicts */ - -%start LINE - -%token Y_EOF - -%token Y_NL -%token Y_INT -%token Y_ID -%token Y_REG -%token Y_FP_REG -%token Y_STR -%token Y_FP - -/* MIPS instructions op codes: */ - -%token Y_ABS_D_OP -%token Y_ABS_PS_OP -%token Y_ABS_S_OP -%token Y_ADD_D_OP -%token Y_ADD_OP -%token Y_ADD_PS_OP -%token Y_ADD_S_OP -%token Y_ADDI_OP -%token Y_ADDIU_OP -%token Y_ADDU_OP -%token Y_ALNV_PS_OP -%token Y_AND_OP -%token Y_ANDI_OP -%token Y_BC1F_OP -%token Y_BC1FL_OP -%token Y_BC1T_OP -%token Y_BC1TL_OP -%token Y_BC2F_OP -%token Y_BC2FL_OP -%token Y_BC2T_OP -%token Y_BC2TL_OP -%token Y_BEQ_OP -%token Y_BEQL_OP -%token Y_BGEZ_OP -%token Y_BGEZAL_OP -%token Y_BGEZALL_OP -%token Y_BGEZL_OP -%token Y_BGTZ_OP -%token Y_BGTZL_OP -%token Y_BLEZ_OP -%token Y_BLEZL_OP -%token Y_BLTZ_OP -%token Y_BLTZAL_OP -%token Y_BLTZALL_OP -%token Y_BLTZL_OP -%token Y_BNE_OP -%token Y_BNEL_OP -%token Y_BREAK_OP -%token Y_C_EQ_D_OP -%token Y_C_EQ_PS_OP -%token Y_C_EQ_S_OP -%token Y_C_F_D_OP -%token Y_C_F_PS_OP -%token Y_C_F_S_OP -%token Y_C_LE_D_OP -%token Y_C_LE_PS_OP -%token Y_C_LE_S_OP -%token Y_C_LT_D_OP -%token Y_C_LT_PS_OP -%token Y_C_LT_S_OP -%token Y_C_NGE_D_OP -%token Y_C_NGE_PS_OP -%token Y_C_NGE_S_OP -%token Y_C_NGL_D_OP -%token Y_C_NGL_PS_OP -%token Y_C_NGL_S_OP -%token Y_C_NGLE_D_OP -%token Y_C_NGLE_PS_OP -%token Y_C_NGLE_S_OP -%token Y_C_NGT_D_OP -%token Y_C_NGT_PS_OP -%token Y_C_NGT_S_OP -%token Y_C_OLE_D_OP -%token Y_C_OLE_PS_OP -%token Y_C_OLE_S_OP -%token Y_C_OLT_D_OP -%token Y_C_OLT_PS_OP -%token Y_C_OLT_S_OP -%token Y_C_SEQ_D_OP -%token Y_C_SEQ_PS_OP -%token Y_C_SEQ_S_OP -%token Y_C_SF_D_OP -%token Y_C_SF_PS_OP -%token Y_C_SF_S_OP -%token Y_C_UEQ_D_OP -%token Y_C_UEQ_PS_OP -%token Y_C_UEQ_S_OP -%token Y_C_ULE_D_OP -%token Y_C_ULE_PS_OP -%token Y_C_ULE_S_OP -%token Y_C_ULT_D_OP -%token Y_C_ULT_PS_OP -%token Y_C_ULT_S_OP -%token Y_C_UN_D_OP -%token Y_C_UN_PS_OP -%token Y_C_UN_S_OP -%token Y_CACHE_OP -%token Y_CEIL_L_D_OP -%token Y_CEIL_L_S_OP -%token Y_CEIL_W_D_OP -%token Y_CEIL_W_S_OP -%token Y_CFC0_OP -%token Y_CFC1_OP -%token Y_CFC2_OP -%token Y_CLO_OP -%token Y_CLZ_OP -%token Y_COP2_OP -%token Y_CTC0_OP -%token Y_CTC1_OP -%token Y_CTC2_OP -%token Y_CVT_D_L_OP -%token Y_CVT_D_S_OP -%token Y_CVT_D_W_OP -%token Y_CVT_L_D_OP -%token Y_CVT_L_S_OP -%token Y_CVT_PS_S_OP -%token Y_CVT_S_D_OP -%token Y_CVT_S_L_OP -%token Y_CVT_S_PL_OP -%token Y_CVT_S_PU_OP -%token Y_CVT_S_W_OP -%token Y_CVT_W_D_OP -%token Y_CVT_W_S_OP -%token Y_DERET_OP -%token Y_DI_OP -%token Y_DIV_D_OP -%token Y_DIV_OP -%token Y_DIV_S_OP -%token Y_DIVU_OP -%token Y_EHB_OP -%token Y_EI_OP -%token Y_ERET_OP -%token Y_EXT_OP -%token Y_FLOOR_L_D_OP -%token Y_FLOOR_L_S_OP -%token Y_FLOOR_W_D_OP -%token Y_FLOOR_W_S_OP -%token Y_INS_OP -%token Y_J_OP -%token Y_JAL_OP -%token Y_JALR_HB_OP -%token Y_JALR_OP -%token Y_JR_HB_OP -%token Y_JR_OP -%token Y_LB_OP -%token Y_LBU_OP -%token Y_LDC1_OP -%token Y_LDC2_OP -%token Y_LDXC1_OP -%token Y_LH_OP -%token Y_LHU_OP -%token Y_LL_OP -%token Y_LUI_OP -%token Y_LUXC1_OP -%token Y_LW_OP -%token Y_LWC1_OP -%token Y_LWC2_OP -%token Y_LWL_OP -%token Y_LWR_OP -%token Y_LWXC1_OP -%token Y_MADD_D_OP -%token Y_MADD_OP -%token Y_MADD_PS_OP -%token Y_MADD_S_OP -%token Y_MADDU_OP -%token Y_MFC0_OP -%token Y_MFC1_OP -%token Y_MFC2_OP -%token Y_MFHC1_OP -%token Y_MFHC2_OP -%token Y_MFHI_OP -%token Y_MFLO_OP -%token Y_MOV_D_OP -%token Y_MOV_PS_OP -%token Y_MOV_S_OP -%token Y_MOVF_D_OP -%token Y_MOVF_OP -%token Y_MOVF_PS_OP -%token Y_MOVF_S_OP -%token Y_MOVN_D_OP -%token Y_MOVN_OP -%token Y_MOVN_PS_OP -%token Y_MOVN_S_OP -%token Y_MOVT_D_OP -%token Y_MOVT_OP -%token Y_MOVT_PS_OP -%token Y_MOVT_S_OP -%token Y_MOVZ_D_OP -%token Y_MOVZ_OP -%token Y_MOVZ_PS_OP -%token Y_MOVZ_S_OP -%token Y_MSUB_D_OP -%token Y_MSUB_OP -%token Y_MSUB_PS_OP -%token Y_MSUB_S_OP -%token Y_MSUBU_OP -%token Y_MTC0_OP -%token Y_MTC1_OP -%token Y_MTC2_OP -%token Y_MTHC1_OP -%token Y_MTHC2_OP -%token Y_MTHI_OP -%token Y_MTLO_OP -%token Y_MUL_D_OP -%token Y_MUL_PS_OP -%token Y_MUL_S_OP -%token Y_MUL_OP -%token Y_MULT_OP -%token Y_MULTU_OP -%token Y_NEG_D_OP -%token Y_NEG_PS_OP -%token Y_NEG_S_OP -%token Y_NMADD_D_OP -%token Y_NMADD_PS_OP -%token Y_NMADD_S_OP -%token Y_NMSUB_D_OP -%token Y_NMSUB_PS_OP -%token Y_NMSUB_S_OP -%token Y_NOR_OP -%token Y_OR_OP -%token Y_ORI_OP -%token Y_PFW_OP -%token Y_PLL_PS_OP -%token Y_PLU_PS_OP -%token Y_PREF_OP -%token Y_PREFX_OP -%token Y_PUL_PS_OP -%token Y_PUU_PS_OP -%token Y_RDHWR_OP -%token Y_RDPGPR_OP -%token Y_RECIP_D_OP -%token Y_RECIP_S_OP -%token Y_RFE_OP -%token Y_ROTR_OP -%token Y_ROTRV_OP -%token Y_ROUND_L_D_OP -%token Y_ROUND_L_S_OP -%token Y_ROUND_W_D_OP -%token Y_ROUND_W_S_OP -%token Y_RSQRT_D_OP -%token Y_RSQRT_S_OP -%token Y_SB_OP -%token Y_SC_OP -%token Y_SDBBP_OP -%token Y_SDC1_OP -%token Y_SDC2_OP -%token Y_SDXC1_OP -%token Y_SEB_OP -%token Y_SEH_OP -%token Y_SH_OP -%token Y_SLL_OP -%token Y_SLLV_OP -%token Y_SLT_OP -%token Y_SLTI_OP -%token Y_SLTIU_OP -%token Y_SLTU_OP -%token Y_SQRT_D_OP -%token Y_SQRT_S_OP -%token Y_SRA_OP -%token Y_SRAV_OP -%token Y_SRL_OP -%token Y_SRLV_OP -%token Y_SSNOP_OP -%token Y_SUB_D_OP -%token Y_SUB_OP -%token Y_SUB_PS_OP -%token Y_SUB_S_OP -%token Y_SUBU_OP -%token Y_SUXC1_OP -%token Y_SW_OP -%token Y_SWC1_OP -%token Y_SWC2_OP -%token Y_SWL_OP -%token Y_SWR_OP -%token Y_SWXC1_OP -%token Y_SYNC_OP -%token Y_SYNCI_OP -%token Y_SYSCALL_OP -%token Y_TEQ_OP -%token Y_TEQI_OP -%token Y_TGE_OP -%token Y_TGEI_OP -%token Y_TGEIU_OP -%token Y_TGEU_OP -%token Y_TLBP_OP -%token Y_TLBR_OP -%token Y_TLBWI_OP -%token Y_TLBWR_OP -%token Y_TLT_OP -%token Y_TLTI_OP -%token Y_TLTIU_OP -%token Y_TLTU_OP -%token Y_TNE_OP -%token Y_TNEI_OP -%token Y_TRUNC_L_D_OP -%token Y_TRUNC_L_S_OP -%token Y_TRUNC_W_D_OP -%token Y_TRUNC_W_S_OP -%token Y_WRPGPR_OP -%token Y_WSBH_OP -%token Y_XOR_OP -%token Y_XORI_OP - - -/* Assembler pseudo operations op codes: */ - -%token Y_ABS_POP -%token Y_B_POP -%token Y_BAL_POP -%token Y_BEQZ_POP -%token Y_BGE_POP -%token Y_BGEU_POP -%token Y_BGT_POP -%token Y_BGTU_POP -%token Y_BLE_POP -%token Y_BLEU_POP -%token Y_BLT_POP -%token Y_BLTU_POP -%token Y_BNEZ_POP -%token Y_LA_POP -%token Y_LD_POP -%token Y_L_D_POP -%token Y_L_S_POP -%token Y_LI_D_POP -%token Y_LI_POP -%token Y_LI_S_POP -%token Y_MFC1_D_POP -%token Y_MOVE_POP -%token Y_MTC1_D_POP -%token Y_MULO_POP -%token Y_MULOU_POP -%token Y_NEG_POP -%token Y_NEGU_POP -%token Y_NOP_POP -%token Y_NOT_POP -%token Y_REM_POP -%token Y_REMU_POP -%token Y_ROL_POP -%token Y_ROR_POP -%token Y_S_D_POP -%token Y_S_S_POP -%token Y_SD_POP -%token Y_SEQ_POP -%token Y_SGE_POP -%token Y_SGEU_POP -%token Y_SGT_POP -%token Y_SGTU_POP -%token Y_SLE_POP -%token Y_SLEU_POP -%token Y_SNE_POP -%token Y_ULH_POP -%token Y_ULHU_POP -%token Y_ULW_POP -%token Y_USH_POP -%token Y_USW_POP - -/* Assembler directives: */ - -%token Y_ALIAS_DIR -%token Y_ALIGN_DIR -%token Y_ASCII_DIR -%token Y_ASCIIZ_DIR -%token Y_ASM0_DIR -%token Y_BGNB_DIR -%token Y_BYTE_DIR -%token Y_COMM_DIR -%token Y_DATA_DIR -%token Y_DOUBLE_DIR -%token Y_END_DIR -%token Y_ENDB_DIR -%token Y_ENDR_DIR -%token Y_ENT_DIR -%token Y_ERR_DIR -%token Y_EXTERN_DIR -%token Y_FILE_DIR -%token Y_FLOAT_DIR -%token Y_FMASK_DIR -%token Y_FRAME_DIR -%token Y_GLOBAL_DIR -%token Y_HALF_DIR -%token Y_K_DATA_DIR -%token Y_K_TEXT_DIR -%token Y_LABEL_DIR -%token Y_LCOMM_DIR -%token Y_LIVEREG_DIR -%token Y_LOC_DIR -%token Y_MASK_DIR -%token Y_NOALIAS_DIR -%token Y_OPTIONS_DIR -%token Y_RDATA_DIR -%token Y_REPEAT_DIR -%token Y_SDATA_DIR -%token Y_SET_DIR -%token Y_SPACE_DIR -%token Y_STRUCT_DIR -%token Y_TEXT_DIR -%token Y_VERSTAMP_DIR -%token Y_VREG_DIR -%token Y_WORD_DIR - -%{ -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "data.h" -#include "scanner.h" -#include "parser.h" - - -/* return (0) */ -#define LINE_PARSE_DONE YYACCEPT - -/* return (1) */ -#define FILE_PARSE_DONE YYABORT - -typedef struct ll -{ - label *head; - struct ll *tail; -} label_list; - - -/* Exported Variables: */ - -bool data_dir; /* => item in data segment */ - -bool text_dir; /* => item in text segment */ - -bool parse_error_occurred; /* => parse resulted in error */ - - -/* Local functions: */ - -static imm_expr *branch_offset (int n_inst); -static int cc_to_rt (int cc, int nd, int tf); -static void check_imm_range (imm_expr*, int32, int32); -static void check_uimm_range (imm_expr*, uint32, uint32); -static void clear_labels (); -static label_list *cons_label (label *head, label_list *tail); -static void div_inst (int op, int rd, int rs, int rt, int const_divisor); -static void mips32_r2_inst (); -static void mult_inst (int op, int rd, int rs, int rt); -static void nop_inst (); -static void set_eq_inst (int op, int rd, int rs, int rt); -static void set_ge_inst (int op, int rd, int rs, int rt); -static void set_gt_inst (int op, int rd, int rs, int rt); -static void set_le_inst (int op, int rd, int rs, int rt); -static void store_word_data (int value); -static void trap_inst (); -static void yywarn (char*); - - -/* Local variables: */ - -static bool null_term; /* => string terminate by \0 */ - -static void (*store_op) (void*); /* Function to store items in an EXPR_LST */ - -static label_list *this_line_labels = NULL; /* List of label for curent line */ - -static bool noat_flag = 0; /* => program can use $1 */ - -static char *input_file_name; /* Name of file being parsed */ - -%} - - - -%% - -LINE: {parse_error_occurred = false; scanner_start_line (); } LBL_CMD ; - -LBL_CMD: OPT_LBL CMD - | CMD - ; - - -OPT_LBL: ID ':' { - /* Call outside of cons_label, since an error sets that variable to NULL. */ - label* l = record_label ((char*)$1.p, - text_dir ? current_text_pc () : current_data_pc (), - 0); - this_line_labels = cons_label (l, this_line_labels); - free ((char*)$1.p); - } - - | ID '=' EXPR - { - label *l = record_label ((char*)$1.p, (mem_addr)$3.i, 1); - free ((char*)$1.p); - - l->const_flag = 1; - clear_labels (); - } - ; - - -CMD: ASM_CODE - { - clear_labels (); - } - TERM - - | ASM_DIRECTIVE - { - clear_labels (); - } - TERM - - | TERM - ; - - -TERM: Y_NL - { - LINE_PARSE_DONE; - } - - | Y_EOF - { - clear_labels (); - FILE_PARSE_DONE; - } - ; - - - -ASM_CODE: LOAD_OPS DEST ADDRESS - { - i_type_inst ($1.i == Y_LD_POP ? Y_LW_OP : $1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - if ($1.i == Y_LD_POP) - i_type_inst_free (Y_LW_OP, - $2.i + 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 4)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADC_OPS COP_REG ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADFP_OPS F_SRC1 ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADI_OPS DEST UIMM16 - { - i_type_inst_free ($1.i, $2.i, 0, (imm_expr *)$3.p); - } - - - | Y_LA_POP DEST ADDRESS - { - if (addr_expr_reg ((addr_expr *)$3.p)) - i_type_inst (Y_ADDI_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - else - i_type_inst (Y_ORI_OP, $2.i, 0, - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_LI_POP DEST IMM32 - { - i_type_inst_free (Y_ORI_OP, $2.i, 0, (imm_expr *)$3.p); - } - - - | Y_LI_D_POP F_DEST Y_FP - { - int *x = (int *) $3.p; - - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*x)); - r_co_type_inst (Y_MTC1_OP, 0, $2.i, 1); - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*(x+1))); - r_co_type_inst (Y_MTC1_OP, 0, $2.i + 1, 1); - } - - - | Y_LI_S_POP F_DEST Y_FP - { - float x = (float) *((double *) $3.p); - int *y = (int *) &x; - - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*y)); - r_co_type_inst (Y_MTC1_OP, 0, $2.i, 1); - } - - - | Y_ULW_POP DEST ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (Y_LWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_LWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); -#else - i_type_inst_free (Y_LWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); - i_type_inst (Y_LWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | ULOADH_POPS DEST ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (($1.i == Y_ULH_POP ? Y_LB_OP : Y_LBU_OP), - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_LBU_OP, 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); -#else - i_type_inst_free (($1.i == Y_ULH_POP ? Y_LB_OP : Y_LBU_OP), - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); - i_type_inst (Y_LBU_OP, 1, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - r_sh_type_inst (Y_SLL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | LOADFP_INDEX_OPS F_DEST ADDRESS - { - mips32_r2_inst (); - } - - - | STORE_OPS SRC1 ADDRESS - { - i_type_inst ($1.i == Y_SD_POP ? Y_SW_OP : $1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - if ($1.i == Y_SD_POP) - i_type_inst_free (Y_SW_OP, $2.i + 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 4)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREC_OPS COP_REG ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_USW_POP SRC1 ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (Y_SWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_SWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); -#else - i_type_inst_free (Y_SWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); - i_type_inst (Y_SWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_USH_POP SRC1 ADDRESS - { - i_type_inst (Y_SB_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - - /* ROL SRC, SRC, 8 */ - r_sh_type_inst (Y_SLL_OP, 1, $2.i, 24); - r_sh_type_inst (Y_SRL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - - i_type_inst_free (Y_SB_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); - /* ROR SRC, SRC, 8 */ - r_sh_type_inst (Y_SRL_OP, 1, $2.i, 24); - r_sh_type_inst (Y_SLL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREFP_OPS F_SRC1 ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREFP_INDEX_OPS F_DEST ADDRESS - { - mips32_r2_inst (); - } - - - | SYS_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | PREFETCH_OPS ADDRESS - { - mips32_r2_inst (); - } - - - | CACHE_OPS Y_INT ADDRESS - { - i_type_inst_free ($1.i, $2.i, 0, (imm_expr *)$3.p); - } - - - | TLB_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | Y_SYNC_OP - { - r_type_inst ($1.i, 0, 0, 0); - } - - | Y_SYNC_OP Y_INT - { - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | Y_BREAK_OP Y_INT - { - if ($2.i == 1) - yyerror ("Breakpoint 1 is reserved for debugger"); - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | Y_NOP_POP - { - nop_inst (); - } - - - | Y_SSNOP_OP - { - r_sh_type_inst (Y_SLL_OP, 0, 0, 1); /* SLL r0 r0 1 */ - } - - - | Y_ABS_POP DEST SRC1 - { - if ($2.i != $3.i) - r_type_inst (Y_ADDU_OP, $2.i, 0, $3.i); - - i_type_inst_free (Y_BGEZ_OP, 0, $3.i, branch_offset (2)); - r_type_inst (Y_SUB_OP, $2.i, 0, $3.i); - } - - - | Y_NEG_POP DEST SRC1 - { - r_type_inst (Y_SUB_OP, $2.i, 0, $3.i); - } - - - | Y_NEGU_POP DEST SRC1 - { - r_type_inst (Y_SUBU_OP, $2.i, 0, $3.i); - } - - - | Y_NOT_POP DEST SRC1 - { - r_type_inst (Y_NOR_OP, $2.i, $3.i, 0); - } - - - | Y_MOVE_POP DEST SRC1 - { - r_type_inst (Y_ADDU_OP, $2.i, 0, $3.i); - } - - - | NULLARY_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | NULLARY_OPS_REV2 - { - mips32_r2_inst (); - } - - - | COUNT_LEADING_OPS DEST SRC1 - { - /* RT must be equal to RD */ - r_type_inst ($1.i, $2.i, $3.i, $2.i); - } - - - | UNARY_OPS_REV2 DEST - { - mips32_r2_inst (); - } - - - | BINARYI_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | BINARYI_OPS DEST SRC1 IMM32 - { - i_type_inst_free (op_to_imm_op ($1.i), $2.i, $3.i, - (imm_expr *)$4.p); - } - - | BINARYI_OPS DEST IMM32 - { - i_type_inst_free (op_to_imm_op ($1.i), $2.i, $2.i, - (imm_expr *)$3.p); - } - - - | BINARYIR_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $4.i, $3.i); - } - - | BINARYIR_OPS DEST SRC1 Y_INT - { - r_sh_type_inst (op_to_imm_op ($1.i), $2.i, $3.i, $4.i); - } - - | BINARYIR_OPS DEST Y_INT - { - r_sh_type_inst (op_to_imm_op ($1.i), $2.i, $2.i, $3.i); - } - - - | BINARY_ARITHI_OPS DEST SRC1 IMM16 - { - i_type_inst_free ($1.i, $2.i, $3.i, (imm_expr *)$4.p); - } - - | BINARY_ARITHI_OPS DEST IMM16 - { - i_type_inst_free ($1.i, $2.i, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_LOGICALI_OPS DEST SRC1 UIMM16 - { - i_type_inst_free ($1.i, $2.i, $3.i, (imm_expr *)$4.p); - } - - | BINARY_LOGICALI_OPS DEST UIMM16 - { - i_type_inst_free ($1.i, $2.i, $2.i, (imm_expr *)$3.p); - } - - - | SHIFT_OPS DEST SRC1 Y_INT - { - if (($4.i < 0) || (31 < $4.i)) - yywarn ("Shift distance can only be in the range 0..31"); - r_sh_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SHIFT_OPS DEST SRC1 SRC2 - { - r_type_inst (imm_op_to_op ($1.i), $2.i, $4.i, $3.i); - } - - - | SHIFT_OPS_REV2 DEST SRC1 Y_INT - { - mips32_r2_inst (); - } - - | SHIFTV_OPS_REV2 DEST SRC1 SRC2 - { - mips32_r2_inst (); - } - - - | BINARY_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | BINARY_OPS DEST SRC1 IMM32 - { - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - r_type_inst ($1.i, - $2.i, - $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - } - free ((imm_expr *)$4.p); - } - - | BINARY_OPS DEST IMM32 - { - check_uimm_range ((imm_expr *)$3.p, UIMM_MIN, UIMM_MAX); - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (!is_zero_imm ((imm_expr *)$3.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - r_type_inst ($1.i, - $2.i, - $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1)); - } - free ((imm_expr *)$3.p); - } - - - | BINARY_OPS_REV2 DEST SRC1 - { - mips32_r2_inst (); - } - - - | SUB_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SUB_OPS DEST SRC1 IMM32 - { - int val = eval_imm_expr ((imm_expr *)$4.p); - - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - i_type_inst ($1.i == Y_SUB_OP ? Y_ADDI_OP - : $1.i == Y_SUBU_OP ? Y_ADDIU_OP - : (fatal_error ("Bad SUB_OP\n"), 0), - $2.i, - $3.i, - make_imm_expr (-val, NULL, false)); - free ((imm_expr *)$4.p); - } - - | SUB_OPS DEST IMM32 - { - int val = eval_imm_expr ((imm_expr *)$3.p); - - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - i_type_inst ($1.i == Y_SUB_OP ? Y_ADDI_OP - : $1.i == Y_SUBU_OP ? Y_ADDIU_OP - : (fatal_error ("Bad SUB_OP\n"), 0), - $2.i, - $2.i, - make_imm_expr (-val, NULL, false)); - free ((imm_expr *)$3.p); - } - - - | DIV_POPS DEST SRC1 - { - /* The hardware divide operation (ignore 1st arg) */ - if ($1.i != Y_DIV_OP && $1.i != Y_DIVU_OP) - yyerror ("REM requires 3 arguments"); - else - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - | DIV_POPS DEST SRC1 SRC2 - { - /* Pseudo divide operations */ - div_inst ($1.i, $2.i, $3.i, $4.i, 0); - } - - | DIV_POPS DEST SRC1 IMM32 - { - if (is_zero_imm ((imm_expr *)$4.p)) - yyerror ("Divide by zero"); - else - { - /* Use $at */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - div_inst ($1.i, $2.i, $3.i, 1, 1); - } - } - - - | MUL_POPS DEST SRC1 SRC2 - { - mult_inst ($1.i, $2.i, $3.i, $4.i); - } - - | MUL_POPS DEST SRC1 IMM32 - { - if (is_zero_imm ((imm_expr *)$4.p)) - /* Optimize: n * 0 == 0 */ - i_type_inst_free (Y_ORI_OP, $2.i, 0, (imm_expr *)$4.p); - else - { - /* Use $at */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - mult_inst ($1.i, $2.i, $3.i, 1); - } - } - - - | MULT_OPS SRC1 SRC2 - { - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - - | MULT_OPS3 DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | MULT_OPS3 DEST SRC1 IMM32 - { - /* Special case, for backward compatibility with pseudo-op - MULT instruction */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); /* Use $at */ - r_type_inst ($1.i, $2.i, $3.i, 1); - } - - - | Y_ROR_POP DEST SRC1 SRC2 - { - r_type_inst (Y_SUBU_OP, 1, 0, $4.i); - r_type_inst (Y_SLLV_OP, 1, 1, $3.i); - r_type_inst (Y_SRLV_OP, $2.i, $4.i, $3.i); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - } - - - | Y_ROL_POP DEST SRC1 SRC2 - { - r_type_inst (Y_SUBU_OP, 1, 0, $4.i); - r_type_inst (Y_SRLV_OP, 1, 1, $3.i); - r_type_inst (Y_SLLV_OP, $2.i, $4.i, $3.i); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - } - - - | Y_ROR_POP DEST SRC1 IMM32 - { - long dist = eval_imm_expr ((imm_expr *)$4.p); - - check_imm_range ((imm_expr *)$4.p, 0, 31); - r_sh_type_inst (Y_SLL_OP, 1, $3.i, -dist); - r_sh_type_inst (Y_SRL_OP, $2.i, $3.i, dist); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free ((imm_expr *)$4.p); - } - - - | Y_ROL_POP DEST SRC1 IMM32 - { - long dist = eval_imm_expr ((imm_expr *)$4.p); - - check_imm_range ((imm_expr *)$4.p, 0, 31); - r_sh_type_inst (Y_SRL_OP, 1, $3.i, -dist); - r_sh_type_inst (Y_SLL_OP, $2.i, $3.i, dist); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free ((imm_expr *)$4.p); - } - - - | BF_OPS_REV2 F_DEST F_SRC2 Y_INT Y_INT - { - mips32_r2_inst (); - } - - - | SET_LE_POPS DEST SRC1 SRC2 - { - set_le_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_LE_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_le_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | SET_GT_POPS DEST SRC1 SRC2 - { - set_gt_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_GT_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_gt_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - - | SET_GE_POPS DEST SRC1 SRC2 - { - set_ge_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_GE_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_ge_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | SET_EQ_POPS DEST SRC1 SRC2 - { - set_eq_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_EQ_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_eq_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | BR_COP_OPS LABEL - { - /* RS and RT fields contain information on test */ - int nd = opcode_is_nullified_branch ($1.i) ? 1 : 0; - int tf = opcode_is_true_branch ($1.i) ? 1 : 0; - i_type_inst_free ($1.i, - cc_to_rt (0, nd, tf), - BIN_RS ($1.i), - (imm_expr *)$2.p); - } - - | BR_COP_OPS CC_REG LABEL - { - /* RS and RT fields contain information on test */ - int nd = opcode_is_nullified_branch ($1.i) ? 1 : 0; - int tf = opcode_is_true_branch ($1.i) ? 1 : 0; - i_type_inst_free ($1.i, - cc_to_rt ($2.i, nd, tf), - BIN_RS ($1.i), - (imm_expr *)$3.p); - } - - - | UNARY_BR_OPS SRC1 LABEL - { - i_type_inst_free ($1.i, 0, $2.i, (imm_expr *)$3.p); - } - - - | UNARY_BR_POPS SRC1 LABEL - { - i_type_inst_free ($1.i == Y_BEQZ_POP ? Y_BEQ_OP : Y_BNE_OP, - 0, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_BR_OPS SRC1 SRC2 LABEL - { - i_type_inst_free ($1.i, $3.i, $2.i, (imm_expr *)$4.p); - } - - | BINARY_BR_OPS SRC1 BR_IMM32 LABEL - { - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (is_zero_imm ((imm_expr *)$3.p)) - i_type_inst ($1.i, $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1), - (imm_expr *)$4.p); - else - { - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst ($1.i, $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1), - (imm_expr *)$4.p); - } - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | BR_GT_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BGT_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $3.i, $2.i); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_GT_POPS SRC1 BR_IMM32 LABEL - { - if ($1.i == Y_BGT_POP) - { - /* Use $at */ - i_type_inst_free (Y_SLTI_OP, 1, $2.i, - incr_expr_offset ((imm_expr *)$3.p, 1)); - i_type_inst (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - else - { - /* Use $at */ - /* Can't add 1 to immediate since 0xffffffff+1 = 0 < 1 */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst_free (Y_BEQ_OP, $2.i, 1, branch_offset (3)); - r_type_inst (Y_SLTU_OP, 1, $2.i, 1); - i_type_inst (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | BR_GE_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BGE_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $2.i, $3.i); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_GE_POPS SRC1 BR_IMM32 LABEL - { - i_type_inst ($1.i == Y_BGE_POP ? Y_SLTI_OP : Y_SLTIU_OP, - 1, $2.i, (imm_expr *)$3.p); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - free ((imm_expr *)$3.p); - } - - - | BR_LT_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BLT_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $2.i, $3.i); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_LT_POPS SRC1 BR_IMM32 LABEL - { - i_type_inst ($1.i == Y_BLT_POP ? Y_SLTI_OP : Y_SLTIU_OP, - 1, $2.i, (imm_expr *)$3.p); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - free ((imm_expr *)$3.p); - } - - - | BR_LE_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BLE_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $3.i, $2.i); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_LE_POPS SRC1 BR_IMM32 LABEL - { - if ($1.i == Y_BLE_POP) - { - /* Use $at */ - i_type_inst_free (Y_SLTI_OP, 1, $2.i, - incr_expr_offset ((imm_expr *)$3.p, 1)); - i_type_inst (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - else - { - /* Use $at */ - /* Can't add 1 to immediate since 0xffffffff+1 = 0 < 1 */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst (Y_BEQ_OP, $2.i, 1, (imm_expr *)$4.p); - r_type_inst (Y_SLTU_OP, 1, $2.i, 1); - i_type_inst (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | J_OPS LABEL - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - j_type_inst (Y_J_OP, (imm_expr *)$2.p); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - j_type_inst (Y_JAL_OP, (imm_expr *)$2.p); - free ((imm_expr *)$2.p); - } - - | J_OPS SRC1 - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - r_type_inst (Y_JR_OP, 0, $2.i, 0); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - r_type_inst (Y_JALR_OP, 31, $2.i, 0); - } - - | J_OPS DEST SRC1 - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - r_type_inst (Y_JR_OP, 0, $3.i, 0); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - r_type_inst (Y_JALR_OP, $2.i, $3.i, 0); - } - - - | B_OPS LABEL - { - i_type_inst_free (($1.i == Y_BAL_POP ? Y_BGEZAL_OP : Y_BGEZ_OP), - 0, 0, (imm_expr *)$2.p); - } - - - | BINARYI_TRAP_OPS SRC1 IMM16 - { - i_type_inst_free ($1.i, 0, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_TRAP_OPS SRC1 SRC2 - { - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - - | FP_MOVE_OPS F_DEST F_SRC1 - { - r_co_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_MOVE_OPS_REV2 F_DEST F_SRC1 - { - mips32_r2_inst (); - } - - - | MOVEC_OPS DEST SRC1 REG - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | MOVECC_OPS DEST SRC1 Y_INT - { - r_type_inst ($1.i, - $2.i, - $3.i, - (($4.i & 0x7) << 2)); - } - - - | FP_MOVEC_OPS F_DEST F_SRC1 REG - { - r_co_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | FP_MOVEC_OPS_REV2 F_DEST F_SRC1 REG - { - mips32_r2_inst (); - } - - - | FP_MOVECC_OPS F_DEST F_SRC1 - { - r_co_type_inst ($1.i, $2.i, $3.i, cc_to_rt (0, 0, 0)); - } - - - | FP_MOVECC_OPS F_DEST F_SRC1 CC_REG - { - r_co_type_inst ($1.i, $2.i, $3.i, cc_to_rt ($4.i, 0, 0)); - } - - - | FP_MOVECC_OPS_REV2 F_DEST F_SRC1 CC_REG - { - mips32_r2_inst (); - } - - - | MOVE_FROM_HILO_OPS REG - { - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | MOVE_TO_HILO_OPS REG - { - r_type_inst ($1.i, 0, $2.i, 0); - } - - - - | MOVE_COP_OPS REG COP_REG - { - if ($1.i == Y_MFC1_D_POP) - { - r_co_type_inst (Y_MFC1_OP, 0, $3.i, $2.i); - r_co_type_inst (Y_MFC1_OP, 0, $3.i + 1, $2.i + 1); - } - else if ($1.i == Y_MTC1_D_POP) - { - r_co_type_inst (Y_MTC1_OP, 0, $3.i, $2.i); - r_co_type_inst (Y_MTC1_OP, 0, $3.i + 1, $2.i + 1); - } - else - r_co_type_inst ($1.i, 0, $3.i, $2.i); - } - - - | MOVE_COP_OPS_REV2 REG COP_REG - { - mips32_r2_inst (); - } - - - | CTL_COP_OPS REG COP_REG - { - r_co_type_inst ($1.i, 0, $3.i, $2.i); - } - - - | FP_UNARY_OPS F_DEST F_SRC2 - { - r_co_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_UNARY_OPS_REV2 F_DEST F_SRC2 - { - mips32_r2_inst (); - } - - - | FP_BINARY_OPS F_DEST F_SRC1 F_SRC2 - { - r_co_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | FP_BINARY_OPS_REV2 F_DEST F_SRC1 F_SRC2 - { - mips32_r2_inst (); - } - - - | FP_TERNARY_OPS_REV2 F_DEST F_SRC1 F_SRC2 FP_REGISTER - { - mips32_r2_inst (); - } - - - | FP_CMP_OPS F_SRC1 F_SRC2 - { - r_cond_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_CMP_OPS CC_REG F_SRC1 F_SRC2 - { - r_cond_type_inst ($1.i, $3.i, $4.i, $2.i); - } - - - | FP_CMP_OPS_REV2 F_SRC1 F_SRC2 - { - mips32_r2_inst (); - } - - - | Y_COP2_OP IMM32 - { - i_type_inst_free ($1.i, 0, 0, (imm_expr *)$2.p); - } - ; - - - -LOAD_OPS: Y_LB_OP - | Y_LBU_OP - | Y_LH_OP - | Y_LHU_OP - | Y_LL_OP - | Y_LW_OP - | Y_LWL_OP - | Y_LWR_OP - | Y_PFW_OP - | Y_LD_POP - ; - -LOADI_OPS: Y_LUI_OP - ; - -ULOADH_POPS: Y_ULH_POP - | Y_ULHU_POP - ; - -LOADC_OPS: Y_LDC2_OP - | Y_LWC2_OP - ; - -LOADFP_OPS: Y_LDC1_OP - | Y_LWC1_OP - | Y_L_D_POP { $$.i = Y_LDC1_OP; } - | Y_L_S_POP { $$.i = Y_LWC1_OP; } - ; - -LOADFP_INDEX_OPS: Y_LDXC1_OP - | Y_LUXC1_OP - | Y_LWXC1_OP - ; - -STORE_OPS: Y_SB_OP - | Y_SC_OP - | Y_SH_OP - | Y_SW_OP - | Y_SWL_OP - | Y_SWR_OP - | Y_SD_POP - ; - -STOREC_OPS: Y_SWC2_OP - | Y_SDC2_OP - | Y_S_D_POP { $$.i = Y_SDC1_OP; } - | Y_S_S_POP { $$.i = Y_SWC1_OP; } - ; - -STOREFP_OPS: Y_SWC1_OP - | Y_SDC1_OP - ; - -STOREFP_INDEX_OPS: Y_SDXC1_OP - | Y_SUXC1_OP - | Y_SWXC1_OP - ; - -SYS_OPS: Y_RFE_OP - { -#ifdef MIPS1 - yywarn ("RFE should only be used when SPIM is compiled as a MIPS-I processor"); -#endif - } - | Y_SYSCALL_OP - ; - -PREFETCH_OPS: Y_PREFX_OP - | Y_SYNCI_OP - ; - -CACHE_OPS: Y_CACHE_OP - | Y_PREF_OP - ; - -TLB_OPS: Y_TLBP_OP - | Y_TLBR_OP - | Y_TLBWI_OP - | Y_TLBWR_OP - ; - -NULLARY_OPS: Y_ERET_OP - { -#ifdef MIPS1 - yywarn ("ERET should only be used when SPIM is compiled as a MIPS32 processor"); -#endif - } - ; - -NULLARY_OPS_REV2: Y_DERET_OP - | Y_EHB_OP - | Y_SDBBP_OP - ; - -COUNT_LEADING_OPS: Y_CLO_OP - | Y_CLZ_OP - ; - -UNARY_OPS_REV2: Y_DI_OP - | Y_EI_OP - ; - -/* These binary operations have immediate analogues. */ - -BINARYI_OPS: Y_ADD_OP - | Y_ADDU_OP - | Y_AND_OP - | Y_XOR_OP - | Y_OR_OP - | Y_SLT_OP - | Y_SLTU_OP - ; - -BINARYIR_OPS: Y_SLLV_OP - | Y_SRAV_OP - | Y_SRLV_OP - ; - -BINARY_ARITHI_OPS: Y_ADDI_OP - | Y_ADDIU_OP - | Y_SLTI_OP - | Y_SLTIU_OP - ; - -BINARY_LOGICALI_OPS: Y_ANDI_OP - | Y_ORI_OP - | Y_XORI_OP - ; - -SHIFT_OPS: Y_SLL_OP - | Y_SRA_OP - | Y_SRL_OP - ; - -SHIFT_OPS_REV2: Y_ROTR_OP - ; - -SHIFTV_OPS_REV2: Y_ROTRV_OP - ; - - -/* These binary operations do not have immediate analogues. */ - -BINARY_OPS: Y_NOR_OP - ; - -BINARY_OPS_REV2: Y_RDHWR_OP - | Y_RDPGPR_OP - | Y_SEB_OP - | Y_SEH_OP - | Y_WRPGPR_OP - | Y_WSBH_OP - ; - -SUB_OPS: Y_SUB_OP - | Y_SUBU_OP - ; - -DIV_POPS: Y_DIV_OP - | Y_DIVU_OP - | Y_REM_POP - | Y_REMU_POP - ; - -MUL_POPS: Y_MULO_POP - | Y_MULOU_POP - ; - -SET_LE_POPS: Y_SLE_POP - | Y_SLEU_POP - ; - -SET_GT_POPS: Y_SGT_POP - | Y_SGTU_POP - ; - -SET_GE_POPS: Y_SGE_POP - | Y_SGEU_POP - ; - -SET_EQ_POPS: Y_SEQ_POP - | Y_SNE_POP - ; - -MULT_OPS: Y_MULT_OP - | Y_MULTU_OP - | Y_MADD_OP - | Y_MADDU_OP - | Y_MSUB_OP - | Y_MSUBU_OP - ; - -MULT_OPS3: Y_MUL_OP - ; - -BF_OPS_REV2: Y_EXT_OP - | Y_INS_OP - ; - -BR_COP_OPS: Y_BC1F_OP - | Y_BC1FL_OP - | Y_BC1T_OP - | Y_BC1TL_OP - | Y_BC2F_OP - | Y_BC2FL_OP - | Y_BC2T_OP - | Y_BC2TL_OP - ; - -UNARY_BR_OPS: Y_BGEZ_OP - | Y_BGEZL_OP - | Y_BGEZAL_OP - | Y_BGEZALL_OP - | Y_BGTZ_OP - | Y_BGTZL_OP - | Y_BLEZ_OP - | Y_BLEZL_OP - | Y_BLTZ_OP - | Y_BLTZL_OP - | Y_BLTZAL_OP - | Y_BLTZALL_OP - ; - -UNARY_BR_POPS: Y_BEQZ_POP - | Y_BNEZ_POP - ; - -BINARY_BR_OPS: Y_BEQ_OP - | Y_BEQL_OP - | Y_BNE_OP - | Y_BNEL_OP - ; - -BR_GT_POPS: Y_BGT_POP - | Y_BGTU_POP - -BR_GE_POPS: Y_BGE_POP - | Y_BGEU_POP - -BR_LT_POPS: Y_BLT_POP - | Y_BLTU_POP - -BR_LE_POPS: Y_BLE_POP - | Y_BLEU_POP - ; - -J_OPS: Y_J_OP - | Y_JR_OP - | Y_JR_HB_OP { yywarn ("Warning:IPS32 Rev 2 '.HB' extension is not implemented and is ignored"); } - | Y_JAL_OP - | Y_JALR_OP - | Y_JALR_HB_OP { yywarn ("Warning:IPS32 Rev 2 '.HB' extension is not implemented and is ignored"); } - ; - -B_OPS: Y_B_POP - | Y_BAL_POP - ; - - -BINARYI_TRAP_OPS: Y_TEQI_OP - | Y_TGEI_OP - | Y_TGEIU_OP - | Y_TLTI_OP - | Y_TLTIU_OP - | Y_TNEI_OP - ; - -BINARY_TRAP_OPS: Y_TEQ_OP - | Y_TGE_OP - | Y_TGEU_OP - | Y_TLT_OP - | Y_TLTU_OP - | Y_TNE_OP - ; - - -MOVE_FROM_HILO_OPS: Y_MFHI_OP - | Y_MFLO_OP - ; - -MOVE_TO_HILO_OPS: Y_MTHI_OP - | Y_MTLO_OP - ; - -MOVEC_OPS: Y_MOVN_OP - | Y_MOVZ_OP - ; - -MOVE_COP_OPS: Y_MFC0_OP - | Y_MFC1_OP - | Y_MFC1_D_POP - | Y_MFC2_OP - | Y_MTC0_OP - | Y_MTC1_OP - | Y_MTC1_D_POP - | Y_MTC2_OP - ; - -MOVE_COP_OPS_REV2: Y_MFHC1_OP - | Y_MFHC2_OP - | Y_MTHC1_OP - | Y_MTHC2_OP - ; - -CTL_COP_OPS: Y_CFC0_OP - | Y_CFC1_OP - | Y_CFC2_OP - | Y_CTC0_OP - | Y_CTC1_OP - | Y_CTC2_OP - ; - -/* Floating point operations */ - -FP_MOVE_OPS: Y_MOV_S_OP - | Y_MOV_D_OP - ; - -FP_MOVE_OPS_REV2: Y_MOV_PS_OP - ; - - -MOVECC_OPS: Y_MOVF_OP - | Y_MOVT_OP - ; - - -FP_MOVEC_OPS: Y_MOVN_D_OP - | Y_MOVN_S_OP - | Y_MOVZ_D_OP - | Y_MOVZ_S_OP - ; - -FP_MOVEC_OPS_REV2: Y_MOVN_PS_OP - | Y_MOVZ_PS_OP - ; - - -FP_MOVECC_OPS: Y_MOVF_D_OP - | Y_MOVF_S_OP - | Y_MOVT_D_OP - | Y_MOVT_S_OP - ; - -FP_MOVECC_OPS_REV2: Y_MOVF_PS_OP - | Y_MOVT_PS_OP - ; - -FP_UNARY_OPS: Y_ABS_S_OP - | Y_ABS_D_OP - | Y_CEIL_W_D_OP - | Y_CEIL_W_S_OP - | Y_CVT_D_S_OP - | Y_CVT_D_W_OP - | Y_CVT_S_D_OP - | Y_CVT_S_W_OP - | Y_CVT_W_D_OP - | Y_CVT_W_S_OP - | Y_FLOOR_W_D_OP - | Y_FLOOR_W_S_OP - | Y_NEG_S_OP - | Y_NEG_D_OP - | Y_ROUND_W_D_OP - | Y_ROUND_W_S_OP - | Y_SQRT_D_OP - | Y_SQRT_S_OP - | Y_TRUNC_W_D_OP - | Y_TRUNC_W_S_OP - ; - -FP_UNARY_OPS_REV2: Y_ABS_PS_OP - | Y_CEIL_L_D_OP - | Y_CEIL_L_S_OP - | Y_CVT_D_L_OP - | Y_CVT_L_D_OP - | Y_CVT_L_S_OP - | Y_CVT_PS_S_OP - | Y_CVT_S_L_OP - | Y_CVT_S_PL_OP - | Y_CVT_S_PU_OP - | Y_FLOOR_L_D_OP - | Y_FLOOR_L_S_OP - | Y_NEG_PS_OP - | Y_RECIP_D_OP - | Y_RECIP_S_OP - | Y_ROUND_L_D_OP - | Y_ROUND_L_S_OP - | Y_RSQRT_D_OP - | Y_RSQRT_S_OP - | Y_TRUNC_L_D_OP - | Y_TRUNC_L_S_OP - ; - -FP_BINARY_OPS: Y_ADD_S_OP - | Y_ADD_D_OP - | Y_DIV_S_OP - | Y_DIV_D_OP - | Y_MUL_S_OP - | Y_MUL_D_OP - | Y_SUB_S_OP - | Y_SUB_D_OP - ; - -FP_BINARY_OPS_REV2: Y_ADD_PS_OP - | Y_MUL_PS_OP - | Y_PLL_PS_OP - | Y_PLU_PS_OP - | Y_PUL_PS_OP - | Y_PUU_PS_OP - ; - -FP_TERNARY_OPS_REV2: Y_ALNV_PS_OP - | Y_MADD_D_OP - | Y_MADD_PS_OP - | Y_MADD_S_OP - | Y_MSUB_D_OP - | Y_MSUB_PS_OP - | Y_MSUB_S_OP - | Y_NMADD_D_OP - | Y_NMADD_PS_OP - | Y_NMADD_S_OP - | Y_NMSUB_D_OP - | Y_NMSUB_PS_OP - | Y_NMSUB_S_OP - ; - -FP_CMP_OPS: Y_C_F_S_OP - | Y_C_UN_S_OP - | Y_C_EQ_S_OP - | Y_C_UEQ_S_OP - | Y_C_OLT_S_OP - | Y_C_OLE_S_OP - | Y_C_ULT_S_OP - | Y_C_ULE_S_OP - | Y_C_SF_S_OP - | Y_C_NGLE_S_OP - | Y_C_SEQ_S_OP - | Y_C_NGL_S_OP - | Y_C_LT_S_OP - | Y_C_NGE_S_OP - | Y_C_LE_S_OP - | Y_C_NGT_S_OP - | Y_C_F_D_OP - | Y_C_UN_D_OP - | Y_C_EQ_D_OP - | Y_C_UEQ_D_OP - | Y_C_OLT_D_OP - | Y_C_OLE_D_OP - | Y_C_ULT_D_OP - | Y_C_ULE_D_OP - | Y_C_SF_D_OP - | Y_C_NGLE_D_OP - | Y_C_SEQ_D_OP - | Y_C_NGL_D_OP - | Y_C_LT_D_OP - | Y_C_NGE_D_OP - | Y_C_LE_D_OP - | Y_C_NGT_D_OP - ; - -FP_CMP_OPS_REV2: Y_C_EQ_PS_OP - | Y_C_F_PS_OP - | Y_C_LT_PS_OP - | Y_C_LE_PS_OP - | Y_C_NGE_PS_OP - | Y_C_NGL_PS_OP - | Y_C_NGLE_PS_OP - | Y_C_NGT_PS_OP - | Y_C_OLE_PS_OP - | Y_C_OLT_PS_OP - | Y_C_SEQ_PS_OP - | Y_C_SF_PS_OP - | Y_C_UEQ_PS_OP - | Y_C_ULE_PS_OP - | Y_C_ULT_PS_OP - | Y_C_UN_PS_OP - ; - - - -ASM_DIRECTIVE: Y_ALIAS_DIR Y_REG Y_REG - - | Y_ALIGN_DIR EXPR - { - align_data ($2.i); - } - - | Y_ASCII_DIR {null_term = false;} STR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - | Y_ASCIIZ_DIR {null_term = true;} STR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_ASM0_DIR - - | Y_BGNB_DIR Y_INT - - - | Y_BYTE_DIR - {store_op = (void(*)(void*))store_byte;} - EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_COMM_DIR ID EXPR - { - align_data (2); - if (lookup_label ((char*)$2.p)->addr == 0) - { - (void)record_label ((char*)$2.p, current_data_pc (), 1); - free ((char*)$2.p); - } - increment_data_pc ($3.i); - } - - - | Y_DATA_DIR - {user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_DATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_K_DATA_DIR - { - user_kernel_data_segment (true); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_K_DATA_DIR Y_INT - { - user_kernel_data_segment (true); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_DOUBLE_DIR - { - store_op = (void(*)(void*))store_double; - if (data_dir) set_data_alignment (3); - } - FP_EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_END_DIR OPTIONAL_ID - - | Y_ENDB_DIR Y_INT - - | Y_ENDR_DIR - - | Y_ENT_DIR ID - - | Y_ENT_DIR ID Y_INT - - - | Y_EXTERN_DIR ID EXPR - { - extern_directive ((char*)$2.p, $3.i); - } - - - | Y_ERR_DIR - { - fatal_error ("File contains an .err directive\n"); - } - - - | Y_FILE_DIR Y_INT Y_STR - - - | Y_FLOAT_DIR - { - store_op = (void(*)(void*))store_float; - if (data_dir) set_data_alignment (2); - } - FP_EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_FMASK_DIR Y_INT Y_INT - - | Y_FRAME_DIR REGISTER Y_INT REGISTER - - - | Y_GLOBAL_DIR ID - { - (void)make_label_global ((char*)$2.p); - free ((char*)$2.p); - } - - - | Y_HALF_DIR - { - store_op = (void(*)(void*))store_half; - if (data_dir) set_data_alignment (1); - } - EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_LABEL_DIR ID - { - (void)record_label ((char*)$2.p, - text_dir ? current_text_pc () : current_data_pc (), - 1); - free ((char*)$2.p); - } - - - | Y_LCOMM_DIR ID EXPR - { - lcomm_directive ((char*)$2.p, $3.i); - } - - - /* Produced by cc 2.10 */ - | Y_LIVEREG_DIR Y_INT Y_INT - - - | Y_LOC_DIR Y_INT Y_INT - - | Y_MASK_DIR Y_INT Y_INT - - | Y_NOALIAS_DIR Y_REG Y_REG - - | Y_OPTIONS_DIR ID - - | Y_REPEAT_DIR EXPR - { - yyerror ("Warning: repeat directive ignored"); - } - - - | Y_RDATA_DIR - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_RDATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_SDATA_DIR - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_SDATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_SET_DIR ID - { - if (streq ((char*)$2.p, "noat")) - noat_flag = true; - else if (streq ((char*)$2.p, "at")) - noat_flag = false; - } - - - | Y_SPACE_DIR EXPR - { - if (data_dir) - increment_data_pc ($2.i); - else if (text_dir) - increment_text_pc ($2.i); - } - - - | Y_STRUCT_DIR EXPR - { - yyerror ("Warning: struct directive ignored"); - } - - - | Y_TEXT_DIR - { - user_kernel_text_segment (false); - data_dir = false; text_dir = true; - enable_data_alignment (); - } - - | Y_TEXT_DIR Y_INT - { - user_kernel_text_segment (false); - data_dir = false; text_dir = true; - enable_data_alignment (); - set_text_pc ($2.i); - } - - - | Y_K_TEXT_DIR - { - user_kernel_text_segment (true); - data_dir = false; text_dir = true; - enable_data_alignment (); - } - - | Y_K_TEXT_DIR Y_INT - { - user_kernel_text_segment (true); - data_dir = false; text_dir = true; - enable_data_alignment (); - set_text_pc ($2.i); - } - - - | Y_VERSTAMP_DIR Y_INT Y_INT - - | Y_VREG_DIR REGISTER Y_INT Y_INT - - - | Y_WORD_DIR - { - store_op = (void(*)(void*))store_word_data; - if (data_dir) set_data_alignment (2); - } - EXPR_LST - - ; - - - -ADDRESS: {only_id = 1;} ADDR {only_id = 0; $$ = $2;} - -ADDR: '(' REGISTER ')' - { - $$.p = make_addr_expr (0, NULL, $2.i); - } - - | ABS_ADDR - { - $$.p = make_addr_expr ($1.i, NULL, 0); - } - - | ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr ($1.i, NULL, $3.i); - } - - | Y_ID - { - $$.p = make_addr_expr (0, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | Y_ID '(' REGISTER ')' - { - $$.p = make_addr_expr (0, (char*)$1.p, $3.i); - free ((char*)$1.p); - } - - | Y_ID '+' ABS_ADDR - { - $$.p = make_addr_expr ($3.i, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | ABS_ADDR '+' ID - { - $$.p = make_addr_expr ($1.i, (char*)$3.p, 0); - } - - | Y_ID '-' ABS_ADDR - { - $$.p = make_addr_expr (- $3.i, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | Y_ID '+' ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr ($3.i, (char*)$1.p, $5.i); - free ((char*)$1.p); - } - - | Y_ID '-' ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr (- $3.i, (char*)$1.p, $5.i); - free ((char*)$1.p); - } - ; - - -BR_IMM32: {only_id = 1;} IMM32 {only_id = 0; $$ = $2;} - -IMM16: IMM32 - { - check_imm_range ((imm_expr*)$1.p, IMM_MIN, IMM_MAX); - $$ = $1; - } - -UIMM16: IMM32 - { - check_uimm_range ((imm_expr*)$1.p, UIMM_MIN, UIMM_MAX); - $$ = $1; - } - - -IMM32: ABS_ADDR - { - $$.p = make_imm_expr ($1.i, NULL, false); - } - - | '(' ABS_ADDR ')' '>' '>' Y_INT - { - $$.p = make_imm_expr ($2.i >> $6.i, NULL, false); - } - - | ID - { - $$.p = make_imm_expr (0, (char*)$1.p, false); - } - - | Y_ID '+' ABS_ADDR - { - $$.p = make_imm_expr ($3.i, (char*)$1.p, false); - free ((char*)$1.p); - } - - | Y_ID '-' ABS_ADDR - { - $$.p = make_imm_expr (- $3.i, (char*)$1.p, false); - free ((char*)$1.p); - } - ; - - -ABS_ADDR: Y_INT - - | Y_INT '+' Y_INT - {$$.i = $1.i + $3.i;} - - | Y_INT Y_INT - { - /* This is actually: Y_INT '-' Y_INT, since the binary - subtract operator gets scanned as a unary negation - operator. */ - if ($2.i >= 0) yyerror ("Syntax error"); - $$.i = $1.i - -$2.i; - } - ; - -SRC1: REGISTER ; - -SRC2: REGISTER ; - -DEST: REGISTER ; - -REG: REGISTER ; - -REGISTER: Y_REG - { - if ($1.i < 0 || $1.i > 31) - yyerror ("Register number out of range"); - if ($1.i == 1 && !bare_machine && !noat_flag) - yyerror ("Register 1 is reserved for assembler"); - $$ = $1; - } - -F_DEST: FP_REGISTER ; - -F_SRC1: FP_REGISTER ; - -F_SRC2: FP_REGISTER ; - -FP_REGISTER: Y_FP_REG - { - if ($1.i < 0 || $1.i > 31) - yyerror ("FP register number out of range"); - $$ = $1; - } - - -CC_REG: Y_INT - { - if ($1.i < 0 || $1.i > 7) - yyerror ("CC register number out of range"); - $$ = $1; - } - - -COP_REG: Y_REG - - | Y_FP_REG - - ; - - -LABEL: ID - { - $$.p = make_imm_expr (-(int)current_text_pc (), (char*)$1.p, true); - } - - -STR_LST: STR_LST STR - | STR - ; - - -STR: Y_STR - { - store_string ((char*)$1.p, strlen((char*)$1.p), null_term); - free ((char*)$1.p); - } - | Y_STR ':' Y_INT - { - int i; - - for (i = 0; i < $3.i; i ++) - store_string ((char*)$1.p, strlen((char*)$1.p), null_term); - free ((char*)$1.p); - } - ; - - -EXPRESSION: {only_id = 1;} EXPR {only_id = 0; $$ = $2;} - -EXPR: - TRM - | - EXPR '+' TRM - { $$.i = $1.i + $3.i; } - | - EXPR '-' TRM - { $$.i = $1.i - $3.i; } - ; - -TRM: - FACTOR - | - TRM '*' FACTOR - { $$.i = $1.i * $3.i; } - | - TRM '/' FACTOR - { $$.i = $1.i / $3.i; } - ; - -FACTOR: Y_INT - - | '(' EXPR ')' - { $$.i = $2.i; } - - | ID - { - label *l = lookup_label ((char*)$1.p); - if (l->addr == 0) - { - record_data_uses_symbol (current_data_pc (), l); - $$.p = NULL; - } - else - $$.i = l->addr; - } - - -EXPR_LST: EXPR_LST EXPRESSION - { - store_op ($2.p); - } - | EXPRESSION - { - store_op ($1.p); - } - | EXPRESSION ':' EXPR - { - int i; - - for (i = 0; i < $3.i; i ++) - store_op ($1.p); - } - ; - - -FP_EXPR_LST: FP_EXPR_LST Y_FP - { - store_op ($2.p); - } - | Y_FP - { - store_op ($1.p); - } - ; - - -OPTIONAL_ID: {only_id = 1;} OPT_ID {only_id = 0; $$ = $2;} - -OPT_ID: ID - | {$$.p = (void*)NULL;} - ; - - -ID: {only_id = 1;} Y_ID {only_id = 0; $$ = $2;} - - -%% - -/* Maintain and update the address of labels for the current line. */ - -void -fix_current_label_address (mem_addr new_addr) -{ - label_list *l; - - for (l = this_line_labels; l != NULL; l = l->tail) - { - l->head->addr = new_addr; - } - clear_labels (); -} - - -static label_list * -cons_label (label *head, label_list *tail) -{ - label_list *c = (label_list *) malloc (sizeof (label_list)); - - c->head = head; - c->tail = tail; - return (c); -} - - -static void -clear_labels () -{ - label_list *n; - - for ( ; this_line_labels != NULL; this_line_labels = n) - { - resolve_label_uses (this_line_labels->head); - n = this_line_labels->tail; - free (this_line_labels); - } - this_line_labels = NULL; -} - - -/* Operations on op codes. */ - -int -op_to_imm_op (int opcode) -{ - switch (opcode) - { - case Y_ADD_OP: return (Y_ADDI_OP); - case Y_ADDU_OP: return (Y_ADDIU_OP); - case Y_AND_OP: return (Y_ANDI_OP); - case Y_OR_OP: return (Y_ORI_OP); - case Y_XOR_OP: return (Y_XORI_OP); - case Y_SLT_OP: return (Y_SLTI_OP); - case Y_SLTU_OP: return (Y_SLTIU_OP); - case Y_SLLV_OP: return (Y_SLL_OP); - case Y_SRAV_OP: return (Y_SRA_OP); - case Y_SRLV_OP: return (Y_SRL_OP); - default: fatal_error ("Can't convert op to immediate op\n"); return (0); - } -} - - -int -imm_op_to_op (int opcode) -{ - switch (opcode) - { - case Y_ADDI_OP: return (Y_ADD_OP); - case Y_ADDIU_OP: return (Y_ADDU_OP); - case Y_ANDI_OP: return (Y_AND_OP); - case Y_ORI_OP: return (Y_OR_OP); - case Y_XORI_OP: return (Y_XOR_OP); - case Y_SLTI_OP: return (Y_SLT_OP); - case Y_SLTIU_OP: return (Y_SLTU_OP); - case Y_J_OP: return (Y_JR_OP); - case Y_LUI_OP: return (Y_ADDU_OP); - case Y_SLL_OP: return (Y_SLLV_OP); - case Y_SRA_OP: return (Y_SRAV_OP); - case Y_SRL_OP: return (Y_SRLV_OP); - default: fatal_error ("Can't convert immediate op to op\n"); return (0); - } -} - - -static void -nop_inst () -{ - r_type_inst (Y_SLL_OP, 0, 0, 0); /* = 0 */ -} - - -static void -trap_inst () -{ - r_type_inst (Y_BREAK_OP, 0, 0, 0); -} - - -static imm_expr * -branch_offset (int n_inst) -{ - return (const_imm_expr (n_inst << 2)); /* Later shifted right 2 places */ -} - - -static void -div_inst (int op, int rd, int rs, int rt, int const_divisor) -{ - if (rd != 0 && !const_divisor) - { - i_type_inst_free (Y_BNE_OP, 0, rt, branch_offset (2)); - trap_inst (); - } - - if (op == Y_DIV_OP || op == Y_REM_POP) - r_type_inst (Y_DIV_OP, 0, rs, rt); - else - r_type_inst (Y_DIVU_OP, 0, rs, rt); - - if (rd != 0) - { - if (op == Y_DIV_OP || op == Y_DIVU_OP) - /* Quotient */ - r_type_inst (Y_MFLO_OP, rd, 0, 0); - else - /* Remainder */ - r_type_inst (Y_MFHI_OP, rd, 0, 0); - } -} - - -static void -mult_inst (int op, int rd, int rs, int rt) -{ - if (op == Y_MULOU_POP) - r_type_inst (Y_MULTU_OP, 0, rs, rt); - else - r_type_inst (Y_MULT_OP, 0, rs, rt); - if (op == Y_MULOU_POP && rd != 0) - { - r_type_inst (Y_MFHI_OP, 1, 0, 0); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, branch_offset (2)); - trap_inst (); - } - else if (op == Y_MULO_POP && rd != 0) - { - r_type_inst (Y_MFHI_OP, 1, 0, 0); /* use $at */ - r_type_inst (Y_MFLO_OP, rd, 0, 0); - r_sh_type_inst (Y_SRA_OP, rd, rd, 31); - i_type_inst_free (Y_BEQ_OP, rd, 1, branch_offset (2)); - trap_inst (); - } - if (rd != 0) - r_type_inst (Y_MFLO_OP, rd, 0, 0); -} - - -static void -set_le_inst (int op, int rd, int rs, int rt) -{ - i_type_inst_free (Y_BNE_OP, rs, rt, branch_offset (3)); - i_type_inst_free (Y_ORI_OP, rd, 0, const_imm_expr (1)); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); - r_type_inst ((op == Y_SLE_POP ? Y_SLT_OP : Y_SLTU_OP), rd, rs, rt); -} - - -static void -set_gt_inst (int op, int rd, int rs, int rt) -{ - r_type_inst (op == Y_SGT_POP ? Y_SLT_OP : Y_SLTU_OP, rd, rt, rs); -} - - -static void -set_ge_inst (int op, int rd, int rs, int rt) -{ - i_type_inst_free (Y_BNE_OP, rs, rt, branch_offset (3)); - i_type_inst_free (Y_ORI_OP, rd, 0, const_imm_expr (1)); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); - r_type_inst (op == Y_SGE_POP ? Y_SLT_OP : Y_SLTU_OP, rd, rt, rs); -} - - -static void -set_eq_inst (int op, int rd, int rs, int rt) -{ - imm_expr *if_eq, *if_neq; - - if (op == Y_SEQ_POP) - if_eq = const_imm_expr (1), if_neq = const_imm_expr (0); - else - if_eq = const_imm_expr (0), if_neq = const_imm_expr (1); - - i_type_inst_free (Y_BEQ_OP, rs, rt, branch_offset (3)); - /* RD <- 0 (if not equal) */ - i_type_inst_free (Y_ORI_OP, rd, 0, if_neq); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); /* Branch always */ - /* RD <- 1 */ - i_type_inst_free (Y_ORI_OP, rd, 0, if_eq); -} - - -/* Store the value either as a datum or instruction. */ - -static void -store_word_data (int value) -{ - if (data_dir) - store_word (value); - else if (text_dir) - store_instruction (inst_decode (value)); -} - - - -void -initialize_parser (char *file_name) -{ - input_file_name = file_name; - only_id = 0; - data_dir = false; - text_dir = true; -} - - -static void -check_imm_range (imm_expr* expr, int32 min, int32 max) -{ - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* If expression can be evaluated, compare its value against the limits - and complain if the value is out of bounds. */ - int32 value = eval_imm_expr (expr); - - if (value < min || max < value) - { - char str[200]; - sprintf (str, "immediate value (%d) out of range (%d .. %d)", - value, min, max); - yywarn (str); - } - } -} - - -static void -check_uimm_range (imm_expr* expr, uint32 min, uint32 max) -{ - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* If expression can be evaluated, compare its value against the limits - and complain if the value is out of bounds. */ - uint32 value = (uint32)eval_imm_expr (expr); - - if (value < min || max < value) - { - char str[200]; - sprintf (str, "immediate value (%d) out of range (%d .. %d)", - (int32)value, (int32)min, (int32)max); - yywarn (str); - } - } -} - -void -yyerror (char *s) -{ - parse_error_occurred = true; - clear_labels (); - yywarn (s); -} - - -void -yywarn (char *s) -{ - error ("spim: (parser) %s on line %d of file %s\n%s", s, line_no, input_file_name, erroneous_line ()); -} - - -static void -mips32_r2_inst () -{ - yyerror ("Warning: MIPS32 Rev 2 instruction is not implemented. Instruction ignored."); -} - - -static int -cc_to_rt (int cc, int nd, int tf) -{ - return (cc << 2) | (nd << 1) | tf; -} diff --git a/spim-jsspim/CPU/reg.h b/spim-jsspim/CPU/reg.h deleted file mode 100755 index 6015c43..0000000 --- a/spim-jsspim/CPU/reg.h +++ /dev/null @@ -1,245 +0,0 @@ -/* SPIM S20 MIPS simulator. - Declarations of registers and code for accessing them. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -typedef int32 /*@alt unsigned int @*/ reg_word; -typedef uint32 u_reg_word; - - -/* General purpose registers: */ - -#define R_LENGTH 32 - -extern reg_word R[R_LENGTH]; - -extern reg_word HI, LO; - -extern mem_addr PC, nPC; - - -/* Argument passing registers */ - -#define REG_V0 2 -#define REG_A0 4 -#define REG_A1 5 -#define REG_A2 6 -#define REG_A3 7 -#define REG_FA0 12 -#define REG_SP 29 - - -/* Result registers */ - -#define REG_RES 2 -#define REG_FRES 0 - - -/* $gp registers */ - -#define REG_GP 28 - -extern char *int_reg_names[]; - - - -/* Coprocessor registers: */ - -extern reg_word CCR[4][32], CPR[4][32]; - - - -/* Exeception handling registers (Coprocessor 0): */ - -/* BadVAddr register: */ -#define CP0_BadVAddr_Reg 8 -#define CP0_BadVAddr (CPR[0][CP0_BadVAddr_Reg]) - -/* Count register: */ -#define CP0_Count_Reg 9 -#define CP0_Count (CPR[0][CP0_Count_Reg]) /* ToDo */ - -/* Compare register: */ -#define CP0_Compare_Reg 11 -#define CP0_Compare (CPR[0][CP0_Compare_Reg]) /* ToDo */ - -/* Status register: */ -#define CP0_Status_Reg 12 -#define CP0_Status (CPR[0][CP0_Status_Reg]) -/* Implemented fields: */ -#define CP0_Status_CU 0xf0000000 -#define CP0_Status_IM 0x0000ff00 -#define CP0_Status_IM7 0x00008000 /* HW Int 5 */ -#define CP0_Status_IM6 0x00004000 /* HW Int 4 */ -#define CP0_Status_IM5 0x00002000 /* HW Int 3 */ -#define CP0_Status_IM4 0x00001000 /* HW Int 2 */ -#define CP0_Status_IM3 0x00000800 /* HW Int 1 */ -#define CP0_Status_IM2 0x00000400 /* HW Int 0 */ -#define CP0_Status_IM1 0x00000200 /* SW Int 1 */ -#define CP0_Status_IM0 0x00000100 /* SW Int 0 */ -#define CP0_Status_UM 0x00000010 -#define CP0_Status_EXL 0x00000002 -#define CP0_Status_IE 0x00000001 -#define CP0_Status_Mask (CP0_Status_CU \ - | CP0_Status_UM \ - | CP0_Status_IM \ - | CP0_Status_EXL \ - | CP0_Status_IE) - -/* Cause register: */ -#define CP0_Cause_Reg 13 -#define CP0_Cause (CPR[0][CP0_Cause_Reg]) -/* Implemented fields: */ -#define CP0_Cause_BD 0x80000000 -#define CP0_Cause_IP 0x0000ff00 -#define CP0_Cause_IP7 0x00008000 /* HW Int 5 */ -#define CP0_Cause_IP6 0x00004000 /* HW Int 4 */ -#define CP0_Cause_IP5 0x00002000 /* HW Int 3 */ -#define CP0_Cause_IP4 0x00001000 /* HW Int 2 */ -#define CP0_Cause_IP3 0x00000800 /* HW Int 1 */ -#define CP0_Cause_IP2 0x00000400 /* HW Int 0 */ -#define CP0_Cause_IP1 0x00000200 /* SW Int 1 */ -#define CP0_Cause_IP0 0x00000100 /* SW Int 0 */ -#define CP0_Cause_ExcCode 0x0000007c -#define CP0_Cause_Mask (CP0_Cause_BD \ - | CP0_Cause_IP \ - | CP0_Cause_IP7 \ - | CP0_Cause_IP6 \ - | CP0_Cause_IP5 \ - | CP0_Cause_IP4 \ - | CP0_Cause_IP3 \ - | CP0_Cause_IP2 \ - | CP0_Cause_ExcCode) -#define CP0_ExCode ((CP0_Cause & CP0_Cause_ExcCode) >> 2) - -/* EPC register: */ -#define CP0_EPC_Reg 14 -#define CP0_EPC (CPR[0][CP0_EPC_Reg]) - -/* Config register: */ -#define CP0_Config_Reg 16 -#define CP0_Config (CPR[0][CP0_Config_Reg]) -/* Implemented fields: */ -#define CP0_Config_BE 0x000080000 -#define CP0_Config_AT 0x000060000 -#define CP0_Config_AR 0x00001c000 -#define CP0_Config_MT 0x000000380 -#define CP0_Config_Mask (CP0_Config_BE \ - | CP0_Config_AT \ - | CP0_Config_AR \ - | CP0_Config_MT) - - - -/* Floating Point Coprocessor (1) registers. - - This is the MIPS32, Revision 1 FPU register set. It contains 32, 32-bit - registers (either 32 single or 16 double precision), as in the R2010. - The MIPS32, Revision 2 or MIPS64 register set has 32 of each type of - register. */ - -#define FGR_LENGTH 32 -#define FPR_LENGTH 16 - -extern double *FPR; /* Dynamically allocate so overlay */ -extern float *FGR; /* is possible */ -extern int *FWR; /* is possible */ - - -#define FPR_S(REGNO) (FGR[REGNO]) - -#define FPR_D(REGNO) (((REGNO) & 0x1) \ - ? (run_error ("Odd FP double register number\n") , 0.0) \ - : FPR[(REGNO) / 2]) - -#define FPR_W(REGNO) (FWR[REGNO]) - - -#define SET_FPR_S(REGNO, VALUE) {FGR[REGNO] = (float) (VALUE);} - -#define SET_FPR_D(REGNO, VALUE) {if ((REGNO) & 0x1) \ - run_error ("Odd FP double register number\n"); \ - else FPR[(REGNO) / 2] = (double) (VALUE);} - -#define SET_FPR_W(REGNO, VALUE) {FWR[REGNO] = (int32) (VALUE);} - - -/* Floating point control registers: */ - -#define FCR (CPR[1]) - - -#define FIR_REG 0 -#define FIR (FCR[FIR_REG]) -/* Implemented fields: */ -#define FIR_W 0x0008000 -#define FIR_D 0x0001000 -#define FIR_S 0x0000800 -#define FIR_MASK (FIR_W | FIR_D | FIR_S) - -#define FCCR_REG 25 -#define FCCR (FCR[FCCR_REG]) -/* Implemented fields: */ -#define FCCR_FCC 0x000000ff -#define FCCR_MASK (FCCR_FCC) - -#define FEXR_REG 26 -#define FEXR (FCR[FEXR_REG]) -/* No implemented fields */ - -#define FENR_REG 28 -#define FENR (FCR[FENR_REG]) -/* No implemented fields */ - -#define FCSR_REG 31 -#define FCSR (FCR[FCSR_REG]) -/* Implemented fields: */ -#define FCSR_FCC 0xfe800000 -#define FCSR_MASK (FCSR_FCC) -/* Floating point Cause (not implemented): */ -#define FCSR_Cause_E 0x00020000 -#define FCSR_Cause_V 0x00010000 -#define FCSR_Cause_Z 0x00008000 -#define FCSR_Cause_O 0x00004000 -#define FCSR_Cause_U 0x00002000 -#define FCSR_Cause_I 0x00001000 -/* Floating point Enables (not implemented): */ -#define FCSR_Enable_V 0x00000800 -#define FCSR_Enable_Z 0x00000400 -#define FCSR_Enable_O 0x00000200 -#define FCSR_Enable_U 0x00000100 -#define FCSR_Enable_I 0x00000080 -/* Floating point Flags (not implemented): */ -#define FCSR_Flag_V 0x00000040 -#define FCSR_Flag_Z 0x00000020 -#define FCSR_Flag_O 0x00000010 -#define FCSR_Flag_U 0x00000008 -#define FCSR_Flag_I 0x00000004 diff --git a/spim-jsspim/CPU/run.cpp b/spim-jsspim/CPU/run.cpp deleted file mode 100755 index a3127fe..0000000 --- a/spim-jsspim/CPU/run.cpp +++ /dev/null @@ -1,1872 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM instructions. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifdef mips -#define _IEEE 1 -#include -#else -#define NaN(X) ((X) != (X)) -#endif - -#include -#include - -#ifdef _WIN32 -#define VC_EXTRALEAN -#include -#else -#include -#include -#include -#include -#endif - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser_yacc.h" -#include "syscall.h" -#include "run.h" - -bool force_break = false; /* For the execution env. to force an execution break */ - -#ifdef _MSC_BUILD -/* Disable MS VS warning about constant predicate in conditional. */ -#pragma warning(disable: 4127) -#endif - - -/* Local functions: */ - -static void bump_CP0_timer (); -static void set_fpu_cc (int cond, int cc, int less, int equal, int unordered); -static void signed_multiply (reg_word v1, reg_word v2); -static void start_CP0_timer (); -#ifdef _WIN32 -void CALLBACK timer_completion_routine(LPVOID lpArgToCompletionRoutine, - DWORD dwTimerLowValue, DWORD dwTimerHighValue); -#endif -static void unsigned_multiply (reg_word v1, reg_word v2); - - -#define SIGN_BIT(X) ((X) & 0x80000000) - -#define ARITH_OVFL(RESULT, OP1, OP2) (SIGN_BIT (OP1) == SIGN_BIT (OP2) \ - && SIGN_BIT (OP1) != SIGN_BIT (RESULT)) - - - -/* True when delayed_branches is true and instruction is executing in delay -slot of another instruction. */ -static int running_in_delay_slot = 0; - - -/* Executed delayed branch and jump instructions by running the - instruction from the delay slot before transfering control. Note, - in branches that don't jump, the instruction in the delay slot is - executed by falling through normally. - - We take advantage of the MIPS architecture, which leaves undefined - the result of executing a delayed instruction in a delay slot. Here - we execute the second branch. */ - -#define BRANCH_INST(TEST, TARGET, NULLIFY) \ - { \ - if (TEST) \ - { \ - mem_addr target = (TARGET); \ - if (delayed_branches) \ - { \ - /* +4 since jump in delay slot */ \ - target += BYTES_PER_WORD; \ - } \ - JUMP_INST(target) \ - } \ - else if (NULLIFY) \ - { \ - /* If test fails and nullify bit set, skip\ - instruction in delay slot. */ \ - PC += BYTES_PER_WORD; \ - } \ - } - - -#define JUMP_INST(TARGET) \ - { \ - if (delayed_branches) \ - { \ - running_in_delay_slot = 1; \ - run_spim (PC + BYTES_PER_WORD, 1, display);\ - running_in_delay_slot = 0; \ - } \ - /* -4 since PC is bumped after this inst */ \ - PC = (TARGET) - BYTES_PER_WORD; \ - } - - -/* If the delayed_load flag is false, the result from a load is available - immediate. If the delayed_load flag is true, the result from a load is - not available until the subsequent instruction has executed (as in the - real machine). We need a two element shift register for the value and its - destination, as the instruction following the load can itself be a load - instruction. */ - -#define LOAD_INST(DEST_A, LD, MASK) \ - { \ - LOAD_INST_BASE (DEST_A, (LD & (MASK))) \ - } - - -#define LOAD_INST_BASE(DEST_A, VALUE) \ - { \ - if (delayed_loads) \ - { \ - delayed_load_addr1 = (DEST_A); \ - delayed_load_value1 = (VALUE); \ - } \ - else \ - { \ - *(DEST_A) = (VALUE); \ - } \ - } - - -#define DO_DELAYED_UPDATE() \ - if (delayed_loads) \ - { \ - /* Check for delayed updates */ \ - if (delayed_load_addr2 != NULL) \ - { \ - *delayed_load_addr2 = delayed_load_value2; \ - } \ - delayed_load_addr2 = delayed_load_addr1; \ - delayed_load_value2 = delayed_load_value1; \ - delayed_load_addr1 = NULL; \ - } - - - -/* Run the program stored in memory, starting at address PC for - STEPS_TO_RUN instruction executions. If flag DISPLAY is true, print - each instruction before it executes. Return true if program's - execution can continue. */ - -bool -run_spim (mem_addr initial_PC, int steps_to_run, bool display) -{ - instruction *inst; - static reg_word *delayed_load_addr1 = NULL, delayed_load_value1; - static reg_word *delayed_load_addr2 = NULL, delayed_load_value2; - int step, step_size, next_step; - - PC = initial_PC; - if (!bare_machine && mapped_io) - next_step = IO_INTERVAL; - else - next_step = steps_to_run; /* Run to completion */ - - /* Start a timer running */ - start_CP0_timer(); - - for (step_size = MIN (next_step, steps_to_run); - steps_to_run > 0; - steps_to_run -= step_size, step_size = MIN (next_step, steps_to_run)) - { - if (!bare_machine && mapped_io) - /* Every IO_INTERVAL steps, check if memory-mapped IO registers - have changed. */ - check_memory_mapped_IO (); - /* else run inner loop for all steps */ - - if ((CP0_Status & CP0_Status_IE) - && !(CP0_Status & CP0_Status_EXL) - && ((CP0_Cause & CP0_Cause_IP) & (CP0_Status & CP0_Status_IM))) - { - /* There is an interrupt to process if IE bit set, EXL bit not - set, and non-masked IP bit set */ - raise_exception (ExcCode_Int); - /* Handle interrupt now, before instruction executes, so that - EPC points to unexecuted instructions, which is the one to - return to. */ - handle_exception (); - } - - force_break = false; - for (step = 0; step < step_size; step += 1) - { - if (force_break) - { - return true; - } - - R[0] = 0; /* Maintain invariant value */ - -#ifdef _WIN32 - SleepEx(0, TRUE); /* Put thread in awaitable state for WaitableTimer */ -#else - { - /* Poll for timer expiration */ - struct itimerval time; - if (-1 == getitimer (ITIMER_REAL, &time)) - { - perror ("getitmer failed"); - } - if (time.it_value.tv_usec == 0 && time.it_value.tv_sec == 0) - { - /* Timer expired */ - bump_CP0_timer (); - - /* Restart timer for next interval */ - start_CP0_timer (); - } - } -#endif - - exception_occurred = 0; - inst = read_mem_inst (PC); - if (exception_occurred) /* In reading instruction */ - { - exception_occurred = 0; - handle_exception (); - continue; - } - else if (inst == NULL) - { - run_error ("Attempt to execute non-instruction at 0x%08x\n", PC); - return false; - } - else if (EXPR (inst) != NULL - && EXPR (inst)->symbol != NULL - && EXPR (inst)->symbol->addr == 0) - { - run_error ("Instruction references undefined symbol at 0x%08x\n %s", PC, inst_to_string(PC)); - return false; - } - - if (display) - print_inst (PC); - -#ifdef TEST_ASM - test_assembly (inst); -#endif - - DO_DELAYED_UPDATE (); - - switch (OPCODE (inst)) - { - case Y_ADD_OP: - { - reg_word vs = R[RS (inst)], vt = R[RT (inst)]; - reg_word sum = vs + vt; - - if (ARITH_OVFL (sum, vs, vt)) - RAISE_EXCEPTION (ExcCode_Ov, break); - R[RD (inst)] = sum; - break; - } - - case Y_ADDI_OP: - { - reg_word vs = R[RS (inst)], imm = (short) IMM (inst); - reg_word sum = vs + imm; - - if (ARITH_OVFL (sum, vs, imm)) - RAISE_EXCEPTION (ExcCode_Ov, break); - R[RT (inst)] = sum; - break; - } - - case Y_ADDIU_OP: - R[RT (inst)] = R[RS (inst)] + (short) IMM (inst); - break; - - case Y_ADDU_OP: - R[RD (inst)] = R[RS (inst)] + R[RT (inst)]; - break; - - case Y_AND_OP: - R[RD (inst)] = R[RS (inst)] & R[RT (inst)]; - break; - - case Y_ANDI_OP: - R[RT (inst)] = R[RS (inst)] & (0xffff & IMM (inst)); - break; - - case Y_BC2F_OP: - case Y_BC2FL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_BEQ_OP: - BRANCH_INST (R[RS (inst)] == R[RT (inst)], - PC + IDISP (inst), - 0); - break; - - case Y_BEQL_OP: - BRANCH_INST (R[RS (inst)] == R[RT (inst)], - PC + IDISP (inst), - 1); - break; - - case Y_BGEZ_OP: - BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 0); - break; - - case Y_BGEZL_OP: - BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 1); - break; - - case Y_BGEZAL_OP: - R[31] = PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 0); - break; - - case Y_BGEZALL_OP: - R[31] = PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 1); - break; - - case Y_BGTZ_OP: - BRANCH_INST (R[RS (inst)] != 0 && SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 0); - break; - - case Y_BGTZL_OP: - BRANCH_INST (R[RS (inst)] != 0 && SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 1); - break; - - case Y_BLEZ_OP: - BRANCH_INST (R[RS (inst)] == 0 || SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 0); - break; - - case Y_BLEZL_OP: - BRANCH_INST (R[RS (inst)] == 0 || SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 1); - break; - - case Y_BLTZ_OP: - BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 0); - break; - - case Y_BLTZL_OP: - BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 1); - break; - - case Y_BLTZAL_OP: - R[31] = PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 0); - break; - - case Y_BLTZALL_OP: - R[31] = PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 1); - break; - - case Y_BNE_OP: - BRANCH_INST (R[RS (inst)] != R[RT (inst)], - PC + IDISP (inst), - 0); - break; - - case Y_BNEL_OP: - BRANCH_INST (R[RS (inst)] != R[RT (inst)], - PC + IDISP (inst), - 1); - break; - - case Y_BREAK_OP: - if (RD (inst) == 1) - /* Debugger breakpoint */ - RAISE_EXCEPTION (ExcCode_Bp, return true) - else - RAISE_EXCEPTION (ExcCode_Bp, break); - - case Y_CACHE_OP: - break; /* Memory details not implemented */ - - case Y_CFC0_OP: - R[RT (inst)] = CCR[0][RD (inst)]; - break; - - case Y_CFC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_CLO_OP: - { - reg_word val = R[RS (inst)]; - int i; - for (i = 31; 0 <= i; i -= 1) - if (((val >> i) & 0x1) == 0) break; - - R[RD (inst) ] = 31 - i; - break; - } - - case Y_CLZ_OP: - { - reg_word val = R[RS (inst)]; - int i; - for (i = 31; 0 <= i; i -= 1) - if (((val >> i) & 0x1) == 1) break; - - R[RD (inst) ] = 31 - i; - break; - } - - case Y_COP2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_CTC0_OP: - CCR[0][RD (inst)] = R[RT (inst)]; - break; - - case Y_CTC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_DIV_OP: - /* The behavior of this instruction is undefined on divide by - zero or overflow. */ - if (R[RT (inst)] != 0 - && !(R[RS (inst)] == (reg_word)0x80000000 - && R[RT (inst)] == (reg_word)0xffffffff)) - { - LO = (reg_word) R[RS (inst)] / (reg_word) R[RT (inst)]; - HI = (reg_word) R[RS (inst)] % (reg_word) R[RT (inst)]; - } - break; - - case Y_DIVU_OP: - /* The behavior of this instruction is undefined on divide by - zero or overflow. */ - if (R[RT (inst)] != 0 - && !(R[RS (inst)] == (reg_word)0x80000000 - && R[RT (inst)] == (reg_word)0xffffffff)) - { - LO = (u_reg_word) R[RS (inst)] / (u_reg_word) R[RT (inst)]; - HI = (u_reg_word) R[RS (inst)] % (u_reg_word) R[RT (inst)]; - } - break; - - case Y_ERET_OP: - { - CP0_Status &= ~CP0_Status_EXL; /* Clear EXL bit */ - JUMP_INST (CP0_EPC); /* Jump to EPC */ - } - break; - - case Y_J_OP: - JUMP_INST (((PC & 0xf0000000) | TARGET (inst) << 2)); - break; - - case Y_JAL_OP: - if (delayed_branches) - R[31] = PC + 2 * BYTES_PER_WORD; - else - R[31] = PC + BYTES_PER_WORD; - JUMP_INST (((PC & 0xf0000000) | (TARGET (inst) << 2))); - break; - - case Y_JALR_OP: - { - mem_addr tmp = R[RS (inst)]; - - if (delayed_branches) - R[RD (inst)] = PC + 2 * BYTES_PER_WORD; - else - R[RD (inst)] = PC + BYTES_PER_WORD; - JUMP_INST (tmp); - } - break; - - case Y_JR_OP: - { - mem_addr tmp = R[RS (inst)]; - - JUMP_INST (tmp); - } - break; - - case Y_LB_OP: - LOAD_INST (&R[RT (inst)], - read_mem_byte (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LBU_OP: - LOAD_INST (&R[RT (inst)], - read_mem_byte (R[BASE (inst)] + IOFFSET (inst)), - 0xff); - break; - - case Y_LH_OP: - LOAD_INST (&R[RT (inst)], - read_mem_half (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LHU_OP: - LOAD_INST (&R[RT (inst)], - read_mem_half (R[BASE (inst)] + IOFFSET (inst)), - 0xffff); - break; - - case Y_LL_OP: - /* Uniprocess, so this instruction is just a load */ - LOAD_INST (&R[RT (inst)], - read_mem_word (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LUI_OP: - R[RT (inst)] = (IMM (inst) << 16) & 0xffff0000; - break; - - case Y_LW_OP: - LOAD_INST (&R[RT (inst)], - read_mem_word (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LDC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_LWC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_LWL_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - reg_word word; /* Can't be register */ - int byte = addr & 0x3; - reg_word reg_val = R[RT (inst)]; - - word = read_mem_word (addr & 0xfffffffc); - if (!exception_occurred) -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - word = word; - break; - - case 1: - word = ((word & 0xffffff) << 8) | (reg_val & 0xff); - break; - - case 2: - word = ((word & 0xffff) << 16) | (reg_val & 0xffff); - break; - - case 3: - word = ((word & 0xff) << 24) | (reg_val & 0xffffff); - break; - } -#else - switch (byte) - { - case 0: - word = ((word & 0xff) << 24) | (reg_val & 0xffffff); - break; - - case 1: - word = ((word & 0xffff) << 16) | (reg_val & 0xffff); - break; - - case 2: - word = ((word & 0xffffff) << 8) | (reg_val & 0xff); - break; - - case 3: - break; - } -#endif - LOAD_INST_BASE (&R[RT (inst)], word); - break; - } - - case Y_LWR_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - reg_word word; /* Can't be register */ - int byte = addr & 0x3; - reg_word reg_val = R[RT (inst)]; - - word = read_mem_word (addr & 0xfffffffc); - if (!exception_occurred) -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - word = (reg_val & 0xffffff00) | ((unsigned)(word & 0xff000000) >> 24); - break; - - case 1: - word = (reg_val & 0xffff0000) | ((unsigned)(word & 0xffff0000) >> 16); - break; - - case 2: - word = (reg_val & 0xff000000) | ((unsigned)(word & 0xffffff00) >> 8); - break; - - case 3: - word = word; - break; - } -#else - switch (byte) - { - case 0: - break; - - case 1: - word = (reg_val & 0xff000000) | ((word & 0xffffff00) >> 8); - break; - - case 2: - word = (reg_val & 0xffff0000) | ((word & 0xffff0000) >> 16); - break; - - case 3: - word = (reg_val & 0xffffff00) | ((word & 0xff000000) >> 24); - break; - } -#endif - LOAD_INST_BASE (&R[RT (inst)], word); - break; - } - - case Y_MADD_OP: - case Y_MADDU_OP: - { - reg_word lo = LO, hi = HI; - reg_word tmp; - if (OPCODE (inst) == Y_MADD_OP) - { - signed_multiply(R[RS (inst)], R[RT (inst)]); - } - else /* Y_MADDU_OP */ - { - unsigned_multiply(R[RS (inst)], R[RT (inst)]); - } - tmp = lo + LO; - if ((unsigned)tmp < (unsigned)LO || (unsigned)tmp < (unsigned)lo) - { - /* Addition of low-order word overflows */ - hi += 1; - } - LO = tmp; - HI = hi + HI; - break; - } - - case Y_MFC0_OP: - R[RT (inst)] = CPR[0][FS (inst)]; - break; - - case Y_MFC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_MFHI_OP: - R[RD (inst)] = HI; - break; - - case Y_MFLO_OP: - R[RD (inst)] = LO; - break; - - case Y_MOVN_OP: - if (R[RT (inst)] != 0) - R[RD (inst)] = R[RS (inst)]; - break; - - case Y_MOVZ_OP: - if (R[RT (inst)] == 0) - R[RD (inst)] = R[RS (inst)]; - break; - - case Y_MSUB_OP: - case Y_MSUBU_OP: - { - reg_word lo = LO, hi = HI; - reg_word tmp; - - if (OPCODE (inst) == Y_MSUB_OP) - { - signed_multiply(R[RS (inst)], R[RT (inst)]); - } - else /* Y_MSUBU_OP */ - { - unsigned_multiply(R[RS (inst)], R[RT (inst)]); - } - - tmp = lo - LO; - if ((unsigned)LO > (unsigned)lo) - { - /* Subtraction of low-order word borrows */ - hi -= 1; - } - LO = tmp; - HI = hi - HI; - break; - } - - case Y_MTC0_OP: - CPR[0][FS (inst)] = R[RT (inst)]; - switch (FS (inst)) - { - case CP0_Compare_Reg: - CP0_Cause &= ~CP0_Cause_IP7; /* Writing clears HW interrupt 5 */ - break; - - case CP0_Status_Reg: - CP0_Status &= CP0_Status_Mask; - CP0_Status |= ((CP0_Status_CU & 0x30000000) | CP0_Status_UM); - break; - - case CP0_Cause_Reg: - CPR[0][FS (inst)] &= CP0_Cause_Mask; - break; - - case CP0_Config_Reg: - CPR[0][FS (inst)] &= CP0_Config_Mask; - break; - - default: - break; - } - break; - - case Y_MTC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_MTHI_OP: - HI = R[RS (inst)]; - break; - - case Y_MTLO_OP: - LO = R[RS (inst)]; - break; - - case Y_MUL_OP: - signed_multiply(R[RS (inst)], R[RT (inst)]); - R[RD (inst)] = LO; - break; - - case Y_MULT_OP: - signed_multiply(R[RS (inst)], R[RT (inst)]); - break; - - case Y_MULTU_OP: - unsigned_multiply (R[RS (inst)], R[RT (inst)]); - break; - - case Y_NOR_OP: - R[RD (inst)] = ~ (R[RS (inst)] | R[RT (inst)]); - break; - - case Y_OR_OP: - R[RD (inst)] = R[RS (inst)] | R[RT (inst)]; - break; - - case Y_ORI_OP: - R[RT (inst)] = R[RS (inst)] | (0xffff & IMM (inst)); - break; - - case Y_PREF_OP: - break; /* Memory details not implemented */ - - case Y_RFE_OP: -#ifdef MIPS1 - /* This is MIPS-I, not compatible with MIPS32 or the - definition of the bits in the CP0 Status register in that - architecture. */ - CP0_Status = (CP0_Status & 0xfffffff0) | ((CP0_Status & 0x3c) >> 2); -#else - RAISE_EXCEPTION (ExcCode_RI, {}); /* Not MIPS32 instruction */ -#endif - break; - - case Y_SB_OP: - set_mem_byte (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]); - break; - - case Y_SC_OP: - /* Uniprocessor, so instruction is just a store */ - set_mem_word (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]); - break; - - case Y_SDC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_SH_OP: - set_mem_half (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]); - break; - - case Y_SLL_OP: - { - int shamt = SHAMT (inst); - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = R[RT (inst)] << shamt; - else - R[RD (inst)] = R[RT (inst)]; - break; - } - - case Y_SLLV_OP: - { - int shamt = (R[RS (inst)] & 0x1f); - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = R[RT (inst)] << shamt; - else - R[RD (inst)] = R[RT (inst)]; - break; - } - - case Y_SLT_OP: - if (R[RS (inst)] < R[RT (inst)]) - R[RD (inst)] = 1; - else - R[RD (inst)] = 0; - break; - - case Y_SLTI_OP: - if (R[RS (inst)] < (short) IMM (inst)) - R[RT (inst)] = 1; - else - R[RT (inst)] = 0; - break; - - case Y_SLTIU_OP: - { - int x = (short) IMM (inst); - - if ((u_reg_word) R[RS (inst)] < (u_reg_word) x) - R[RT (inst)] = 1; - else - R[RT (inst)] = 0; - break; - } - - case Y_SLTU_OP: - if ((u_reg_word) R[RS (inst)] < (u_reg_word) R[RT (inst)]) - R[RD (inst)] = 1; - else - R[RD (inst)] = 0; - break; - - case Y_SRA_OP: - { - int shamt = SHAMT (inst); - reg_word val = R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = val >> shamt; - else - R[RD (inst)] = val; - break; - } - - case Y_SRAV_OP: - { - int shamt = R[RS (inst)] & 0x1f; - reg_word val = R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = val >> shamt; - else - R[RD (inst)] = val; - break; - } - - case Y_SRL_OP: - { - int shamt = SHAMT (inst); - u_reg_word val = R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = val >> shamt; - else - R[RD (inst)] = val; - break; - } - - case Y_SRLV_OP: - { - int shamt = R[RS (inst)] & 0x1f; - u_reg_word val = R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = val >> shamt; - else - R[RD (inst)] = val; - break; - } - - case Y_SUB_OP: - { - reg_word vs = R[RS (inst)], vt = R[RT (inst)]; - reg_word diff = vs - vt; - - if (SIGN_BIT (vs) != SIGN_BIT (vt) - && SIGN_BIT (vs) != SIGN_BIT (diff)) - RAISE_EXCEPTION (ExcCode_Ov, break); - R[RD (inst)] = diff; - break; - } - - case Y_SUBU_OP: - R[RD (inst)] = (u_reg_word)R[RS (inst)]-(u_reg_word)R[RT (inst)]; - break; - - case Y_SW_OP: - set_mem_word (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]); - break; - - case Y_SWC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_SWL_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - mem_word data; - reg_word reg = R[RT (inst)]; - int byte = addr & 0x3; - - data = read_mem_word (addr & 0xfffffffc); -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - data = reg; - break; - - case 1: - data = (data & 0xff000000) | (reg >> 8 & 0xffffff); - break; - - case 2: - data = (data & 0xffff0000) | (reg >> 16 & 0xffff); - break; - - case 3: - data = (data & 0xffffff00) | (reg >> 24 & 0xff); - break; - } -#else - switch (byte) - { - case 0: - data = (data & 0xffffff00) | (reg >> 24 & 0xff); - break; - - case 1: - data = (data & 0xffff0000) | (reg >> 16 & 0xffff); - break; - - case 2: - data = (data & 0xff000000) | (reg >> 8 & 0xffffff); - break; - - case 3: - data = reg; - break; - } -#endif - set_mem_word (addr & 0xfffffffc, data); - break; - } - - case Y_SWR_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - mem_word data; - reg_word reg = R[RT (inst)]; - int byte = addr & 0x3; - - data = read_mem_word (addr & 0xfffffffc); -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - data = ((reg << 24) & 0xff000000) | (data & 0xffffff); - break; - - case 1: - data = ((reg << 16) & 0xffff0000) | (data & 0xffff); - break; - - case 2: - data = ((reg << 8) & 0xffffff00) | (data & 0xff) ; - break; - - case 3: - data = reg; - break; - } -#else - switch (byte) - { - case 0: - data = reg; - break; - - case 1: - data = ((reg << 8) & 0xffffff00) | (data & 0xff) ; - break; - - case 2: - data = ((reg << 16) & 0xffff0000) | (data & 0xffff); - break; - - case 3: - data = ((reg << 24) & 0xff000000) | (data & 0xffffff); - break; - } -#endif - set_mem_word (addr & 0xfffffffc, data); - break; - } - - case Y_SYNC_OP: - break; /* Memory details not implemented */ - - case Y_SYSCALL_OP: - if (!do_syscall ()) - return false; - break; - - case Y_TEQ_OP: - if (R[RS (inst)] == R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TEQI_OP: - if (R[RS (inst)] == IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TGE_OP: - if (R[RS (inst)] >= R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TGEI_OP: - if (R[RS (inst)] >= IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TGEIU_OP: - if ((u_reg_word)R[RS (inst)] >= (u_reg_word)IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TGEU_OP: - if ((u_reg_word)R[RS (inst)] >= (u_reg_word)R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TLBP_OP: - RAISE_EXCEPTION(ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBR_OP: - RAISE_EXCEPTION(ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBWI_OP: - RAISE_EXCEPTION(ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBWR_OP: - RAISE_EXCEPTION(ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLT_OP: - if (R[RS (inst)] < R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TLTI_OP: - if (R[RS (inst)] < IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TLTIU_OP: - if ((u_reg_word)R[RS (inst)] < (u_reg_word)IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TLTU_OP: - if ((u_reg_word)R[RS (inst)] < (u_reg_word)R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TNE_OP: - if (R[RS (inst)] != R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TNEI_OP: - if (R[RS (inst)] != IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_XOR_OP: - R[RD (inst)] = R[RS (inst)] ^ R[RT (inst)]; - break; - - case Y_XORI_OP: - R[RT (inst)] = R[RS (inst)] ^ (0xffff & IMM (inst)); - break; - - - /* FPA Operations */ - - case Y_ABS_S_OP: - SET_FPR_S (FD (inst), fabs (FPR_S (FS (inst)))); - break; - - case Y_ABS_D_OP: - SET_FPR_D (FD (inst), fabs (FPR_D (FS (inst)))); - break; - - case Y_ADD_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst)) + FPR_S (FT (inst))); - /* Should trap on inexact/overflow/underflow */ - break; - - case Y_ADD_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst)) + FPR_D (FT (inst))); - /* Should trap on inexact/overflow/underflow */ - break; - - case Y_BC1F_OP: - case Y_BC1FL_OP: - case Y_BC1T_OP: - case Y_BC1TL_OP: - { - int cc = CC (inst); - int nd = ND (inst); /* 1 => nullify */ - int tf = TF (inst); /* 0 => BC1F, 1 => BC1T */ - BRANCH_INST ((FCCR & (1 << cc)) == (tf << cc), - PC + IDISP (inst), - nd); - break; - } - - case Y_C_F_S_OP: - case Y_C_UN_S_OP: - case Y_C_EQ_S_OP: - case Y_C_UEQ_S_OP: - case Y_C_OLT_S_OP: - case Y_C_OLE_S_OP: - case Y_C_ULT_S_OP: - case Y_C_ULE_S_OP: - case Y_C_SF_S_OP: - case Y_C_NGLE_S_OP: - case Y_C_SEQ_S_OP: - case Y_C_NGL_S_OP: - case Y_C_LT_S_OP: - case Y_C_NGE_S_OP: - case Y_C_LE_S_OP: - case Y_C_NGT_S_OP: - { - float v1 = FPR_S (FS (inst)), v2 = FPR_S (FT (inst)); - double dv1 = v1, dv2 = v2; - int cond = COND (inst); - int cc = FD (inst); - - if (NaN (dv1) || NaN (dv2)) - { - if (cond & COND_IN) - { - RAISE_EXCEPTION (ExcCode_FPE, break); - } - set_fpu_cc (cond, cc, 0, 0, 1); - } - else - { - set_fpu_cc (cond, cc, v1 < v2, v1 == v2, 0); - } - } - break; - - case Y_C_F_D_OP: - case Y_C_UN_D_OP: - case Y_C_EQ_D_OP: - case Y_C_UEQ_D_OP: - case Y_C_OLT_D_OP: - case Y_C_OLE_D_OP: - case Y_C_ULT_D_OP: - case Y_C_ULE_D_OP: - case Y_C_SF_D_OP: - case Y_C_NGLE_D_OP: - case Y_C_SEQ_D_OP: - case Y_C_NGL_D_OP: - case Y_C_LT_D_OP: - case Y_C_NGE_D_OP: - case Y_C_LE_D_OP: - case Y_C_NGT_D_OP: - { - double v1 = FPR_D (FS (inst)), v2 = FPR_D (FT (inst)); - int cond = COND (inst); - int cc = FD (inst); - - if (NaN (v1) || NaN (v2)) - { - if (cond & COND_IN) - { - RAISE_EXCEPTION (ExcCode_FPE, break); - } - set_fpu_cc (cond, cc, 0, 0, 1); - } - else - { - set_fpu_cc (cond, cc, v1 < v2, v1 == v2, 0); - } - } - break; - - case Y_CFC1_OP: - R[RT (inst)] = FCR[FS (inst)]; - break; - - case Y_CTC1_OP: - FCR[FS (inst)] = R[RT (inst)]; - - if (FIR_REG == FS (inst)) - { - /* Read only register */ - FIR = FIR_MASK; - } - else if (FCCR_REG == FS (inst)) - { - /* FCC bits in FCSR and FCCR linked */ - FCSR = (FCSR & ~0xfe400000) - | ((FCCR & 0xfe) << 24) - | ((FCCR & 0x1) << 23); - FCCR &= FCCR_MASK; - } - else if (FCSR_REG == FS (inst)) - { - /* FCC bits in FCSR and FCCR linked */ - FCCR = ((FCSR >> 24) & 0xfe) | ((FCSR >> 23) & 0x1); - FCSR &= FCSR_MASK; - if ((R[RT (inst)] & ~FCSR_MASK) != 0) - /* Trying to set unsupported mode */ - RAISE_EXCEPTION (ExcCode_FPE, {}); - } - break; - - case Y_CEIL_W_D_OP: - { - double val = FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), (int32)ceil (val)); - break; - } - - case Y_CEIL_W_S_OP: - { - double val = (double)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), (int32)ceil (val)); - break; - } - - case Y_CVT_D_S_OP: - { - double val = FPR_S (FS (inst)); - - SET_FPR_D (FD (inst), val); - break; - } - - case Y_CVT_D_W_OP: - { - double val = (double)FPR_W (FS (inst)); - - SET_FPR_D (FD (inst), val); - break; - } - - case Y_CVT_S_D_OP: - { - float val = (float)FPR_D (FS (inst)); - - SET_FPR_S (FD (inst), val); - break; - } - - case Y_CVT_S_W_OP: - { - float val = (float)FPR_W (FS (inst)); - - SET_FPR_S (FD (inst), val); - break; - } - - case Y_CVT_W_D_OP: - { - int val = (int32)FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), val); - break; - } - - case Y_CVT_W_S_OP: - { - int val = (int32)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), val); - break; - } - - case Y_DIV_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst)) / FPR_S (FT (inst))); - break; - - case Y_DIV_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst)) / FPR_D (FT (inst))); - break; - - case Y_FLOOR_W_D_OP: - { - double val = FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), (int32)floor (val)); - break; - } - - case Y_FLOOR_W_S_OP: - { - double val = (double)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), (int32)floor (val)); - break; - } - - case Y_LDC1_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - if ((addr & 0x3) != 0) - RAISE_EXCEPTION (ExcCode_AdEL, CP0_BadVAddr = addr); - - LOAD_INST ((reg_word *) &FPR_S(FT (inst)), - read_mem_word (addr), - 0xffffffff); - LOAD_INST ((reg_word *) &FPR_S(FT (inst) + 1), - read_mem_word (addr + sizeof(mem_word)), - 0xffffffff); - break; - } - - case Y_LWC1_OP: - LOAD_INST ((reg_word *) &FPR_S(FT (inst)), - read_mem_word (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_MFC1_OP: - { - float val = FPR_S(FS (inst)); - reg_word *vp = (reg_word *) &val; - - R[RT (inst)] = *vp; /* Fool coercion */ - break; - } - - case Y_MOV_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - - case Y_MOV_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - - case Y_MOVF_OP: - { - int cc = CC (inst); - if ((FCCR & (1 << cc)) == 0) - R[RD (inst)] = R[RS (inst)]; - break; - } - - case Y_MOVF_D_OP: - { - int cc = CC (inst); - if ((FCCR & (1 << cc)) == 0) - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - } - - case Y_MOVF_S_OP: - { - int cc = CC (inst); - if ((FCCR & (1 << cc)) == 0) - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - - } - - case Y_MOVN_D_OP: - { - if (R[RT (inst)] != 0) - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - } - - case Y_MOVN_S_OP: - { - if (R[RT (inst)] != 0) - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - } - - case Y_MOVT_OP: - { - int cc = CC (inst); - if ((FCCR & (1 << cc)) != 0) - R[RD (inst)] = R[RS (inst)]; - break; - } - - case Y_MOVT_D_OP: - { - int cc = CC (inst); - if ((FCCR & (1 << cc)) != 0) - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - } - - case Y_MOVT_S_OP: - { - int cc = CC (inst); - if ((FCCR & (1 << cc)) != 0) - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - - } - - case Y_MOVZ_D_OP: - { - if (R[RT (inst)] == 0) - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - } - - case Y_MOVZ_S_OP: - { - if (R[RT (inst)] == 0) - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - - } - - case Y_MTC1_OP: - { - reg_word word = R[RT (inst)]; - float *wp = (float *) &word; - - SET_FPR_S(FS (inst), *wp); /* fool coercion */ - break; - } - - case Y_MUL_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst)) * FPR_S (FT (inst))); - break; - - case Y_MUL_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst)) * FPR_D (FT (inst))); - break; - - case Y_NEG_S_OP: - SET_FPR_S (FD (inst), -FPR_S (FS (inst))); - break; - - case Y_NEG_D_OP: - SET_FPR_D (FD (inst), -FPR_D (FS (inst))); - break; - - case Y_ROUND_W_D_OP: - { - double val = FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), (int32)(val + 0.5)); /* Casting truncates */ - break; - } - - case Y_ROUND_W_S_OP: - { - double val = (double)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), (int32)(val + 0.5)); /* Casting truncates */ - break; - } - - case Y_SDC1_OP: - { - double val = FPR_D (RT (inst)); - reg_word *vp = (reg_word*)&val; - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - if ((addr & 0x3) != 0) - RAISE_EXCEPTION (ExcCode_AdEL, CP0_BadVAddr = addr); - - set_mem_word (addr, *vp); - set_mem_word (addr + sizeof(mem_word), *(vp + 1)); - break; - } - - case Y_SQRT_D_OP: - SET_FPR_D (FD (inst), sqrt (FPR_D (FS (inst)))); - break; - - case Y_SQRT_S_OP: - SET_FPR_S (FD (inst), sqrt (FPR_S (FS (inst)))); - break; - - case Y_SUB_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst)) - FPR_S (FT (inst))); - break; - - case Y_SUB_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst)) - FPR_D (FT (inst))); - break; - - case Y_SWC1_OP: - { - float val = FPR_S(RT (inst)); - reg_word *vp = (reg_word *) &val; - - set_mem_word (R[BASE (inst)] + IOFFSET (inst), *vp); - break; - } - - case Y_TRUNC_W_D_OP: - { - double val = FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), (int32)val); /* Casting truncates */ - break; - } - - case Y_TRUNC_W_S_OP: - { - double val = (double)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), (int32)val); /* Casting truncates */ - break; - } - - default: - fatal_error ("Unknown instruction type: %d\n", OPCODE (inst)); - break; - } - - /* After instruction executes: */ - PC += BYTES_PER_WORD; - - if (exception_occurred) - { - handle_exception (); - } - } /* End: for (step = 0; ... */ - } /* End: for ( ; steps_to_run > 0 ... */ - - /* Executed enought steps, return, but are able to continue. */ - return true; -} - - -#ifdef _WIN32 -void CALLBACK -timer_completion_routine(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue) -{ - lpArgToCompletionRoutine = lpArgToCompletionRoutine; - dwTimerLowValue = dwTimerLowValue; - dwTimerHighValue = dwTimerHighValue; - bump_CP0_timer (); -} -#endif - - -/* Increment CP0 Count register and test if it matches the Compare - register. If so, cause an interrupt. */ - -static void -bump_CP0_timer () -{ - CP0_Count += 1; - if (CP0_Count == CP0_Compare) - { - RAISE_INTERRUPT (7); - } -} - - -static void -start_CP0_timer () -{ -#ifdef _WIN32 - HANDLE timer = CreateWaitableTimer(NULL, TRUE, TEXT("SPIMTimer")); - if (NULL == timer) - { - error ("CreateWaitableTimer failed"); - } - else - { - LARGE_INTEGER interval; - interval.QuadPart = -10000 * TIMER_TICK_MS; /* Unit is 100 nsec */ - - if (!SetWaitableTimer (timer, &interval, 1, timer_completion_routine, 0, FALSE)) - { - error ("SetWaitableTimer failed"); - } - } -#else - /* Should use ITIMER_VIRTUAL delivering SIGVTALRM, but that does not seem - to work under Cygwin, so we'll adopt the lowest common denominator and - use real time. - - We ignore the resulting signal, however, and read the timer with getitimer, - since signals interrupt I/O calls, such as read, and make user - interaction with SPIM work very poorly. Since speed isn't an important - aspect of SPIM, polling isn't a big deal. */ - if (SIG_ERR == signal (SIGALRM, SIG_IGN)) - { - perror ("signal failed"); - } - else - { - struct itimerval time; - if (-1 == getitimer (ITIMER_REAL, &time)) - { - perror ("getitmer failed"); - } - if (time.it_value.tv_usec == 0 && time.it_value.tv_sec == 0) - { - /* Timer is expired or has not been started. - Start a non-periodic timer for TIMER_TICK_MS microseconds. */ - time.it_interval.tv_sec = 0; - time.it_interval.tv_usec = 0; - time.it_value.tv_sec = 0; - time.it_value.tv_usec = TIMER_TICK_MS * 1000; - if (-1 == setitimer (ITIMER_REAL, &time, NULL)) - { - perror ("setitmer failed"); - } - } - } -#endif -} - - -/* Multiply two 32-bit numbers, V1 and V2, to produce a 64 bit result in - the HI/LO registers. The algorithm is high-school math: - - A B - x C D - ------ - AD || BD - AC || CB || 0 - - where A and B are the high and low short words of V1, C and D are the short - words of V2, AD is the product of A and D, and X || Y is (X << 16) + Y. - Since the algorithm is programmed in C, we need to be careful not to - overflow. */ - -static void -unsigned_multiply (reg_word v1, reg_word v2) -{ - u_reg_word a, b, c, d; - u_reg_word bd, ad, cb, ac; - u_reg_word mid, mid2, carry_mid = 0; - - a = (v1 >> 16) & 0xffff; - b = v1 & 0xffff; - c = (v2 >> 16) & 0xffff; - d = v2 & 0xffff; - - bd = b * d; - ad = a * d; - cb = c * b; - ac = a * c; - - mid = ad + cb; - if (mid < ad || mid < cb) - /* Arithmetic overflow or carry-out */ - carry_mid = 1; - - mid2 = mid + ((bd >> 16) & 0xffff); - if (mid2 < mid || mid2 < ((bd >> 16) & 0xffff)) - /* Arithmetic overflow or carry-out */ - carry_mid += 1; - - LO = (bd & 0xffff) | ((mid2 & 0xffff) << 16); - HI = ac + (carry_mid << 16) + ((mid2 >> 16) & 0xffff); -} - - -static void -signed_multiply (reg_word v1, reg_word v2) -{ - int neg_sign = 0; - - if (v1 < 0) - { - v1 = - v1; - neg_sign = 1; - } - if (v2 < 0) - { - v2 = - v2; - neg_sign = ! neg_sign; - } - - unsigned_multiply (v1, v2); - if (neg_sign) - { - LO = ~ LO; - HI = ~ HI; - LO += 1; - if (LO == 0) - HI += 1; - } -} - -static void -set_fpu_cc (int cond, int cc, int less, int equal, int unordered) -{ - int result; - int fcsr_bit; - - result = 0; - if (cond & COND_LT) result |= less; - if (cond & COND_EQ) result |= equal; - if (cond & COND_UN) result |= unordered; - - FCCR = (FCCR & ~(1 << cc)) | (result << cc); - if (0 == cc) - { - fcsr_bit = 23; - } - else - { - fcsr_bit = 24 + cc; - } - FCSR = (FCSR & ~(1 << fcsr_bit)) | (result << fcsr_bit); -} - - -void -raise_exception (int excode) -{ - if (ExcCode_Int != excode - || ((CP0_Status & CP0_Status_IE) /* Allow interrupt if IE and !EXL */ - && !(CP0_Status & CP0_Status_EXL))) - { - /* Ignore interrupt exception when interrupts disabled. */ - exception_occurred = 1; - if (running_in_delay_slot) - { - /* In delay slot */ - if ((CP0_Status & CP0_Status_EXL) == 0) - { - /* Branch's addr */ - CP0_EPC = ROUND_DOWN (PC - BYTES_PER_WORD, BYTES_PER_WORD); - /* Set BD bit to record that instruction is in delay slot */ - CP0_Cause |= CP0_Cause_BD; - } - } - else - { - /* Not in delay slot */ - if ((CP0_Status & CP0_Status_EXL) == 0) - { - /* Faulting instruction's address */ - CP0_EPC = ROUND_DOWN (PC, BYTES_PER_WORD); - } - } - /* ToDo: set CE field of Cause register to coprocessor causing exception */ - - /* Record cause of exception */ - CP0_Cause = (CP0_Cause & ~CP0_Cause_ExcCode) | (excode << 2); - - /* Turn on EXL bit to prevent subsequent interrupts from affecting EPC */ - CP0_Status |= CP0_Status_EXL; - -#ifdef MIPS1 - CP0_Status = (CP0_Status & 0xffffffc0) | ((CP0_Status & 0xf) << 2); -#endif - } -} diff --git a/spim-jsspim/CPU/run.h b/spim-jsspim/CPU/run.h deleted file mode 100755 index a8029d1..0000000 --- a/spim-jsspim/CPU/run.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM instructions. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -bool run_spim (mem_addr initial_PC, int steps, bool display); diff --git a/spim-jsspim/CPU/scanner.h b/spim-jsspim/CPU/scanner.h deleted file mode 100755 index 3f97644..0000000 --- a/spim-jsspim/CPU/scanner.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to lexical scanner. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions (besides yylex): */ - -void initialize_scanner (FILE *in_file); -void push_scanner (FILE *in_file); -void pop_scanner (); -char* erroneous_line (); -void scanner_start_line (); -int register_name_to_number (char *name); -char *source_line (); -int yylex (); - -/* Exported Variables: */ - -/* This flag tells the scanner to treat the next sequence of letters - etc as an identifier and not look it up as an opcode. It permits us - to use opcodes as symbols in most places. However, because of the - LALR(1) lookahead, it does not work for labels. */ - -extern int only_id; - -typedef intptr_union yylval_t; -#define YYSTYPE yylval_t -extern YYSTYPE yylval; /* Value of token from YYLEX */ - -extern int line_no; /* Line number in input file*/ diff --git a/spim-jsspim/CPU/scanner.l b/spim-jsspim/CPU/scanner.l deleted file mode 100755 index 24a7baf..0000000 --- a/spim-jsspim/CPU/scanner.l +++ /dev/null @@ -1,733 +0,0 @@ -%{ -/* SPIM S20 MIPS simulator. - Lexical scanner. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "sym-tbl.h" -#include "parser.h" -#include "scanner.h" -#include "parser_yacc.h" - -#ifdef _WIN32 -#include -#else -#include -#endif - -#define YY_NO_UNISTD_H - -/* Exported Variables: */ - -int only_id; -int line_no; /* Line number in input file*/ - - -/* Local Variables: */ - -/* Track which line we are reading and where it began in the buffer. */ -static int current_line_no = 0; - -static char *current_line = NULL; - - -static double scan_float; /* Where FP values are kept */ - -static int line_returned = 0; /* Returned current line yet? */ - -static int eof_returned = 0; /* Return EOF token yet? */ - - -/* Local functions: */ - -static int check_keyword (char *id, int allow_pseudo_ops); -static char *copy_str (char *str, int chop); -static char scan_escape (char **str); - - -#undef yywrap - -%} - -%% - -[ \t] { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - } - - -[\n] { - line_no += 1; - return (Y_NL); - } - -[\r] { /* Ignore carrage returns */ } - -[;] { - return (Y_NL); - } - - -[\001] { /* Marker character inserted to allow scanner to - return Y_EOF before returning hard EOF. */ - return (Y_EOF); - } - -"#".* { - /* Ignore comments */ - } - - -(-[0-9]+)|([0-9]+) { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.i = atoi (yytext); - return (Y_INT); - } - - -((0x)|(-0x))[0-9A-Fa-f]+ { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - if (*yytext == '-') - { - sscanf(yytext+3, "%x", (unsigned int*)&(yylval.i)); - yylval.i = -yylval.i; - } - else - { - sscanf(yytext+2, "%x", (unsigned int*)&(yylval.i)); - } - return (Y_INT); - } - - -(\+|\-)?[0-9]+[\.\,\'][0-9]+(e)?(\+|\-)?[0-9]* { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - scan_float = atof (yytext); - yylval.p = (double*) &scan_float; - return (Y_FP); - } - - -[a-zA-Z_\.][a-zA-Z0-9_\.]* { - int token = check_keyword (yytext, - !bare_machine - && accept_pseudo_insts); - label *l; - - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (!only_id && token != 0) - { - /* Keyword */ - yylval.i = token; - current_line = yytext; - return (token); - } - - if (only_id && token != 0) - yyerror ("Cannot use opcodes as labels"); - - if ((l = label_is_defined (yytext)) != NULL - && l->const_flag) - { - /* Defined label */ - yylval.i = (int) l->addr; - return (Y_INT); - } - else - { - /* Not-yet defined label */ - yylval.p = (char*) str_copy (yytext); - return (Y_ID); - } - } - - -\$[a-zA-Z0-9_\.$]+ { - int reg_no = register_name_to_number (yytext + 1); - - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (reg_no != -1 - && *(yytext + 1) == 'f' - && *(yytext + 2) != 'p') - { - /* Floating point register ($f0) */ - yylval.i = reg_no; - return (Y_FP_REG); - } - - if (0 <= reg_no && reg_no < R_LENGTH) - { - /* Register ($r0) */ - yylval.i = reg_no; - return (Y_REG); - } - else - { - /* Otherwise, an integer or identifier */ - label *l = label_is_defined (yytext); - - if (l != NULL && l->const_flag) - { - yylval.i = (int) l->addr; - return (Y_INT); - } - else - { - yylval.p = (char*) str_copy (yytext); - return (Y_ID); - } - } - } - - -[\*\/:()+-]|">"|"=" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - return (*yytext); - } - - -"," { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - /* Skip commas */ - } - -"?" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.p = (char*) str_copy (yytext); - /* For top level */ - return (Y_ID); - } - - -\"(([^""])|(\\\"))*\" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.p = (char*) copy_str (yytext + 1, 1); - return (Y_STR); - } - -\'(([^''])|(\\[^'']))\' { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (*(yytext + 1) == '\\') - { - char *escape = yytext + 2; - yylval.i = (int) scan_escape (&escape); - } - else - { - yylval.i = (int) *(yytext + 1); - } - - return (Y_INT); - } - -. { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yyerror ("Unknown character"); - } - - -%% - - - -void -initialize_scanner (FILE *in_file) -{ - if (yyin != in_file) - { - push_scanner (in_file); - } - yyin = in_file; - -#ifdef FLEX_SCANNER - yyrestart(in_file); -#define YY_FLEX_VERSION (YY_FLEX_MAJOR_VERSION * 1000 + YY_FLEX_MINOR_VERSION * 100 + YY_FLEX_SUBMINOR_VERSION) -#if YY_FLEX_VERSION >= 2533 - /* flex 2.5.33 flipped the polarity of this flag (sigh) */ - yy_init = 0; -#else - yy_init = 1; -#endif -#endif - - line_no = 1; - current_line = NULL; - line_returned = 0; - eof_returned = 0; -} - -void -push_scanner (FILE *in_file) -{ - YY_BUFFER_STATE buf = yy_create_buffer (in_file, YY_BUF_SIZE); - yypush_buffer_state (buf); -} - -void -pop_scanner () -{ - yypop_buffer_state (); -} - -void -scanner_start_line () -{ - current_line = NULL; - line_returned = 0; -} - - -/* This is a work-around for a bug in flex v 2.5.31 (but not earlier or - later versions such as 2.5.4) that left this symbol undefined. */ - -#ifndef yytext_ptr -#define yytext_ptr yytext -#endif - - -/* Use yywrap to insert a marker character, which causes the - scanner to return Y_EOF, before return a hard EOF. This - wouldn't be necessary, except that bison does not allow - the parser to use EOF (= 0) as a non-terminal */ - -int yywrap() -{ - if (eof_returned) - return (1); - else - { - unput ('\001'); - eof_returned = 1; -#ifdef FLEX_SCANNER - yy_did_buffer_switch_on_eof = 1; -#endif - return (0); - } -} - - -/* A backslash has just been read, return the character designated by *STR. */ - -static char -scan_escape (char **str) -{ - char first = **str; - *str += 1; - switch (first) - { - case 'a': return '\a'; - case 'b': return '\b'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case '\\': return '\\'; - case '"': return '"'; - case '\'': return '\''; - - case 'x': - case 'X': - { - char c1 = **str, c2 = *(*str + 1); - int b = 0; - - if ('0' <= c1 && c1 <= '9') b = c1 - '0'; - else if ('A' <= c1 && c1 <= 'F') b = c1 - 'A' + 10; - else if ('a' <= c1 && c1 <= 'f') b = c1 - 'a' + 10; - else yyerror ("Bad character in \\X construct in string"); - - b <<= 4; - if ('0' <= c2 && c2 <= '9') b += c2 - '0'; - else if ('A' <= c2 && c2 <= 'F') b += c2 - 'A' + 10; - else if ('a' <= c2 && c2 <= 'f') b += c2 - 'a' + 10; - else yyerror ("Bad character in \\X construct in string"); - - *str += 2; - return (char) b; - } - - default: - { - char message[] = "Bad character \\X"; - message[strlen (message) - 1] = first; - yyerror (message); - return '\0'; - } - } -} - - -/* Return a freshly-allocated copy of STRING with the last CHOP - characters removed. */ - -static char * -copy_str (char *str, int chop) -{ - int new_len = strlen (str) - chop; - char *new_str = (char *) xmalloc (new_len + 1), *n; - - for (n = new_str; *str != '\0' && new_len > 0; new_len -= 1) - if (*str == '\\') - switch (*(str + 1)) - { - case 'n': - { - *n ++ = '\n'; - str += 2; - new_len -= 1; - continue; - } - case 't': - { - *n ++ = '\t'; - str += 2; - new_len -= 1; - continue; - } - case '"': - { - *n ++ = '"'; - str += 2; - new_len -= 1; - continue; - } - case '0': /* \nnn */ - case '1': - case '2': - case '3': - { - char c2 = *(str + 2), c3 = *(str + 3); - int b = (*(str + 1) - '0') << 3; - - if ('0' <= c2 && c2 <= '7') - b += (c2 - '0') << 3; - else - yyerror ("Bad character in \\ooo construct in string"); - - if ('0' <= c3 && c3 <= '7') - b += c3 - '0'; - else - yyerror ("Bad character in \\ooo construct in string"); - - *n ++ = (char) b; - str += 4; - new_len -= 3; - continue; - } - case 'X': - { - char c2 = *(str + 2), c3 = *(str + 3); - int b = 0; - - if ('0' <= c2 && c2 <= '9') - b = c2 - '0'; - else if ('A' <= c2 && c2 <= 'F') - b = c2 - 'A' + 10; - else - yyerror ("Bad character in \\X construct in string"); - - b <<= 4; - if ('0' <= c3 && c3 <= '9') - b += c3 - '0'; - else if ('A' <= c3 && c3 <= 'F') - b += c3 - 'A' + 10; - else - yyerror ("Bad character in \\X construct in string"); - - *n ++ = (char) b; - str += 4; - new_len -= 3; - continue; - } - default: - { - *n ++ = *str ++; - continue; - } - } - else - *n ++ = *str ++; - - *n = '\0'; - return (new_str); -} - - -/* On a parse error, write out the current line and print a caret (^) - below the point at which the error occured. Also, reset the input - stream to the begining of the next line. */ - -char* -erroneous_line () -{ - int prefix_length = yytext - current_line; - int i, c; - str_stream ss; - - ss_init (&ss); - - if (current_line == NULL) return ss_to_string (&ss); - - /* Print part of line that has been consumed. */ - ss_printf (&ss, " "); - if (0 <= prefix_length) - { - /* yytext and current_line point to same line */ - c = *(current_line + prefix_length); - *(current_line + prefix_length) = '\0'; - ss_printf (&ss, "%s", current_line); - *(current_line + prefix_length) = (char)c; - ss_printf (&ss, "%s", yytext); - } - else - { - /* yytext and current_line point to different lines */ - ss_printf (&ss, "%s", current_line); - prefix_length = strlen(current_line); - } - - /* Flush the rest of the line (not consumed) from lex input. */ - if (*yytext != '\n') - { -#ifdef __cplusplus - while ((c = yyinput ()) != '\n' && c != EOF && c != 1) -#else - while ((c = input ()) != '\n' && c != EOF && c != 1) -#endif - { - ss_printf (&ss, "%c", c); - } - if (c == '\n') unput ('\n'); - current_line = NULL; - } - - /* Print marker to point at which consumption stopped. */ - ss_printf (&ss, "\n "); - for (i = 0; i < prefix_length; i ++) ss_printf (&ss, " "); - ss_printf (&ss, "^\n"); - - return ss_to_string (&ss); -} - - -static name_val_val keyword_tbl [] = { -#undef OP -#define OP(NAME, OPCODE, TYPE, R_OPCODE) {NAME, OPCODE, TYPE}, -#include "op.h" -}; - - -static int -check_keyword (char *id, int allow_pseudo_ops) -{ - name_val_val *entry = - map_string_to_name_val_val (keyword_tbl, - sizeof(keyword_tbl) / sizeof (name_val_val), - id); - if (entry == NULL) - return (0); - else if (!allow_pseudo_ops && entry->value2 == PSEUDO_OP) - return (0); - else - return (entry->value1); -} - - -static name_val_val register_tbl [] = { - {"a0", 4, 0}, - {"a1", 5, 0}, - {"a2", 6, 0}, - {"a3", 7, 0}, - {"at", 1, 0}, - {"fp", 30, 0}, - {"gp", 28, 0}, - {"k0", 26, 0}, - {"k1", 27, 0}, - {"kt0", 26, 0}, - {"kt1", 27, 0}, - {"ra", 31, 0}, - {"s0", 16, 0}, - {"s1", 17, 0}, - {"s2", 18, 0}, - {"s3", 19, 0}, - {"s4", 20, 0}, - {"s5", 21, 0}, - {"s6", 22, 0}, - {"s7", 23, 0}, - {"s8", 30, 0}, - {"sp", 29, 0}, - {"t0", 8, 0}, - {"t1", 9, 0}, - {"t2", 10, 0}, - {"t3", 11, 0}, - {"t4", 12, 0}, - {"t5", 13, 0}, - {"t6", 14, 0}, - {"t7", 15, 0}, - {"t8", 24, 0}, - {"t9", 25, 0}, - {"v0", 2, 0}, - {"v1", 3, 0}, - {"zero", 0, 0} -}; - -int -register_name_to_number (char *name) -{ - int c1 = *name, c2 = *(name + 1); - - if ('0' <= c1 && c1 <= '9' - && (c2 == '\0' || (('0' <= c2 && c2 <= '9') && *(name + 2) == '\0'))) - return (atoi (name)); - else if (c1 == 'f' && c2 >= '0' && c2 <= '9') - return atoi (name + 1); - else - { - name_val_val *entry = - map_string_to_name_val_val (register_tbl, - sizeof (register_tbl) / sizeof (name_val_val), - name); - if (entry == NULL) - return (-1); - else - return (entry->value1); - } -} - - -/* Exactly once, return the current source line, as a printable string - with a line number. Subsequent calls receive NULL instead of the - line. */ - -char * -source_line () -{ - if (line_returned) - return (NULL); - else if (current_line == NULL) /* Error on line */ - return (NULL); - else - { - char *eol1, c1; - char *null1 = NULL; - char *r; - - /* Find end of line: */ - for (eol1 = current_line; *eol1 != '\0' && *eol1 != '\n'; ) eol1 += 1; - -#ifdef FLEX_SCANNER - /* Ran into null byte, inserted by yylex. In necessary, look further - for newline. (This only works for scanners produced by flex. Other - versions of lex need similar code, or source code lines will end - early. */ - if (*eol1 == '\0' && yy_hold_char != '\n') - { - null1 = eol1; - *eol1 = yy_hold_char; - for ( ; *eol1 != '\0' && *eol1 != '\n'; ) - eol1 += 1; - } -#endif - - /* Save end-of-line character and null terminate string so it can - be printed. */ - c1 = *eol1; - *eol1 = '\0'; - - r = (char *) xmalloc (eol1 - current_line + 10); - sprintf (r, "%d: %s", current_line_no, current_line); - - /* Restore end-of-line character and, if necessary, yylex's null byte. */ - *eol1 = c1; - if (null1 != NULL) - { - *null1 = '\0'; - } - line_returned = 1; - return ((char *) r); - } -} diff --git a/spim-jsspim/CPU/spim-syscall.h b/spim-jsspim/CPU/spim-syscall.h deleted file mode 100644 index f350f07..0000000 --- a/spim-jsspim/CPU/spim-syscall.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPIM S20 MIPS simulator. - System calls implemented by simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#define PRINT_INT_SYSCALL 1 -#define PRINT_FLOAT_SYSCALL 2 -#define PRINT_DOUBLE_SYSCALL 3 -#define PRINT_STRING_SYSCALL 4 -#define READ_INT_SYSCALL 5 -#define READ_FLOAT_SYSCALL 6 -#define READ_DOUBLE_SYSCALL 7 -#define READ_STRING_SYSCALL 8 -#define SBRK_SYSCALL 9 -#define EXIT_SYSCALL 10 -#define PRINT_CHARACTER_SYSCALL 11 -#define READ_CHARACTER_SYSCALL 12 - -#define OPEN_SYSCALL 13 -#define READ_SYSCALL 14 -#define WRITE_SYSCALL 15 -#define CLOSE_SYSCALL 16 - -#define EXIT2_SYSCALL 17 diff --git a/spim-jsspim/CPU/spim-utils.cpp b/spim-jsspim/CPU/spim-utils.cpp deleted file mode 100755 index 562b653..0000000 --- a/spim-jsspim/CPU/spim-utils.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/* SPIM S20 MIPS simulator. - Misc. routines for SPIM. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include -#include -#include - -#include "spim.h" -#include "version.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "data.h" -#include "reg.h" -#include "mem.h" -#include "scanner.h" -#include "parser.h" -#include "parser_yacc.h" -#include "run.h" -#include "sym-tbl.h" - - -/* Internal functions: */ - -static mem_addr copy_int_to_stack (int n); -static mem_addr copy_str_to_stack (char *s); -static void delete_all_breakpoints (); - - -int exception_occurred; - -int initial_text_size = TEXT_SIZE; - -int initial_data_size = DATA_SIZE; - -mem_addr initial_data_limit = DATA_LIMIT; - -int initial_stack_size = STACK_SIZE; - -mem_addr initial_stack_limit = STACK_LIMIT; - -int initial_k_text_size = K_TEXT_SIZE; - -int initial_k_data_size = K_DATA_SIZE; - -mem_addr initial_k_data_limit = K_DATA_LIMIT; - - - -/* Initialize or reinitialize the state of the machine. */ - -void -initialize_world (char* exception_file_names, bool print_message) -{ - /* Allocate the floating point registers */ - if (FGR == NULL) - FPR = (double *) xmalloc (FPR_LENGTH * sizeof (double)); - /* Allocate the memory */ - make_memory (initial_text_size, - initial_data_size, initial_data_limit, - initial_stack_size, initial_stack_limit, - initial_k_text_size, - initial_k_data_size, initial_k_data_limit); - initialize_registers (); - initialize_inst_tables (); - initialize_symbol_table (); - k_text_begins_at_point (K_TEXT_BOT); - k_data_begins_at_point (K_DATA_BOT); - data_begins_at_point (DATA_BOT); - text_begins_at_point (TEXT_BOT); - - if (exception_file_names != NULL) - { - bool old_bare = bare_machine; - bool old_accept = accept_pseudo_insts; - char *filename; - char *files; - - /* Save machine state */ - bare_machine = false; /* Exception handler uses extended machine */ - accept_pseudo_insts = true; - - /* strtok modifies the string, so we must back up the string prior to use. */ - if ((files = strdup (exception_file_names)) == NULL) - fatal_error ("Insufficient memory to complete.\n"); - - for (filename = strtok (files, ";"); filename != NULL; filename = strtok (NULL, ";")) - { - if (!read_assembly_file (filename)) - fatal_error ("Cannot read exception handler: %s\n", filename); - - if (print_message) - write_output (message_out, "Loaded: %s\n", filename); - } - - free (files); - - /* Restore machine state */ - bare_machine = old_bare; - accept_pseudo_insts = old_accept; - - if (!bare_machine) - { - (void)make_label_global ("main"); /* In case .globl main forgotten */ - (void)record_label ("main", 0, 0); - } - } - initialize_scanner (stdin); - delete_all_breakpoints (); -} - - -void -write_startup_message () -{ - write_output (message_out, "SPIM %s\n", SPIM_VERSION); - write_output (message_out, "Copyright 1990-2017 by James Larus.\n"); - write_output (message_out, "All Rights Reserved.\n"); - write_output (message_out, "SPIM is distributed under a BSD license.\n"); - write_output (message_out, "See the file README for a full copyright notice.\n"); -} - - - -void -initialize_registers () -{ - memclr (FPR, FPR_LENGTH * sizeof (double)); - FGR = (float *) FPR; - FWR = (int *) FPR; - - memclr (R, R_LENGTH * sizeof (reg_word)); - R[REG_SP] = STACK_TOP - BYTES_PER_WORD - 4096; /* Initialize $sp */ - HI = LO = 0; - PC = 0; - - CP0_BadVAddr = 0; - CP0_Count = 0; - CP0_Compare = 0; - CP0_Status = (CP0_Status_CU & 0x30000000) | CP0_Status_IM | CP0_Status_UM; - CP0_Cause = 0; - CP0_EPC = 0; -#ifdef SPIM_BIGENDIAN - CP0_Config = CP0_Config_BE; -#else - CP0_Config = 0; -#endif - - FIR = FIR_W | FIR_D | FIR_S; /* Word, double, & single implemented */ - FCSR = 0x0; - FCCR = 0x0; - FEXR = 0x0; - FENR = 0x0; -} - - -/* Read file NAME, which should contain assembly code. Return true if - successful and false otherwise. */ - -bool -read_assembly_file (char *name) -{ - FILE *file = fopen (name, "rt"); - - if (file == NULL) - { - error ("Cannot open file: `%s'\n", name); - return false; - } - else - { - initialize_scanner (file); - initialize_parser (name); - - while (!yyparse ()) ; - - fclose (file); - flush_local_labels (!parse_error_occurred); - end_of_assembly_file (); - return true; - } -} - - -mem_addr -starting_address () -{ - return (find_symbol_address (DEFAULT_RUN_LOCATION)); -} - - -#define MAX_ARGS 10000 - -/* Initialize the SPIM stack from a string containing the command line. */ - -void -initialize_stack(const char *command_line) -{ - int argc = 0; - char *argv[MAX_ARGS]; - char *a; - char *args = str_copy((char*)command_line); /* Destructively modify string */ - char *orig_args = args; - - while (*args != '\0') - { - /* Skip leading blanks */ - while (*args == ' ' || *args == '\t') args++; - - /* First non-blank char */ - a = args; - - /* Last non-blank, non-null char */ - while (*args != ' ' && *args != '\t' && *args != '\0') args++; - - /* Terminate word */ - if (a != args) - { - if (*args != '\0') - *args++ = '\0'; /* Null terminate */ - - argv[argc++] = a; - - if (MAX_ARGS == argc) - { - break; /* If too many, ignore rest of list */ - } - } - } - - initialize_run_stack (argc, argv); - free (orig_args); -} - - -/* Initialize the SPIM stack with ARGC, ARGV, and ENVP data. */ - -#ifdef _MSC_VER -#define environ _environ -#endif - -void -initialize_run_stack (int argc, char **argv) -{ - char **p; - extern char **environ; - int i, j = 0, env_j; - mem_addr addrs[10000]; - - - R[REG_SP] = STACK_TOP - 1; /* Initialize $sp */ - - /* Put strings on stack: */ - /* env: */ - for (p = environ; *p != NULL; p++) - addrs[j++] = copy_str_to_stack (*p); - env_j = j; - - /* argv; */ - for (i = 0; i < argc; i++) - addrs[j++] = copy_str_to_stack (argv[i]); - - /* Align stack pointer for word-size data */ - R[REG_SP] = R[REG_SP] & ~3; /* Round down to nearest word */ - R[REG_SP] -= BYTES_PER_WORD; /* First free word on stack */ - R[REG_SP] = R[REG_SP] & ~7; /* Double-word align stack-pointer*/ - - /* Build vectors on stack: */ - /* env: */ - (void)copy_int_to_stack (0); /* Null-terminate vector */ - for (i = env_j - 1; i >= 0; i--) - R[REG_A2] = copy_int_to_stack (addrs[i]); - - /* argv: */ - (void)copy_int_to_stack (0); /* Null-terminate vector */ - for (i = j - 1; i >= env_j; i--) - R[REG_A1] = copy_int_to_stack (addrs[i]); - - /* argc: */ - R[REG_A0] = argc; - set_mem_word (R[REG_SP], argc); /* Leave argc on stack */ -} - - -static mem_addr -copy_str_to_stack (char *s) -{ - int i = (int)strlen (s); - while (i >= 0) - { - set_mem_byte (R[REG_SP], s[i]); - R[REG_SP] -= 1; - i -= 1; - } - return ((mem_addr) R[REG_SP] + 1); /* Leaves stack pointer byte-aligned!! */ -} - - -static mem_addr -copy_int_to_stack (int n) -{ - set_mem_word (R[REG_SP], n); - R[REG_SP] -= BYTES_PER_WORD; - return ((mem_addr) R[REG_SP] + BYTES_PER_WORD); -} - - -/* Run the program, starting at PC, for STEPS instructions. Display each - instruction before executing if DISPLAY is true. If CONT_BKPT is - true, then step through a breakpoint. CONTINUABLE is true if - execution can continue. Return true if breakpoint is encountered. */ - -bool -run_program (mem_addr pc, int steps, bool display, bool cont_bkpt, bool* continuable) -{ - if (cont_bkpt && inst_is_breakpoint (pc)) - { - mem_addr addr = PC == 0 ? pc : PC; - - delete_breakpoint (addr); - exception_occurred = 0; - *continuable = run_spim (addr, 1, display); - add_breakpoint (addr); - steps -= 1; - pc = PC; - } - - exception_occurred = 0; - *continuable = run_spim (pc, steps, display); - if (exception_occurred && CP0_ExCode == ExcCode_Bp) - { - /* Turn off EXL bit, so subsequent interrupts set EPC since the break is - handled by SPIM code, not MIPS code. */ - CP0_Status &= ~CP0_Status_EXL; - return true; - } - else - return false; -} - - -/* Record of where a breakpoint was placed and the instruction previously - in memory. */ - -typedef struct bkptrec -{ - mem_addr addr; - instruction *inst; - struct bkptrec *next; -} bkpt; - - -static bkpt *bkpts = NULL; - - -/* Set a breakpoint at memory location ADDR. */ - -void -add_breakpoint (mem_addr addr) -{ - bkpt *rec = (bkpt *) xmalloc (sizeof (bkpt)); - - rec->next = bkpts; - rec->addr = addr; - - if ((rec->inst = set_breakpoint (addr)) != NULL) - bkpts = rec; - else - { - if (exception_occurred) - error ("Cannot put a breakpoint at address 0x%08x\n", addr); - else - error ("No instruction to breakpoint at address 0x%08x\n", addr); - free (rec); - } -} - - -/* Delete all breakpoints at memory location ADDR. */ - -void -delete_breakpoint (mem_addr addr) -{ - bkpt *p, *b; - int deleted_one = 0; - - for (p = NULL, b = bkpts; b != NULL; ) - if (b->addr == addr) - { - bkpt *n; - - set_mem_inst (addr, b->inst); - if (p == NULL) - bkpts = b->next; - else - p->next = b->next; - n = b->next; - free (b); - b = n; - deleted_one = 1; - } - else - p = b, b = b->next; - if (!deleted_one) - error ("No breakpoint to delete at 0x%08x\n", addr); -} - - -static void -delete_all_breakpoints () -{ - bkpt *b, *n; - - for (b = bkpts, n = NULL; b != NULL; b = n) - { - n = b->next; - free (b); - } - bkpts = NULL; -} - - -/* List all breakpoints. */ - -void -list_breakpoints () -{ - bkpt *b; - - if (bkpts) - for (b = bkpts; b != NULL; b = b->next) - write_output (message_out, "Breakpoint at 0x%08x\n", b->addr); - else - write_output (message_out, "No breakpoints set\n"); -} - - - -/* Utility routines */ - - -/* Return the entry in the linear TABLE of length LENGTH with key STRING. - TABLE must be sorted on the key field. - Return NULL if no such entry exists. */ - -name_val_val * -map_string_to_name_val_val (name_val_val tbl[], int tbl_len, char *id) -{ - int low = 0; - int hi = tbl_len - 1; - - while (low <= hi) - { - int mid = (low + hi) / 2; - char *idp = id, *np = tbl[mid].name; - - while (*idp == *np && *idp != '\0') {idp ++; np ++;} - - if (*np == '\0' && *idp == '\0') /* End of both strings */ - return (& tbl[mid]); - else if (*idp > *np) - low = mid + 1; - else - hi = mid - 1; - } - - return NULL; -} - - -/* Return the entry in the linear TABLE of length LENGTH with VALUE1 field NUM. - TABLE must be sorted on the VALUE1 field. - Return NULL if no such entry exists. */ - -name_val_val * -map_int_to_name_val_val (name_val_val tbl[], int tbl_len, int num) -{ - int low = 0; - int hi = tbl_len - 1; - - while (low <= hi) - { - int mid = (low + hi) / 2; - - if (tbl[mid].value1 == num) - return (&tbl[mid]); - else if (num > tbl[mid].value1) - low = mid + 1; - else - hi = mid - 1; - } - - return NULL; -} - - -#ifdef NEED_VSPRINTF -char * -vsprintf (str, fmt, args) - char *str,*fmt; - va_list *args; -{ - FILE _strbuf; - - _strbuf._flag = _IOWRT+_IOSTRG; - _strbuf._ptr = str; - _strbuf._cnt = 32767; - _doprnt(fmt, args, &_strbuf); - putc('\0', &_strbuf); - return(str); -} -#endif - - -#ifdef NEED_STRTOL -unsigned long -strtol (const char* str, const char** eptr, int base) -{ - long result; - - if (base != 0 && base != 16) - fatal_error ("SPIM's strtol only works for base 16 (not base %d)\n", base); - if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) - { - str += 2; - sscanf (str, "%lx", &result); - } - else if (base == 16) - { - sscanf (str, "%lx", &result); - } - else - { - sscanf (str, "%ld", &result); - } - return (result); -} -#endif - - -#ifdef NEED_STRTOUL -unsigned long -strtoul (const char* str, char** eptr, int base) -{ - unsigned long result; - - if (base != 0 && base != 16) - fatal_error ("SPIM's strtoul only works for base 16 (not base %d)\n", base); - if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) - { - str += 2; - sscanf (str, "%lx", &result); - } - else if (base == 16) - { - sscanf (str, "%lx", &result); - } - else - { - sscanf (str, "%ld", &result); - } - return (result); -} -#endif - - -char * -str_copy (char *str) -{ - return (strcpy ((char*)xmalloc ((int)strlen (str) + 1), str)); -} - - -void * -xmalloc (int size) -{ - void *x = (void *) malloc (size); - - if (x == 0) - fatal_error ("Out of memory at request for %d bytes.\n"); - return (x); -} - - -/* Allocate a zero'ed block of storage. */ - -void * -zmalloc (int size) -{ - void *z = (void *) malloc (size); - - if (z == 0) - fatal_error ("Out of memory at request for %d bytes.\n"); - - memclr (z, size); - return (z); -} diff --git a/spim-jsspim/CPU/spim-utils.h b/spim-jsspim/CPU/spim-utils.h deleted file mode 100755 index 33273c5..0000000 --- a/spim-jsspim/CPU/spim-utils.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to misc. routines for SPIM. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Triple containing a string and two integers. Used in tables - mapping from a name to values. */ - -typedef struct -{ - char *name; - int value1; - int value2; -} name_val_val; - - - -/* Exported functions: */ - -void add_breakpoint (mem_addr addr); -void delete_breakpoint (mem_addr addr); -void format_data_segs (str_stream *ss); -void format_insts (str_stream *ss, mem_addr from, mem_addr to); -void format_mem (str_stream *ss, mem_addr from, mem_addr to); -void format_registers (str_stream *ss, int print_gpr_hex, int print_fpr_hex); -void initialize_registers (); -void initialize_stack (const char *command_line); -void initialize_run_stack (int argc, char **argv); -void initialize_world (char *exception_file_names, bool print_message); -void list_breakpoints (); -name_val_val *map_int_to_name_val_val (name_val_val tbl[], int tbl_len, int num); -name_val_val *map_string_to_name_val_val (name_val_val tbl[], int tbl_len, char *id); -bool read_assembly_file (char *name); -bool run_program (mem_addr pc, int steps, bool display, bool cont_bkpt, bool* continuable); -mem_addr starting_address (); -char *str_copy (char *str); -void write_startup_message (); -void *xmalloc (int); -void *zmalloc (int); diff --git a/spim-jsspim/CPU/spim.h b/spim-jsspim/CPU/spim.h deleted file mode 100755 index 39aba75..0000000 --- a/spim-jsspim/CPU/spim.h +++ /dev/null @@ -1,260 +0,0 @@ -/* SPIM S20 MIPS simulator. - Definitions for the SPIM S20. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef NULL -#define NULL 0 -#endif - -/* This declaration must match the endianness of the machine SPIM is running on. You CANNOT - set SPIM to simulate a different endianness than the machine that executes it. Almost - every processor (notably the x86) is little endian today. If your machine is big endian, - define -DSPIM_BIGENDIAN in the Makefile. */ - -#ifndef SPIM_BIGENDIAN -#define SPIM_LITTLENDIAN -#endif - - -/* Type declarations for portability. They work for DEC's Alpha (64 bits) - and 32 bit machines */ - -typedef int int32; -typedef unsigned int uint32; -typedef union {int i; void* p;} intptr_union; - - -#define streq(s1, s2) !strcmp(s1, s2) - - -/* Round V to next greatest B boundary */ -#define ROUND_UP(V, B) (((int) V + (B-1)) & ~(B-1)) -#define ROUND_DOWN(V, B) (((int) V) & ~(B-1)) - -/* Sign-extend an int16 to an int32 */ -#define SIGN_EX(X) (((X) & 0x8000) ? ((X) | 0xffff0000) : (X)) - - -#ifdef MIN /* Some systems define these in system includes */ -#undef MIN -#endif -#ifdef MAX -#undef MAX -#endif -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) - - -/* Useful and pervasive declarations: */ - -#ifdef NEED_MEM_FUNCTIONS -#define memcpy(T, F, S) bcopy((void*)F, (void*)T, S) -#define memclr(B, S) bzero(B, S) -#define memcmp(S1, S2, N) bcmp(S1, S2, N) -#else -#include -#define memclr(B, S) memset((void*)B, 0, S) -#endif - -#include -#include -#define QSORT_FUNC int(*)(const void *, const void *) - - - -#define K 1024 - - -/* Type of a memory address. Must be a 32-bit quantity to match MIPS. */ - -typedef uint32 /*@alt int @*/ mem_addr; - - -#define BYTES_PER_WORD 4 /* On the MIPS processor */ - - -/* Sizes of memory segments. */ - -/* Initial size of text segment. */ - -#ifndef TEXT_SIZE -#define TEXT_SIZE (256*K) /* 1/4 MB */ -#endif - -/* Initial size of k_text segment. */ - -#ifndef K_TEXT_SIZE -#define K_TEXT_SIZE (64*K) /* 64 KB */ -#endif - -/* The data segment must be larger than 64K since we immediate grab - 64K for the small data segment pointed to by $gp. The data segment is - expanded by an sbrk system call. */ - -/* Initial size of data segment. */ - -#ifndef DATA_SIZE -#define DATA_SIZE (256*K) /* 1/4 MB */ -#endif - -/* Maximum size of data segment. */ - -#ifndef DATA_LIMIT -#define DATA_LIMIT (K*K) /* 1 MB */ -#endif - -/* Initial size of k_data segment. */ - -#ifndef K_DATA_SIZE -#define K_DATA_SIZE (64*K) /* 64 KB */ -#endif - -/* Maximum size of k_data segment. */ - -#ifndef K_DATA_LIMIT -#define K_DATA_LIMIT (K*K) /* 1 MB */ -#endif - -/* The stack grows down automatically. */ - -/* Initial size of stack segment. */ - -#ifndef STACK_SIZE -#define STACK_SIZE (64*K) /* 64 KB */ -#endif - -/* Maximum size of stack segment. */ - -#ifndef STACK_LIMIT -#define STACK_LIMIT (256*K) /* 1/4 MB */ -#endif - - -/* Name of the function to invoke at start up */ - -#define DEFAULT_RUN_LOCATION "__start" - - -/* Name of the symbol marking the end of the exception handler */ - -#define END_OF_TRAP_HANDLER_SYMBOL "__eoth" - - -/* Default number of instructions to execute. */ - -#define DEFAULT_RUN_STEPS 2147483647 - - -/* Address to branch to when exception occurs */ -#ifdef MIPS1 -/* MIPS R2000 */ -#define EXCEPTION_ADDR 0x80000080 -#else -/* MIPS32 */ -#define EXCEPTION_ADDR 0x80000180 -#endif - -/* Maximum size of object stored in the small data segment pointed to by $gp */ - -#define SMALL_DATA_SEG_MAX_SIZE 8 - -#ifndef DIRECT_MAPPED -#define DIRECT_MAPPED 0 -#define TWO_WAY_SET 1 -#endif - - -/* Interval (in instructions) at which memory-mapped IO registers are - checked and updated. (This is to reduce overhead from making system calls - to check for IO. It can be set as low as 1.) */ - -#define IO_INTERVAL 100 - - -/* Number of IO_INTERVALs that a character remains in receiver buffer, - even if another character is available. */ - -#define RECV_INTERVAL 100 - - -/* Number of IO_INTERVALs that it takes to write a character. */ - -#define TRANS_LATENCY 100 - - -/* Iterval (milliseconds) for the hardware timer in CP0. */ - -#define TIMER_TICK_MS 10 /* 100 times per second */ - - - -/* A port is either a Unix file descriptor (an int) or a FILE* pointer. */ - -#include - -typedef union {int i; FILE* f;} port; - - -/* Exported functions (from spim.c or xspim.c): */ - -int console_input_available (); -void error (char *fmt, ...); -void fatal_error (char *fmt, ...); -char get_console_char (); -void put_console_char (char c); -void read_input (char *str, int n); -void run_error (char *fmt, ...); -void write_output (port, char *fmt, ...); - - -/* Exported variables: */ - -extern bool bare_machine; /* => simulate bare machine */ -extern bool accept_pseudo_insts; /* => parse pseudo instructions */ -extern bool delayed_branches; /* => simulate delayed branches */ -extern bool delayed_loads; /* => simulate delayed loads */ -extern bool quiet; /* => no warning messages */ -extern char *exception_file_name; /* File containing exception handler */ -extern bool force_break; /* => stop interpreter loop */ -extern bool parser_error_occurred; /* => parse resulted in error */ -extern int spim_return_value; /* Value returned when spim exits */ -/* Actual type of structure pointed to depends on X/terminal interface */ -extern port message_out, console_out, console_in; -extern bool mapped_io; /* => activate memory-mapped IO */ -extern int initial_text_size; -extern int initial_data_size; -extern mem_addr initial_data_limit; -extern int initial_stack_size; -extern mem_addr initial_stack_limit; -extern int initial_k_text_size; -extern int initial_k_data_size; -extern mem_addr initial_k_data_limit; diff --git a/spim-jsspim/CPU/string-stream.cpp b/spim-jsspim/CPU/string-stream.cpp deleted file mode 100755 index a083247..0000000 --- a/spim-jsspim/CPU/string-stream.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* SPIM S20 MIPS simulator. - Append-only output stream convertable to a string. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include -#include - -#include "spim.h" -#include "string-stream.h" - - -#ifndef SS_BUF_LENGTH -/* Initialize length of buffer */ -#define SS_BUF_LENGTH 256 -#endif - - -void -ss_init (str_stream* ss) -{ - ss->buf = (char *) malloc (SS_BUF_LENGTH); - ss->max_length = SS_BUF_LENGTH; - ss->empty_pos = 0; - ss->initialized = 1; -} - - -void -ss_clear (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - ss->empty_pos = 0; -} - - -void -ss_erase (str_stream* ss, int n) -{ - if (0 == ss->initialized) ss_init (ss); - - ss->empty_pos -= n; - if (ss->empty_pos <0) ss->empty_pos = 0; -} - - -int -ss_length (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - return ss->empty_pos; -} - - -char* -ss_to_string (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - if (ss->empty_pos == ss->max_length) - { - /* Not enough room to store output: increase buffer size and try again */ - ss->max_length = ss->max_length + 1; - ss->buf = (char *) realloc (ss->buf, (size_t)ss->max_length); - if (NULL == ss->buf) - fatal_error ("realloc failed\n"); - } - ss->buf[ss->empty_pos] = '\0'; /* Null terminate string */ - ss->empty_pos += 1; - return ss->buf; -} - - -void -ss_printf (str_stream* ss, char* fmt, ...) -{ - int free_space; - int n; - va_list args; - - va_start (args, fmt); - - if (0 == ss->initialized) ss_init (ss); - - free_space = ss->max_length - ss->empty_pos; -#ifdef _WIN32 - /* Returns -1 when buffer is too small */ - while ((n = _vsnprintf (ss->buf + ss->empty_pos, free_space, fmt, args)) < 0) -#else - /* Returns necessary space when buffer is too small */ - while ((n = vsnprintf (ss->buf + ss->empty_pos, free_space, fmt, args)) >= free_space) -#endif - { - /* Not enough room to store output: double buffer size and try again */ - ss->max_length = 2 * ss->max_length; - ss->buf = (char *) realloc (ss->buf, (size_t)ss->max_length); - free_space = ss->max_length - ss->empty_pos; - if (NULL == ss->buf) - fatal_error ("realloc failed\n"); - - va_end (args); /* Restart argument pointer */ - va_start (args, fmt); - } - ss->empty_pos += n; - - /* Null terminate string (for debugging) if there is enough room*/ - if (ss->empty_pos < ss->max_length) - ss->buf[ss->empty_pos] = '\0'; - - va_end (args); -} diff --git a/spim-jsspim/CPU/string-stream.h b/spim-jsspim/CPU/string-stream.h deleted file mode 100755 index 1766b67..0000000 --- a/spim-jsspim/CPU/string-stream.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPIM S20 MIPS simulator. - Append-only output stream convertable to a string. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -typedef struct str_stm -{ - char* buf; /* Buffer containing output */ - int max_length; /* Length of buffer */ - int empty_pos; /* Index of empty char in stream*/ - int initialized; /* Stream initialized? */ -} str_stream; - - -void ss_init (str_stream* ss); -void ss_clear (str_stream* ss); -void ss_erase (str_stream* ss, int n); -int ss_length (str_stream* ss); -char* ss_to_string (str_stream* ss); -void ss_printf (str_stream* ss, char* fmt, ...); diff --git a/spim-jsspim/CPU/sym-tbl.cpp b/spim-jsspim/CPU/sym-tbl.cpp deleted file mode 100755 index b2490b5..0000000 --- a/spim-jsspim/CPU/sym-tbl.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to maintain symbol table to resolve symbolic labels. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "data.h" -#include "parser.h" -#include "sym-tbl.h" -#include "parser_yacc.h" - - -/* Local functions: */ - -static void get_hash (char *name, int *slot_no, label **entry); -static void resolve_a_label_sub (label *sym, instruction *inst, mem_addr pc); - - - -/* Keep track of the memory location that a label represents. If we - see a reference to a label that is not yet defined, then record the - reference so that we can patch up the instruction when the label is - defined. - - At the end of a file, we flush the hash table of all non-global - labels so they can't be seen in other files. */ - - -static label *local_labels = NULL; /* Labels local to current file. */ - - -#define HASHBITS 30 - -#define LABEL_HASH_TABLE_SIZE 8191 - - -/* Map from name of a label to a label structure. */ - -static label *label_hash_table [LABEL_HASH_TABLE_SIZE]; - - -/* Initialize the symbol table by removing and freeing old entries. */ - -void -initialize_symbol_table () -{ - int i; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - { - label *x, *n; - - for (x = label_hash_table [i]; x != NULL; x = n) - { - free (x->name); - n = x->next; - free (x); - } - label_hash_table [i] = NULL; - } - - local_labels = NULL; -} - - - -/* Lookup for a label with the given NAME. Set the SLOT_NO to be the hash - table bucket that contains (or would contain) the label's record. If the - record is already in the table, set ENTRY to point to it. Otherwise, - set ENTRY to be NULL. */ - -static void -get_hash (char *name, int *slot_no, label **entry) -{ - int hi; - int i; - label *lab; - int len; - - /* Compute length of name in len. */ - for (len = 0; name[len]; len++) ; - - /* Compute hash code */ - hi = len; - for (i = 0; i < len; i++) - hi = ((hi * 613) + (unsigned)(name[i])); - - hi &= (1 << HASHBITS) - 1; - hi %= LABEL_HASH_TABLE_SIZE; - - *slot_no = hi; - /* Search table for entry */ - for (lab = label_hash_table [hi]; lab; lab = lab->next) - if (streq (lab->name, name)) - { - *entry = lab; /* <-- return if found */ - return; - } - *entry = NULL; -} - - -/* Lookup label with NAME. Either return its symbol table entry or NULL - if it is not in the table. */ - -label * -label_is_defined (char *name) -{ - int hi; - label *entry; - - get_hash (name, &hi, &entry); - - return (entry); -} - - -/* Return a label with a given NAME. If an label with that name has - previously been looked-up, the same node is returned this time. */ - -label * -lookup_label (char *name) -{ - int hi; - label *entry, *lab; - - get_hash (name, &hi, &entry); - - if (entry != NULL) - return (entry); - - /* Not found, create one, add to chain */ - lab = (label *) xmalloc (sizeof (label)); - lab->name = str_copy (name); - lab->addr = 0; - lab->global_flag = 0; - lab->const_flag = 0; - lab->gp_flag = 0; - lab->uses = NULL; - - lab->next = label_hash_table [hi]; - label_hash_table [hi] = lab; - return lab; /* <-- return if created */ -} - - -/* Record that the label named NAME refers to ADDRESS. If RESOLVE_USES is - true, resolve all references to it. Return the label structure. */ - -label * -record_label (char *name, mem_addr address, int resolve_uses) -{ - label *l = lookup_label (name); - - if (!l->gp_flag) - { - if (l->addr != 0) - { - yyerror ("Label is defined for the second time"); - return (l); - } - l->addr = address; - } - - if (resolve_uses) - { - resolve_label_uses (l); - } - - if (!l->global_flag) - { - l->next_local = local_labels; - local_labels = l; - } - return (l); -} - - -/* Make the label named NAME global. Return its symbol. */ - -label * -make_label_global (char *name) -{ - label *l = lookup_label (name); - - l->global_flag = 1; - return (l); -} - - -/* Record that an INSTRUCTION uses the as-yet undefined SYMBOL. */ - -void -record_inst_uses_symbol (instruction *inst, label *sym) -{ - label_use *u = (label_use *) xmalloc (sizeof (label_use)); - - if (data_dir) /* Want to free up original instruction */ - { - u->inst = copy_inst (inst); - u->addr = current_data_pc (); - } - else - { - u->inst = inst; - u->addr = current_text_pc (); - } - u->next = sym->uses; - sym->uses = u; -} - - -/* Record that a memory LOCATION uses the as-yet undefined SYMBOL. */ - -void -record_data_uses_symbol (mem_addr location, label *sym) -{ - label_use *u = (label_use *) xmalloc (sizeof (label_use)); - - u->inst = NULL; - u->addr = location; - u->next = sym->uses; - sym->uses = u; -} - - -/* Given a newly-defined LABEL, resolve the previously encountered - instructions and data locations that refer to the label. */ - -void -resolve_label_uses (label *sym) -{ - label_use *use; - label_use *next_use; - - for (use = sym->uses; use != NULL; use = next_use) - { - resolve_a_label_sub (sym, use->inst, use->addr); - if (use->inst != NULL && use->addr >= DATA_BOT && use->addr < stack_bot) - { - set_mem_word (use->addr, inst_encode (use->inst)); - free_inst (use->inst); - } - next_use = use->next; - free (use); - } - sym->uses = NULL; -} - - -/* Resolve the newly-defined label in INSTRUCTION. */ - -void -resolve_a_label (label *sym, instruction *inst) -{ - resolve_a_label_sub (sym, - inst, - (data_dir ? current_data_pc () : current_text_pc ())); -} - - -static void -resolve_a_label_sub (label *sym, instruction *inst, mem_addr pc) -{ - if (inst == NULL) - { - /* Memory data: */ - set_mem_word (pc, sym->addr); - } - else - { - /* Instruction: */ - if (EXPR (inst)->pc_relative) - EXPR (inst)->offset = 0 - pc; /* Instruction may have moved */ - - if (EXPR (inst)->symbol == NULL - || SYMBOL_IS_DEFINED (EXPR (inst)->symbol)) - { - int32 value; - int32 field_mask; - - if (opcode_is_branch (OPCODE (inst))) - { - int val; - - /* Drop low two bits since instructions are on word boundaries. */ - val = SIGN_EX (eval_imm_expr (EXPR (inst))); /* 16->32 bits */ - val = (val >> 2) & 0xffff; /* right shift, 32->16 bits */ - - if (delayed_branches) - val -= 1; - - value = val; - field_mask = 0xffff; - } - else if (opcode_is_jump (OPCODE (inst))) - { - value = eval_imm_expr (EXPR (inst)); - if ((value & 0xf0000000) != (pc & 0xf0000000)) - { - error ("Target of jump differs in high-order 4 bits from instruction pc 0x%x\n", pc); - } - /* Drop high four bits, since they come from the PC and the - low two bits since instructions are on word boundaries. */ - value = (value & 0x0fffffff) >> 2; - field_mask = 0xffffffff; /* Already checked that value fits in instruction */ - } - else if (opcode_is_load_store (OPCODE (inst))) - { - /* Label's location is an address */ - value = eval_imm_expr (EXPR (inst)); - field_mask = 0xffff; - - if (value & 0x8000) - { - /* LW/SW sign extends offset. Compensate by adding 1 to high 16 bits. */ - instruction* prev_inst; - instruction* prev_prev_inst; - prev_inst = read_mem_inst (pc - BYTES_PER_WORD); - prev_prev_inst = read_mem_inst (pc - 2 * BYTES_PER_WORD); - - if (prev_inst != NULL - && OPCODE (prev_inst) == Y_LUI_OP - && EXPR (inst)->symbol == EXPR (prev_inst)->symbol - && IMM (prev_inst) == 0) - { - /* Check that previous instruction was LUI and it has no immediate, - otherwise it will have compensated for sign-extension */ - EXPR (prev_inst)->offset += 0x10000; - } - /* There is an ADDU instruction before the LUI if the - LW/SW instruction uses an index register: skip over the ADDU. */ - else if (prev_prev_inst != NULL - && OPCODE (prev_prev_inst) == Y_LUI_OP - && EXPR (inst)->symbol == EXPR (prev_prev_inst)->symbol - && IMM (prev_prev_inst) == 0) - { - EXPR (prev_prev_inst)->offset += 0x10000; - } - } - } - else - { - /* Label's location is a value */ - value = eval_imm_expr (EXPR (inst)); - field_mask = 0xffff; - } - - if ((value & ~field_mask) != (int32)0 - && (value & ~field_mask) != (int32)0xffff0000) - { - error ("Immediate value is too large for field: "); - print_inst (pc); - } - if (opcode_is_jump (OPCODE (inst))) - SET_TARGET (inst, value); /* Don't mask so it is sign-extended */ - else - SET_IMM (inst, value); /* Ditto */ - SET_ENCODING (inst, inst_encode (inst)); - } - else - error ("Resolving undefined symbol: %s\n", - (EXPR (inst)->symbol == NULL) ? "" : EXPR (inst)->symbol->name); - } -} - - -/* Remove all local (non-global) label from the table. */ - -void -flush_local_labels (int issue_undef_warnings) -{ - label *l; - - for (l = local_labels; l != NULL; l = l->next_local) - { - int hi; - label *entry, *lab, *p; - - get_hash (l->name, &hi, &entry); - - for (lab = label_hash_table [hi], p = NULL; - lab; - p = lab, lab = lab->next) - if (lab == entry) - { - if (p == NULL) - label_hash_table [hi] = lab->next; - else - p->next = lab->next; - if (issue_undef_warnings && entry->addr == 0 && !entry->const_flag) - error ("Warning: local symbol %s was not defined\n", - entry->name); - /* Can't free label since IMM_EXPR's still reference it */ - break; - } - } - local_labels = NULL; -} - - -/* Return the address of SYMBOL or 0 if it is undefined. */ - -mem_addr -find_symbol_address (char *symbol) -{ - label *l = lookup_label (symbol); - - if (l == NULL || l->addr == 0) - return 0; - else - return (l->addr); -} - - -/* Print all symbols in the table. */ - -void -print_symbols () -{ - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table [i]; l != NULL; l = l->next) - write_output (message_out, "%s%s at 0x%08x\n", - l->global_flag ? "g\t" : "\t", l->name, l->addr); -} - - -/* Print all undefined symbols in the table. */ - -void -print_undefined_symbols () -{ - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table [i]; l != NULL; l = l->next) - if (l->addr == 0) - write_output (message_out, "%s\n", l->name); -} - - -/* Return a string containing the names of all undefined symbols in the - table, seperated by a newline character. Return NULL if no symbols - are undefined. */ - -char * -undefined_symbol_string () -{ - int buffer_length = 128; - int string_length = 0; - char *buffer = (char*)malloc(buffer_length); - - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table[i]; l != NULL; l = l->next) - if (l->addr == 0) - { - int name_length = (int)strlen(l->name); - int after_length = string_length + name_length + 2; - if (buffer_length < after_length) - { - buffer_length = MAX (2 * buffer_length, 2 * after_length); - buffer = (char*)realloc (buffer, buffer_length); - } - memcpy (buffer + string_length, l->name, name_length); - string_length += name_length; - buffer[string_length] = '\n'; - string_length += 1; - buffer[string_length] = '\0'; /* After end of string */ - } - - if (string_length != 0) - return (buffer); - else - { - free (buffer); - return (NULL); - }; -} diff --git a/spim-jsspim/CPU/sym-tbl.h b/spim-jsspim/CPU/sym-tbl.h deleted file mode 100755 index 94760f3..0000000 --- a/spim-jsspim/CPU/sym-tbl.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPIM S20 MIPS simulator. - Data structures for symbolic addresses. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -typedef struct lab_use -{ - instruction *inst; /* NULL => Data, not code */ - mem_addr addr; - struct lab_use *next; -} label_use; - - -/* Symbol table information on a label. */ - -typedef struct lab -{ - char *name; /* Name of label */ - long addr; /* Address of label or 0 if not yet defined */ - unsigned global_flag : 1; /* Non-zero => declared global */ - unsigned gp_flag : 1; /* Non-zero => referenced off gp */ - unsigned const_flag : 1; /* Non-zero => constant value (in addr) */ - struct lab *next; /* Hash table link */ - struct lab *next_local; /* Link in list of local labels */ - label_use *uses; /* List of instructions that reference */ -} label; /* label that has not yet been defined */ - - -#define SYMBOL_IS_DEFINED(SYM) ((SYM)->addr != 0) - - - -/* Exported functions: */ - -mem_addr find_symbol_address (char *symbol); -void flush_local_labels (int issue_undef_warnings); -void initialize_symbol_table (); -label *label_is_defined (char *name); -label *lookup_label (char *name); -label *make_label_global (char *name); -void print_symbols (); -void print_undefined_symbols (); -label *record_label (char *name, mem_addr address, int resolve_uses); -void record_data_uses_symbol (mem_addr location, label *sym); -void record_inst_uses_symbol (instruction *inst, label *sym); -char *undefined_symbol_string (); -void resolve_a_label (label *sym, instruction *inst); -void resolve_label_uses (label *sym); diff --git a/spim-jsspim/CPU/syscall.cpp b/spim-jsspim/CPU/syscall.cpp deleted file mode 100755 index 0c36b7d..0000000 --- a/spim-jsspim/CPU/syscall.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM syscalls, both in simulator and bare mode. - Execute MIPS syscalls in bare mode, when running on MIPS systems. - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef _WIN32 -#include -#endif -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#endif - -#include "spim.h" -#include "string-stream.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "syscall.h" - - -#ifdef _WIN32 -/* Windows has an handler that is invoked when an invalid argument is passed to a system - call. https://msdn.microsoft.com/en-us/library/a9yf33zb(v=vs.110).aspx - - All good, except that the handler tries to invoke Watson and then kill spim with an exception. - - Override the handler to just report an error. -*/ - -#include -#include -#include - -void myInvalidParameterHandler(const wchar_t* expression, - const wchar_t* function, - const wchar_t* file, - unsigned int line, - uintptr_t pReserved) -{ - if (function != NULL) - { - run_error ("Bad parameter to system call: %s\n", function); - } - else - { - run_error ("Bad parameter to system call\n"); - } -} - -static _invalid_parameter_handler oldHandler; - -void windowsParameterHandlingControl(int flag ) -{ - static _invalid_parameter_handler oldHandler; - static _invalid_parameter_handler newHandler = myInvalidParameterHandler; - - if (flag == 0) - { - oldHandler = _set_invalid_parameter_handler(newHandler); - _CrtSetReportMode(_CRT_ASSERT, 0); // Disable the message box for assertions. - } - else - { - newHandler = _set_invalid_parameter_handler(oldHandler); - _CrtSetReportMode(_CRT_ASSERT, 1); // Enable the message box for assertions. - } -} -#endif - - -/* Decides which syscall to execute or simulate. Returns zero upon - exit syscall and non-zero to continue execution. */ - -int -do_syscall () -{ -#ifdef _WIN32 - windowsParameterHandlingControl(0); -#endif - - /* Syscalls for the source-language version of SPIM. These are easier to - use than the real syscall and are portable to non-MIPS operating - systems. */ - - switch (R[REG_V0]) - { - case PRINT_INT_SYSCALL: - write_output (console_out, "%d", R[REG_A0]); - break; - - case PRINT_FLOAT_SYSCALL: - { - float val = FPR_S (REG_FA0); - - write_output (console_out, "%.8f", val); - break; - } - - case PRINT_DOUBLE_SYSCALL: - write_output (console_out, "%.18g", FPR[REG_FA0 / 2]); - break; - - case PRINT_STRING_SYSCALL: - write_output (console_out, "%s", mem_reference (R[REG_A0])); - break; - - case READ_INT_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - R[REG_RES] = atol (str); - break; - } - - case READ_FLOAT_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - FPR_S (REG_FRES) = (float) atof (str); - break; - } - - case READ_DOUBLE_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - FPR [REG_FRES] = atof (str); - break; - } - - case READ_STRING_SYSCALL: - { - read_input ( (char *) mem_reference (R[REG_A0]), R[REG_A1]); - data_modified = true; - break; - } - - case SBRK_SYSCALL: - { - mem_addr x = data_top; - expand_data (R[REG_A0]); - R[REG_RES] = x; - data_modified = true; - break; - } - - case PRINT_CHARACTER_SYSCALL: - write_output (console_out, "%c", R[REG_A0]); - break; - - case READ_CHARACTER_SYSCALL: - { - static char str [2]; - - read_input (str, 2); - if (*str == '\0') *str = '\n'; /* makes xspim = spim */ - R[REG_RES] = (long) str[0]; - break; - } - - case EXIT_SYSCALL: - spim_return_value = 0; - return (0); - - case EXIT2_SYSCALL: - spim_return_value = R[REG_A0]; /* value passed to spim's exit() call */ - return (0); - - case OPEN_SYSCALL: - { -#ifdef _WIN32 - R[REG_RES] = _open((char*)mem_reference (R[REG_A0]), R[REG_A1], R[REG_A2]); -#else - R[REG_RES] = open((char*)mem_reference (R[REG_A0]), R[REG_A1], R[REG_A2]); -#endif - break; - } - - case READ_SYSCALL: - { - /* Test if address is valid */ - (void)mem_reference (R[REG_A1] + R[REG_A2] - 1); -#ifdef _WIN32 - R[REG_RES] = _read(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); -#else - R[REG_RES] = read(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); -#endif - data_modified = true; - break; - } - - case WRITE_SYSCALL: - { - /* Test if address is valid */ - (void)mem_reference (R[REG_A1] + R[REG_A2] - 1); -#ifdef _WIN32 - R[REG_RES] = _write(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); -#else - R[REG_RES] = write(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); -#endif - break; - } - - case CLOSE_SYSCALL: - { -#ifdef _WIN32 - R[REG_RES] = _close(R[REG_A0]); -#else - R[REG_RES] = close(R[REG_A0]); -#endif - break; - } - - default: - run_error ("Unknown system call: %d\n", R[REG_V0]); - break; - } - -#ifdef _WIN32 - windowsParameterHandlingControl(1); -#endif - return (1); -} - - -void -handle_exception () -{ - if (!quiet && CP0_ExCode != ExcCode_Int) - error ("Exception occurred at PC=0x%08x\n", CP0_EPC); - - exception_occurred = 0; - PC = EXCEPTION_ADDR; - - switch (CP0_ExCode) - { - case ExcCode_Int: - break; - - case ExcCode_AdEL: - if (!quiet) - error (" Unaligned address in inst/data fetch: 0x%08x\n", CP0_BadVAddr); - break; - - case ExcCode_AdES: - if (!quiet) - error (" Unaligned address in store: 0x%08x\n", CP0_BadVAddr); - break; - - case ExcCode_IBE: - if (!quiet) - error (" Bad address in text read: 0x%08x\n", CP0_BadVAddr); - break; - - case ExcCode_DBE: - if (!quiet) - error (" Bad address in data/stack read: 0x%08x\n", CP0_BadVAddr); - break; - - case ExcCode_Sys: - if (!quiet) - error (" Error in syscall\n"); - break; - - case ExcCode_Bp: - exception_occurred = 0; - return; - - case ExcCode_RI: - if (!quiet) - error (" Reserved instruction execution\n"); - break; - - case ExcCode_CpU: - if (!quiet) - error (" Coprocessor unuable\n"); - break; - - case ExcCode_Ov: - if (!quiet) - error (" Arithmetic overflow\n"); - break; - - case ExcCode_Tr: - if (!quiet) - error (" Trap\n"); - break; - - case ExcCode_FPE: - if (!quiet) - error (" Floating point\n"); - break; - - default: - if (!quiet) - error ("Unknown exception: %d\n", CP0_ExCode); - break; - } -} diff --git a/spim-jsspim/CPU/syscall.h b/spim-jsspim/CPU/syscall.h deleted file mode 100755 index f8c0b46..0000000 --- a/spim-jsspim/CPU/syscall.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM syscalls, both in simulator and bare mode. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions. */ - -int do_syscall (); -void handle_exception (); - -#define PRINT_INT_SYSCALL 1 -#define PRINT_FLOAT_SYSCALL 2 -#define PRINT_DOUBLE_SYSCALL 3 -#define PRINT_STRING_SYSCALL 4 - -#define READ_INT_SYSCALL 5 -#define READ_FLOAT_SYSCALL 6 -#define READ_DOUBLE_SYSCALL 7 -#define READ_STRING_SYSCALL 8 - -#define SBRK_SYSCALL 9 - -#define EXIT_SYSCALL 10 - -#define PRINT_CHARACTER_SYSCALL 11 -#define READ_CHARACTER_SYSCALL 12 - -#define OPEN_SYSCALL 13 -#define READ_SYSCALL 14 -#define WRITE_SYSCALL 15 -#define CLOSE_SYSCALL 16 - -#define EXIT2_SYSCALL 17 - diff --git a/spim-jsspim/CPU/version.h b/spim-jsspim/CPU/version.h deleted file mode 100644 index 2c1902e..0000000 --- a/spim-jsspim/CPU/version.h +++ /dev/null @@ -1 +0,0 @@ -#define SPIM_VERSION "Version 9.1.20 of August 29, 2017" diff --git a/spim-jsspim/spim.cpp b/spim-jsspim/spim.cpp deleted file mode 100644 index 4cee351..0000000 --- a/spim-jsspim/spim.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "emscripten/bind.h" -#include "emscripten/val.h" - -#include -#include -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "data.h" -#include "version.h" - -using namespace emscripten; - -bool bare_machine; /* => simulate bare machine */ -bool delayed_branches; /* => simulate delayed branches */ -bool delayed_loads; /* => simulate delayed loads */ -bool accept_pseudo_insts = true; /* => parse pseudo instructions */ -bool quiet; /* => no warning messages */ -char *exception_file_name; -port message_out, console_out, console_in; -bool mapped_io; /* => activate memory-mapped IO */ -int spim_return_value; /* Value returned when spim exits */ - -static str_stream ss; -void init() { - error("Based on SPIM %s " - "by James Larus.\n", - SPIM_VERSION); - - initialize_world(DEFAULT_EXCEPTION_HANDLER, false); - initialize_run_stack(0, nullptr); - read_assembly_file("input.s"); - PC = starting_address(); -} - - -int step(int step_size, bool cont_bkpt) { - mem_addr addr = PC == 0 ? starting_address() : PC; - if (step_size == 0) step_size = DEFAULT_RUN_STEPS; - - bool continuable, bp_encountered; - bp_encountered = run_program(addr, step_size, false, cont_bkpt, &continuable); - - if (!continuable) { // finished - printf("\n"); // to flush output - error("Execution finished\n"); - return 0; - } - - if (bp_encountered) { - error("Breakpoint encountered at 0x%08x\n", PC); - return -1; - } - - return 1; -} - - -std::string getUserText() { - ss_clear(&ss); - format_insts(&ss, TEXT_BOT, text_top); - return std::string(ss_to_string(&ss)); -} - -std::string getKernelText() { - ss_clear(&ss); - format_insts(&ss, K_TEXT_BOT, k_text_top); - return std::string(ss_to_string(&ss)); -} - -val getStack() { return val(typed_memory_view(STACK_LIMIT / 16, (unsigned int *) stack_seg)); } -val getUserData() { return val(typed_memory_view(data_top - DATA_BOT, (unsigned int *) data_seg)); } -val getKernelData() { return val(typed_memory_view(k_data_top - K_DATA_BOT, (unsigned int *) k_data_seg)); } -val getGeneralRegVals() { return val(typed_memory_view(32, (unsigned int *) R)); } -val getFloatRegVals() { return val(typed_memory_view(32, (float *) FPR)); } -val getDoubleRegVals() { return val(typed_memory_view(16, (double *) FPR)); } - -val getSpecialRegVals() { - static unsigned int specialRegs[12]; - specialRegs[0] = PC; - specialRegs[1] = CP0_EPC; - specialRegs[2] = CP0_Cause; - specialRegs[3] = CP0_BadVAddr; - specialRegs[4] = CP0_Status; - specialRegs[5] = HI; - specialRegs[6] = LO; - specialRegs[7] = FIR; - specialRegs[8] = FCSR; - specialRegs[9] = FCCR; - specialRegs[10] = FEXR; - specialRegs[11] = FENR; - - return val(typed_memory_view(12, specialRegs)); -} - -EMSCRIPTEN_BINDINGS(init) { function("init", &init); } -EMSCRIPTEN_BINDINGS(step) { function("step", &step); } -EMSCRIPTEN_BINDINGS(getUserText) { function("getUserText", &getUserText); } -EMSCRIPTEN_BINDINGS(getKernelText) { function("getKernelText", &getKernelText); } -EMSCRIPTEN_BINDINGS(getStack) { function("getStack", &getStack); } -EMSCRIPTEN_BINDINGS(getUserData) { function("getUserData", &getUserData); } -EMSCRIPTEN_BINDINGS(getKernelData) { function("getKernelData", &getKernelData); } -EMSCRIPTEN_BINDINGS(getGeneralRegVals) { function("getGeneralRegVals", &getGeneralRegVals); } -EMSCRIPTEN_BINDINGS(getFloatRegVals) { function("getFloatRegVals", &getFloatRegVals); } -EMSCRIPTEN_BINDINGS(getDoubleRegVals) { function("getDoubleRegVals", &getDoubleRegVals); } -EMSCRIPTEN_BINDINGS(getSpecialRegVals) { function("getSpecialRegVals", &getSpecialRegVals); } -EMSCRIPTEN_BINDINGS(delete_breakpoint) { function("deleteBreakpoint", &delete_breakpoint); } -EMSCRIPTEN_BINDINGS(add_breakpoint) { function("addBreakpoint", &add_breakpoint); } - -/* Print an error message. */ - -void error(char *fmt, ...) { - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); -} - -/* Print the error message then exit. */ - -void fatal_error(char *fmt, ...) { - va_list args; - va_start(args, fmt); - fmt = va_arg(args, char *); - vfprintf(stderr, fmt, args); - exit(-1); -} - -/* Print an error message and return to top level. */ - -void run_error(char *fmt, ...) { - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); -} - -/* IO facilities: */ - -void write_output(port fp, char *fmt, ...) { - va_list args; - va_start(args, fmt); - vfprintf(stdout, fmt, args); - fflush(stdout); - va_end(args); -} - -/* Simulate the semantics of fgets (not gets) on Unix file. */ - -void read_input(char *str, int str_size) { - char *ptr; - ptr = str; - while (1 < str_size) /* Reserve space for null */ - { - char buf[1]; - if (read((int) console_in.i, buf, 1) <= 0) /* Not in raw mode! */ - break; - - *ptr++ = buf[0]; - str_size -= 1; - - if (buf[0] == '\n') break; - } - - if (0 < str_size) *ptr = '\0'; /* Null terminate input */ -} - -int console_input_available() { - return 0; -} - -char get_console_char() { - char buf; - read(0, &buf, 1); - return (buf); -} - -void put_console_char(char c) { - putc(c, stdout); - fflush(stdout); -} \ No newline at end of file diff --git a/spim-qtbase/CPU/data.cpp b/spim-qtbase/CPU/data.cpp deleted file mode 100755 index a9a049a..0000000 --- a/spim-qtbase/CPU/data.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to manipulate data segment directives. - - Copyright (c) 1990-2021, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser.h" -#include "run.h" -#include "data.h" - - -/* The first 64K of the data segment are dedicated to small data - segment, which is pointed to by $gp. This register points to the - middle of the segment, so we can use the full offset field in an - instruction. */ - -static mem_addr next_data_pc; /* Location for next datum in user process */ - -static mem_addr next_k_data_pc; /* Location for next datum in kernel */ - -static bool in_kernel = 0; /* => data goes to kdata, not data */ - -#define DATA_PC (in_kernel ? next_k_data_pc : next_data_pc) - -static mem_addr next_gp_item_addr; /* Address of next item accessed off $gp */ - -static bool enable_data_auto_alignment = true; /* => align literal to natural bound */ - - - -/* If TO_KERNEL is true, subsequent data will be placed in the - kernel data segment. If false, data will go to the user's data - segment.*/ - -void -user_kernel_data_segment (bool to_kernel) -{ - in_kernel = to_kernel; -} - - -void -end_of_assembly_file () -{ - in_kernel = false; - enable_data_auto_alignment = true; -} - - -/* Set the point at which the first datum is stored to be ADDRESS + - 64K. The 64K increment allocates an area pointed to by register - $gp, which is initialized. */ - -void -data_begins_at_point (mem_addr addr) -{ - if (bare_machine) - next_data_pc = addr; - else - { - next_gp_item_addr = addr; - gp_midpoint = addr + 32*K; - R[REG_GP] = gp_midpoint; - next_data_pc = addr + 64 * K; - } -} - - -/* Set the point at which the first datum is stored in the kernel's - data segment. */ - -void -k_data_begins_at_point (mem_addr addr) -{ - next_k_data_pc = addr; -} - - -/* Arrange that the next datum is stored on a memory boundary with its - low ALIGNMENT bits equal to 0. If argument is 0, disable automatic - alignment.*/ - -void -align_data (int alignment) -{ - if (alignment == 0) - enable_data_auto_alignment = false; - else if (in_kernel) - { - next_k_data_pc = (next_k_data_pc + (1 << alignment) - 1) & (0xffffffff << alignment); - fix_current_label_address (next_k_data_pc); - } - else - { - next_data_pc = (next_data_pc + (1 << alignment) - 1) & (0xffffffff << alignment); - fix_current_label_address (next_data_pc); - } -} - - -void -set_data_alignment (int alignment) -{ - if (enable_data_auto_alignment) - align_data (alignment); -} - - -void -enable_data_alignment () -{ - enable_data_auto_alignment = true; -} - - -/* Set the location (in user or kernel data space) for the next datum. */ - -void -set_data_pc (mem_addr addr) -{ - if (in_kernel) - next_k_data_pc = addr; - else - next_data_pc = addr; -} - - -/* Return the address at which the next datum will be stored. */ - -mem_addr -current_data_pc () -{ - return (DATA_PC); -} - - -/* Bump the address at which the next data will be stored by DELTA - bytes. */ - -void -increment_data_pc (int delta) -{ - if (in_kernel) - { - next_k_data_pc += delta; - if (k_data_top <= next_k_data_pc) - expand_k_data(ROUND_UP(next_k_data_pc - k_data_top + 1, 64*K)); - } - else - { - next_data_pc += delta; - if (data_top <= next_data_pc) - expand_data(ROUND_UP(next_data_pc - data_top + 1, 64*K)); - } -} - - -/* Process a .extern NAME SIZE directive. */ - -void -extern_directive (char *name, int size) -{ - label *sym = make_label_global (name); - - if (!bare_machine - && !sym->gp_flag // Not already a global symbol - && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE - && next_gp_item_addr + size < gp_midpoint + 32*K) - { - sym->gp_flag = 1; - sym->addr = next_gp_item_addr; - next_gp_item_addr += size; - } -} - - -/* Process a .lcomm NAME SIZE directive. */ - -void -lcomm_directive (char *name, int size) -{ - if (!bare_machine - && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE - && next_gp_item_addr + size < gp_midpoint + 32*K) - { - label *sym = record_label (name, next_gp_item_addr, 1); - sym->gp_flag = 1; - - next_gp_item_addr += size; - /* Don't need to initialize since memory starts with 0's */ - } - else - { - (void)record_label (name, next_data_pc, 1); - - for ( ; size > 0; size --) - { - store_byte (0); - } - } -} - - -/* Process a .ascii STRING or .asciiz STRING directive. */ - -void -store_string (char *string, int length, bool null_terminate) -{ - for ( ; length > 0; string ++, length --) { - store_byte (*string); - } - if (null_terminate) - { - store_byte (0); - } -} - - -/* Process a .byte EXPR directive. */ - -void -store_byte (int value) -{ - set_mem_byte (DATA_PC, value); - increment_data_pc (1); -} - - -/* Process a .half EXPR directive. */ - -void -store_half (int value) -{ - if ((DATA_PC & 0x1) != 0) - { -#ifdef SPIM_BIGENDIAN - store_byte ((value >> 8) & 0xff); - store_byte (value & 0xff); -#else - store_byte (value & 0xff); - store_byte ((value >> 8) & 0xff); -#endif - } - else - { - set_mem_half (DATA_PC, value); - increment_data_pc (BYTES_PER_WORD / 2); - } -} - - -/* Process a .word EXPR directive. */ - -void -store_word (int value) -{ - if ((DATA_PC & 0x3) != 0) - { -#ifdef SPIM_BIGENDIAN - store_half ((value >> 16) & 0xffff); - store_half (value & 0xffff); -#else - store_half (value & 0xffff); - store_half ((value >> 16) & 0xffff); -#endif - } - else - { - set_mem_word (DATA_PC, value); - increment_data_pc (BYTES_PER_WORD); - } -} - - -/* Process a .double EXPR directive. */ - -void -store_double (double *value) -{ - if ((DATA_PC & 0x7) != 0) - { - store_word (* ((mem_word *) value)); - store_word (* (((mem_word *) value) + 1)); - } - else - { - set_mem_word (DATA_PC, *((mem_word *) value)); - increment_data_pc (BYTES_PER_WORD); - set_mem_word (DATA_PC, *(((mem_word *) value) + 1)); - increment_data_pc (BYTES_PER_WORD); - } -} - - -/* Process a .float EXPR directive. */ - -void -store_float (double *value) -{ - float val = (float)*value; - float *vp = &val; - - if ((DATA_PC & 0x3) != 0) - { - store_half (*(mem_word *) vp & 0xffff); - store_half ((*(mem_word *) vp >> 16) & 0xffff); - } - else - { - set_mem_word (DATA_PC, *((mem_word *) vp)); - increment_data_pc (BYTES_PER_WORD); - } -} diff --git a/spim-qtbase/CPU/data.h b/spim-qtbase/CPU/data.h deleted file mode 100755 index c058f88..0000000 --- a/spim-qtbase/CPU/data.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to code to manipulate data segment directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -void align_data (int alignment); -mem_addr current_data_pc (); -void data_begins_at_point (mem_addr addr); -void enable_data_alignment (); -void end_of_assembly_file (); -void extern_directive (char *name, int size); -void increment_data_pc (int value); -void k_data_begins_at_point (mem_addr addr); -void lcomm_directive (char *name, int size); -void set_data_alignment (int); -void set_data_pc (mem_addr addr); -void set_text_pc (mem_addr addr); -void store_byte (int value); -void store_double (double *value); -void store_float (double *value); -void store_half (int value); -void store_string (char *string, int length, bool null_terminate); -void store_word (int value); -void user_kernel_data_segment (bool to_kernel); diff --git a/spim-qtbase/CPU/display-utils.cpp b/spim-qtbase/CPU/display-utils.cpp deleted file mode 100755 index 045969d..0000000 --- a/spim-qtbase/CPU/display-utils.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* SPIM S20 MIPS simulator. - Utilities for displaying machine contents. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "data.h" -#include "reg.h" -#include "mem.h" -#include "run.h" -#include "sym-tbl.h" - - -char* int_reg_names[32] = - {"r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"}; - - -static mem_addr format_partial_line (str_stream *ss, mem_addr addr); - - -/* Write to the stream the contents of the machine's registers, in a wide - variety of formats. */ - -void -format_registers (str_stream *ss, int print_gpr_hex, int print_fpr_hex) -{ - int i; - char *grstr, *fpstr; - char *grfill, *fpfill; - - ss_printf (ss, " PC = %08x ", PC); - ss_printf (ss, "EPC = %08x ", CP0_EPC); - ss_printf (ss, " Cause = %08x ", CP0_Cause); - ss_printf (ss, " BadVAddr= %08x\n", CP0_BadVAddr); - ss_printf (ss, " Status = %08x ", CP0_Status); - ss_printf (ss, "HI = %08x ", HI); - ss_printf (ss, " LO = %08x\n", LO); - - if (print_gpr_hex) - grstr = "R%-2d (%2s) = %08x", grfill = " "; - else - grstr = "R%-2d (%2s) = %-10d", grfill = " "; - - ss_printf (ss, "\t\t\t\t General Registers\n"); - for (i = 0; i < 8; i++) - { - ss_printf (ss, grstr, i, int_reg_names[i], R[i]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+8, int_reg_names[i+8], R[i+8]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+16, int_reg_names[i+16], R[i+16]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+24, int_reg_names[i+24], R[i+24]); - ss_printf (ss, "\n"); - } - - ss_printf (ss, "\n FIR = %08x ", FIR); - ss_printf (ss, " FCSR = %08x ", FCSR); - - ss_printf (ss, "\t\t\t Double Floating Point Registers\n"); - - if (print_fpr_hex) - fpstr = "FP%-2d=%08x,%08x", fpfill = " "; - else - fpstr = "FP%-2d = %#-13.6g", fpfill = " "; - - if (print_fpr_hex) - for (i = 0; i < 4; i += 1) - { - int *r1, *r2; - - /* Use pointers to cast to ints without invoking float->int conversion - so we can just print the bits. */ - r1 = (int *)&FPR[i]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)&FPR[i+4]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+8, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)&FPR[i+8]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+16, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)&FPR[i+12]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+24, *r1, *r2); - ss_printf (ss, "\n"); - } - else for (i = 0; i < 4; i += 1) - { - ss_printf (ss, fpstr, 2*i, FPR[i]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+8, FPR[i+4]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+16, FPR[i+8]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+24, FPR[i+12]); - ss_printf (ss, "\n"); - } - - if (print_fpr_hex) - fpstr = "FP%-2d=%08x", fpfill = " "; - else - fpstr = "FP%-2d = %#-13.6g", fpfill = " "; - - ss_printf (ss, "\t\t\t Single Floating Point Registers\n"); - - if (print_fpr_hex) - for (i = 0; i < 8; i += 1) - { - /* Use pointers to cast to ints without invoking float->int conversion - so we can just print the bits. */ - ss_printf (ss, fpstr, i, *(int *)&FPR_S(i)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+8, *(int *)&FPR_S(i+8)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+16, *(int *)&FPR_S(i+16)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+24, *(int *)&FPR_S(i+24)); - ss_printf (ss, "\n"); - } - else for (i = 0; i < 8; i += 1) - { - ss_printf (ss, fpstr, i, FPR_S(i)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+8, FPR_S(i+8)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+16, FPR_S(i+16)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+24, FPR_S(i+24)); - ss_printf (ss, "\n"); - } -} - - - -/* Write to the stream a printable representation of the instructions in - memory addresses: FROM...TO. */ - -void -format_insts (str_stream *ss, mem_addr from, mem_addr to) -{ - instruction *inst; - mem_addr i; - - for (i = from; i < to; i += 4) - { - inst = read_mem_inst (i); - if (inst != NULL) - { - format_an_inst (ss, inst, i); - } - } -} - - -/* Write to the stream a printable representation of the data and stack - segments. */ - -void -format_data_segs (str_stream *ss) -{ - ss_printf (ss, "\tDATA\n"); - format_mem (ss, DATA_BOT, data_top); - - ss_printf (ss, "\n\tSTACK\n"); - format_mem (ss, ROUND_DOWN (R[29], BYTES_PER_WORD), STACK_TOP); - - ss_printf (ss, "\n\tKERNEL DATA\n"); - format_mem (ss, K_DATA_BOT, k_data_top); -} - - -#define BYTES_PER_LINE (4*BYTES_PER_WORD) - - -/* Write to the stream a printable representation of the data in memory - address: FROM...TO. */ - -void -format_mem (str_stream *ss, mem_addr from, mem_addr to) -{ - mem_word val; - mem_addr i = ROUND_UP (from, BYTES_PER_WORD); - int j; - - i = format_partial_line (ss, i); - - for ( ; i < to; ) - { - /* Count consecutive zero words */ - for (j = 0; (i + (uint32) j * BYTES_PER_WORD) < to; j += 1) - { - val = read_mem_word (i + (uint32) j * BYTES_PER_WORD); - if (val != 0) - { - break; - } - } - - if (j >= 4) - { - /* Block of 4 or more zero memory words: */ - ss_printf (ss, "[0x%08x]...[0x%08x] 0x00000000\n", - i, - i + (uint32) j * BYTES_PER_WORD); - - i = i + (uint32) j * BYTES_PER_WORD; - i = format_partial_line (ss, i); - } - else - { - /* Fewer than 4 zero words, print them on a single line: */ - ss_printf (ss, "[0x%08x] ", i); - do - { - val = read_mem_word (i); - ss_printf (ss, " 0x%08x", (unsigned int)val); - i += BYTES_PER_WORD; - } - while (i % BYTES_PER_LINE != 0); - - ss_printf (ss, "\n"); - } - } -} - - -/* Write to the stream a text line containing a fraction of a - quadword. Return the address after the last one written. */ - -static mem_addr -format_partial_line (str_stream *ss, mem_addr addr) -{ - if ((addr % BYTES_PER_LINE) != 0) - { - ss_printf (ss, "[0x%08x] ", addr); - - for (; (addr % BYTES_PER_LINE) != 0; addr += BYTES_PER_WORD) - { - mem_word val = read_mem_word (addr); - ss_printf (ss, " 0x%08x", (unsigned int)val); - } - - ss_printf (ss, "\n"); - } - - return addr; -} diff --git a/spim-qtbase/CPU/dump_ops.cpp b/spim-qtbase/CPU/dump_ops.cpp deleted file mode 100644 index 873acf3..0000000 --- a/spim-qtbase/CPU/dump_ops.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* SPIM S20 MIPS simulator. - Dump the op.h file in a readable format to allow checking of encodings. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include - -typedef struct inst_t -{ - char *opcode; - - union - { - unsigned int x; - struct - { - unsigned int funct:6; - unsigned int pad:10; - unsigned int rt:5; - unsigned int rs:5; - unsigned int op:6; - } f; - }; -} inst; - - -#define OP(a, b, c, d) {a, d}, - -inst ops [] = { -#include "op.h" -}; - - -int -compare_ops (inst *p1, inst *p2) -{ - if (p1->f.op < p2->f.op) - return (-1); - else if (p1->f.op > p2->f.op) - return (1); - else - { - if (p1->f.rs < p2->f.rs) - return (-1); - else if (p1->f.rs > p2->f.rs) - return (1); - else - { - if (p1->f.rt < p2->f.rt) - return (-1); - else if (p1->f.rt > p2->f.rt) - return (1); - else - { - if (p1->f.funct < p2->f.funct) - return (-1); - else if (p1->f.funct > p2->f.funct) - return (1); - else - return 0; - } - } - } -} - - -main (int argc, char** argv) -{ - /* Remove pseudo ops (opcode == -1) from table */ - int empty, next; - for (empty = 0, next = 0; next < (sizeof(ops) / sizeof(ops[0])); next += 1) - { - if (-1 == ops[next].x) - { - } - else - { - ops[empty] = ops[next]; - empty += 1; - } - } - - /* Radix sort instructions by field: op, rs, rt, funct */ - qsort (ops, empty, sizeof(ops[0]), compare_ops); - - /* Print related instructions in groups */ - int i; - for (i = 0; i < empty; i += 1) - { - if (0 < i && ops[i - 1].f.op != ops[i].f.op) - printf ("\n"); - - printf ("%10s op=%2d rs=%2d rt=%2d funct=%02x 0x%08x\n", - ops[i].opcode, - ops[i].f.op, - ops[i].f.rs, - ops[i].f.rt, - ops[i].f.funct, - ops[i].x); - } -} diff --git a/spim-qtbase/CPU/exceptions.s b/spim-qtbase/CPU/exceptions.s deleted file mode 100755 index c88334d..0000000 --- a/spim-qtbase/CPU/exceptions.s +++ /dev/null @@ -1,195 +0,0 @@ -# SPIM S20 MIPS simulator. -# The default exception handler for spim. -# -# Copyright (c) 1990-2010, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -# Define the exception handling code. This must go first! - - .kdata -__m1_: .asciiz " Exception " -__m2_: .asciiz " occurred and ignored\n" -__e0_: .asciiz " [Interrupt] " -__e1_: .asciiz " [TLB]" -__e2_: .asciiz " [TLB]" -__e3_: .asciiz " [TLB]" -__e4_: .asciiz " [Address error in inst/data fetch] " -__e5_: .asciiz " [Address error in store] " -__e6_: .asciiz " [Bad instruction address] " -__e7_: .asciiz " [Bad data address] " -__e8_: .asciiz " [Error in syscall] " -__e9_: .asciiz " [Breakpoint] " -__e10_: .asciiz " [Reserved instruction] " -__e11_: .asciiz "" -__e12_: .asciiz " [Arithmetic overflow] " -__e13_: .asciiz " [Trap] " -__e14_: .asciiz "" -__e15_: .asciiz " [Floating point] " -__e16_: .asciiz "" -__e17_: .asciiz "" -__e18_: .asciiz " [Coproc 2]" -__e19_: .asciiz "" -__e20_: .asciiz "" -__e21_: .asciiz "" -__e22_: .asciiz " [MDMX]" -__e23_: .asciiz " [Watch]" -__e24_: .asciiz " [Machine check]" -__e25_: .asciiz "" -__e26_: .asciiz "" -__e27_: .asciiz "" -__e28_: .asciiz "" -__e29_: .asciiz "" -__e30_: .asciiz " [Cache]" -__e31_: .asciiz "" -__excp: .word __e0_, __e1_, __e2_, __e3_, __e4_, __e5_, __e6_, __e7_, __e8_, __e9_ - .word __e10_, __e11_, __e12_, __e13_, __e14_, __e15_, __e16_, __e17_, __e18_, - .word __e19_, __e20_, __e21_, __e22_, __e23_, __e24_, __e25_, __e26_, __e27_, - .word __e28_, __e29_, __e30_, __e31_ -s1: .word 0 -s2: .word 0 - -# This is the exception handler code that the processor runs when -# an exception occurs. It only prints some information about the -# exception, but can server as a model of how to write a handler. -# -# Because we are running in the kernel, we can use $k0/$k1 without -# saving their old values. - -# This is the exception vector address for MIPS-1 (R2000): -# .ktext 0x80000080 -# This is the exception vector address for MIPS32: - .ktext 0x80000180 -# Select the appropriate one for the mode in which SPIM is compiled. - .set noat - move $k1 $at # Save $at - .set at - sw $v0 s1 # Not re-entrant and we can't trust $sp - sw $a0 s2 # But we need to use these registers - - mfc0 $k0 $13 # Cause register - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - - # Print information about exception. - # - li $v0 4 # syscall 4 (print_str) - la $a0 __m1_ - syscall - - li $v0 1 # syscall 1 (print_int) - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - syscall - - li $v0 4 # syscall 4 (print_str) - andi $a0 $k0 0x3c - lw $a0 __excp($a0) - nop - syscall - - bne $k0 0x18 ok_pc # Bad PC exception requires special checks - nop - - mfc0 $a0 $14 # EPC - andi $a0 $a0 0x3 # Is EPC word-aligned? - beq $a0 0 ok_pc - nop - - li $v0 10 # Exit on really bad PC - syscall - -ok_pc: - li $v0 4 # syscall 4 (print_str) - la $a0 __m2_ - syscall - - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - bne $a0 0 ret # 0 means exception was an interrupt - nop - -# Interrupt-specific code goes here! -# Don't skip instruction at EPC since it has not executed. - - -ret: -# Return from (non-interrupt) exception. Skip offending instruction -# at EPC to avoid infinite loop. -# - mfc0 $k0 $14 # Bump EPC register - addiu $k0 $k0 4 # Skip faulting instruction - # (Need to handle delayed branch case here) - mtc0 $k0 $14 - - -# Restore registers and reset procesor state -# - lw $v0 s1 # Restore other registers - lw $a0 s2 - - .set noat - move $at $k1 # Restore $at - .set at - - mtc0 $0 $13 # Clear Cause register - - mfc0 $k0 $12 # Set Status register - ori $k0 0x1 # Interrupts enabled - mtc0 $k0 $12 - -# Return from exception on MIPS32: - eret - -# Return sequence for MIPS-I (R2000): -# rfe # Return from exception handler - # Should be in jr's delay slot -# jr $k0 -# nop - - - -# Standard startup code. Invoke the routine "main" with arguments: -# main(argc, argv, envp) -# - .text - .globl __start -__start: - lw $a0 0($sp) # argc - addiu $a1 $sp 4 # argv - addiu $a2 $a1 4 # envp - sll $v0 $a0 2 - addu $a2 $a2 $v0 - jal main - nop - - li $v0 10 - syscall # syscall 10 (exit) - - .globl __eoth -__eoth: diff --git a/spim-qtbase/CPU/inst.cpp b/spim-qtbase/CPU/inst.cpp deleted file mode 100755 index dc0b13e..0000000 --- a/spim-qtbase/CPU/inst.cpp +++ /dev/null @@ -1,1700 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to build assembly instructions and resolve symbolic labels. - - Copyright (c) 1990-2021, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser.h" -#include "scanner.h" -#include "parser_yacc.h" -#include "data.h" - - -/* Local functions: */ - -static int compare_pair_value (name_val_val *p1, name_val_val *p2); -static void format_imm_expr (str_stream *ss, imm_expr *expr, int base_reg); -static void i_type_inst_full_word (int opcode, int rt, int rs, imm_expr *expr, - int value_known, int32 value); -static void inst_cmp (instruction *inst1, instruction *inst2); -static instruction *make_r_type_inst (int opcode, int rd, int rs, int rt); -static instruction *mk_i_inst (int32 value, int opcode, int rs, int rt, int offset); -static instruction *mk_j_inst (int32 value, int opcode, int target); -static instruction *mk_r_inst (int32 value, int opcode, int rs, int rt, int rd, int shamt); -static instruction *mk_co_r_inst (int32 value, int opcode, int fd, int fs, int ft); -static void produce_immediate (imm_expr *expr, int rt, int value_known, int32 value); -static void sort_a_opcode_table (); -static void sort_i_opcode_table (); -static void sort_name_table (); - - -/* Local variables: */ - -/* True means store instructions in kernel, not user, text segment */ - -static bool in_kernel = 0; - -/* Instruction used as breakpoint by SPIM: */ - -static instruction *break_inst = NULL; - - -/* Locations for next instruction in user and kernel text segments */ - -static mem_addr next_text_pc; - -static mem_addr next_k_text_pc; - -static bool enable_text_auto_alignment = true; /* => align literal to natural bound */ - - -#define INST_PC (in_kernel ? next_k_text_pc : next_text_pc) - - -/* Set ADDRESS at which the next instruction is stored. */ - -void -text_begins_at_point (mem_addr addr) -{ - next_text_pc = addr; - in_kernel = false; - enable_text_auto_alignment = true; -} - - -void -k_text_begins_at_point (mem_addr addr) -{ - next_k_text_pc = addr; - in_kernel = false; - enable_text_auto_alignment = true; -} - -/* Arrange that the next instruction is stored on a memory boundary with its - low ALIGNMENT bits equal to 0. If argument is 0, disable automatic - alignment.*/ - -void -align_text (int alignment) -{ - if (alignment == 0) - enable_text_auto_alignment = false; - else if (in_kernel) - { - next_k_text_pc = (next_k_text_pc + (1 << alignment) - 1) & (0xffffffff << alignment); - fix_current_label_address (next_k_text_pc); - } - else - { - next_text_pc = (next_text_pc + (1 << alignment) - 1) & (0xffffffff << alignment); - fix_current_label_address (next_text_pc); - } -} - - -void -set_text_alignment (int alignment) -{ - if (enable_text_auto_alignment) - align_text (alignment); -} - - -void -enable_text_alignment () -{ - enable_text_auto_alignment = true; -} - - -/* Set the location (in user or kernel text space) for the next instruction. */ - -void -set_text_pc (mem_addr addr) -{ - if (in_kernel) - next_k_text_pc = addr; - else - next_text_pc = addr; -} - - -/* Return address for next instruction, in appropriate text segment. */ - -mem_addr -current_text_pc () -{ - return (INST_PC); -} - - -/* Increment the current text segement PC. */ - -void -increment_text_pc (int delta) -{ - if (in_kernel) - { - next_k_text_pc += delta; - if (k_text_top <= next_k_text_pc) - run_error("Can't expand kernel text segment\n"); - } - else - { - next_text_pc += delta; - if (text_top <= next_text_pc) - run_error("Can't expand text segment\n"); - } -} - - -/* If FLAG is true, next instruction goes to kernel text segment, - otherwise it goes to user segment. */ - -void -user_kernel_text_segment (bool to_kernel) -{ - in_kernel = to_kernel; -} - - -/* Store an INSTRUCTION in memory at the next location. */ - -void -store_instruction (instruction *inst) -{ - if (data_dir) - { - store_word (inst_encode (inst)); - free_inst (inst); - } - else if (text_dir) - { - exception_occurred = 0; - set_mem_inst (INST_PC, inst); - if (exception_occurred) - error ("Invalid address (0x%08x) for instruction\n", INST_PC); - else - increment_text_pc (BYTES_PER_WORD); - if (inst != NULL) - { - SET_SOURCE (inst, source_line ()); - if (ENCODING (inst) == 0) - SET_ENCODING (inst, inst_encode (inst)); - } - } -} - - - -void -i_type_inst_free (int opcode, int rt, int rs, imm_expr *expr) -{ - i_type_inst (opcode, rt, rs, expr); - free (expr); -} - - -/* Produce an immediate instruction with the OPCODE, RT, RS, and IMM - fields. NB, because the immediate value may not fit in the field, - this routine may produce more than one instruction. On the bare - machine, we resolve symbolic address, but they better produce values - that fit into instruction's immediate field. */ - -void -i_type_inst (int opcode, int rt, int rs, imm_expr *expr) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_EXPR (inst, copy_imm_expr (expr)); - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* Evaluate the instruction's expression. */ - int32 value = eval_imm_expr (expr); - - if (!bare_machine - && (((opcode == Y_ADDI_OP - || opcode == Y_ADDIU_OP - || opcode == Y_SLTI_OP - || opcode == Y_SLTIU_OP - || opcode == Y_TEQI_OP - || opcode == Y_TGEI_OP - || opcode == Y_TGEIU_OP - || opcode == Y_TLTI_OP - || opcode == Y_TLTIU_OP - || opcode == Y_TNEI_OP - || (opcode_is_load_store (opcode) && expr->bits == 0)) - // Sign-extended immediate values: - ? ((value & 0xffff8000) != 0 && (value & 0xffff8000) != 0xffff8000) - // Not sign-extended: - : (value & 0xffff0000) != 0))) - { - // Non-immediate value - free_inst (inst); - i_type_inst_full_word (opcode, rt, rs, expr, 1, value); - return; - } - else - resolve_a_label (expr->symbol, inst); - } - else if (bare_machine || expr->bits != 0) - /* Don't know expression's value, but only needed upper/lower 16-bits - anyways. */ - record_inst_uses_symbol (inst, expr->symbol); - else - { - /* Don't know the expressions's value and want all of its bits, - so assume that it will not produce a small result and generate - sequence for 32 bit value. */ - free_inst (inst); - - i_type_inst_full_word (opcode, rt, rs, expr, 0, 0); - return; - } - - store_instruction (inst); -} - - -/* The immediate value for an instruction will (or may) not fit in 16 bits. - Build the value from its piece with separate instructions. */ - -static void -i_type_inst_full_word (int opcode, int rt, int rs, imm_expr *expr, - int value_known, int32 value) -{ - if (opcode_is_load_store (opcode)) - { - int32 offset; - - if (expr->symbol != NULL - && expr->symbol->gp_flag - && rs == 0 - && (int32)IMM_MIN <= (offset = expr->symbol->addr + expr->offset) - && offset <= (int32)IMM_MAX) - { - i_type_inst_free (opcode, rt, REG_GP, make_imm_expr (offset, NULL, false)); - } - else if (value_known) - { - int low, high; - - high = (value >> 16) & 0xffff; - low = value & 0xffff; - - if (!(high == 0 && !(low & 0x8000)) && - !(high == 0xffff && (low & 0x8000))) - { - /* Some of high 16 bits are non-zero */ - if (low & 0x8000) - { - /* Adjust high 16, since load sign-extends low 16*/ - high += 1; - } - - i_type_inst_free (Y_LUI_OP, 1, 0, const_imm_expr (high)); - if (rs != 0) /* Base register */ - { - r_type_inst (Y_ADDU_OP, 1, 1, rs); - } - i_type_inst_free (opcode, rt, 1, lower_bits_of_expr (const_imm_expr (low))); - } - else - { - /* Special case, sign-extension of low 16 bits sets high to 0xffff */ - i_type_inst_free (opcode, rt, rs, const_imm_expr (low)); - } - } - else - { - /* Use $at */ - /* Need to adjust if lower bits are negative */ - i_type_inst_free (Y_LUI_OP, 1, 0, upper_bits_of_expr (expr)); - if (rs != 0) /* Base register */ - { - r_type_inst (Y_ADDU_OP, 1, 1, rs); - } - i_type_inst_free (opcode, rt, 1, lower_bits_of_expr (expr)); - } - } - else if (opcode_is_branch (opcode)) - { - /* This only allows branches +/- 32K, which is not correct! */ - i_type_inst_free (opcode, rt, rs, lower_bits_of_expr (expr)); - } - else - /* Computation instruction */ - { - int offset; - - if (expr->symbol != NULL - && expr->symbol->gp_flag && rs == 0 - && (int32)IMM_MIN <= (offset = expr->symbol->addr + expr->offset) - && offset <= (int32)IMM_MAX) - { - i_type_inst_free ((opcode == Y_LUI_OP ? Y_ADDIU_OP : opcode), - rt, REG_GP, make_imm_expr (offset, NULL, false)); - } - else - { - /* Use $at */ - if ((opcode == Y_ORI_OP - || opcode == Y_ADDI_OP - || opcode == Y_ADDIU_OP - || opcode == Y_LUI_OP) - && rs == 0) - { - produce_immediate(expr, rt, value_known, value); - } - else - { - produce_immediate(expr, 1, value_known, value); - r_type_inst (imm_op_to_op (opcode), rt, rs, 1); - } - } - } -} - - -static void -produce_immediate (imm_expr *expr, int rt, int value_known, int32 value) -{ - if (value_known && (value & 0xffff) == 0) - { - i_type_inst_free (Y_LUI_OP, rt, 0, upper_bits_of_expr (expr)); - } - else if (value_known && (value & 0xffff0000) == 0) - { - i_type_inst_free (Y_ORI_OP, rt, 0, lower_bits_of_expr (expr)); - } - else - { - i_type_inst_free (Y_LUI_OP, 1, 0, upper_bits_of_expr (expr)); - i_type_inst_free (Y_ORI_OP, rt, 1, lower_bits_of_expr(expr)); - } -} - - -/* Return a jump-type instruction with the given OPCODE and TARGET - fields. NB, even the immediate value may not fit in the field, this - routine will not produce more than one instruction. */ - -void -j_type_inst (int opcode, imm_expr *target) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE(inst, opcode); - target->offset = 0; /* Not PC relative */ - target->pc_relative = false; - SET_EXPR (inst, copy_imm_expr (target)); - if (target->symbol == NULL || SYMBOL_IS_DEFINED (target->symbol)) - resolve_a_label (target->symbol, inst); - else - record_inst_uses_symbol (inst, target->symbol); - store_instruction (inst); -} - - -/* Return a register-type instruction with the given OPCODE, RD, RS, and RT - fields. */ - -static instruction * -make_r_type_inst (int opcode, int rd, int rs, int rt) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE(inst, opcode); - SET_RS(inst, rs); - SET_RT(inst, rt); - SET_RD(inst, rd); - SHAMT(inst) = 0; - return (inst); -} - - -/* Return a register-type instruction with the given OPCODE, RD, RS, and RT - fields. */ - -void -r_type_inst (int opcode, int rd, int rs, int rt) -{ - store_instruction (make_r_type_inst (opcode, rd, rs, rt)); -} - - -/* Return a register-type instruction with the given OPCODE, FD, FS, and FT - fields. */ - -void -r_co_type_inst (int opcode, int fd, int fs, int ft) -{ - instruction *inst = make_r_type_inst (opcode, fs, 0, ft); - SET_FD (inst, fd); - store_instruction (inst); -} - - -/* Return a register-shift instruction with the given OPCODE, RD, RT, and - SHAMT fields.*/ - -void -r_sh_type_inst (int opcode, int rd, int rt, int shamt) -{ - instruction *inst = make_r_type_inst (opcode, rd, 0, rt); - SET_SHAMT(inst, shamt & 0x1f); - store_instruction (inst); -} - - -/* Return a floating-point compare instruction with the given OPCODE, - FS, FT, and CC fields.*/ - -void -r_cond_type_inst (int opcode, int fs, int ft, int cc) -{ - instruction *inst = make_r_type_inst (opcode, fs, 0, ft); - SET_FD(inst, cc << 2); - switch (opcode) - { - case Y_C_EQ_D_OP: - case Y_C_EQ_S_OP: - { - SET_COND(inst, COND_EQ); - break; - } - - case Y_C_LE_D_OP: - case Y_C_LE_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_EQ); - break; - } - - case Y_C_LT_D_OP: - case Y_C_LT_S_OP: - { - SET_COND(inst, COND_IN | COND_LT); - break; - } - - case Y_C_NGE_D_OP: - case Y_C_NGE_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_UN); - break; - } - - case Y_C_NGLE_D_OP: - case Y_C_NGLE_S_OP: - { - SET_COND(inst, COND_IN | COND_UN); - break; - } - - case Y_C_NGL_D_OP: - case Y_C_NGL_S_OP: - { - SET_COND(inst, COND_IN | COND_EQ | COND_UN); - break; - } - - case Y_C_NGT_D_OP: - case Y_C_NGT_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_EQ | COND_UN); - break; - } - - case Y_C_OLT_D_OP: - case Y_C_OLT_S_OP: - { - SET_COND(inst, COND_LT); - break; - } - - case Y_C_OLE_D_OP: - case Y_C_OLE_S_OP: - { - SET_COND(inst, COND_LT | COND_EQ); - break; - } - - case Y_C_SEQ_D_OP: - case Y_C_SEQ_S_OP: - { - SET_COND(inst, COND_IN | COND_EQ); - break; - } - - case Y_C_SF_D_OP: - case Y_C_SF_S_OP: - { - SET_COND(inst, COND_IN); - break; - } - - case Y_C_F_D_OP: - case Y_C_F_S_OP: - { - SET_COND(inst, 0); - break; - } - - case Y_C_UEQ_D_OP: - case Y_C_UEQ_S_OP: - { - SET_COND(inst, COND_EQ | COND_UN); - break; - } - - case Y_C_ULT_D_OP: - case Y_C_ULT_S_OP: - { - SET_COND(inst, COND_LT | COND_UN); - break; - } - - case Y_C_ULE_D_OP: - case Y_C_ULE_S_OP: - { - SET_COND(inst, COND_LT | COND_EQ | COND_UN); - break; - } - - case Y_C_UN_D_OP: - case Y_C_UN_S_OP: - { - SET_COND(inst, COND_UN); - break; - } - } - store_instruction (inst); -} - - -/* Make and return a deep copy of INST. */ - -instruction * -copy_inst (instruction *inst) -{ - instruction *new_inst = (instruction *) xmalloc (sizeof (instruction)); - - *new_inst = *inst; - /*memcpy ((void*)new_inst, (void*)inst , sizeof (instruction));*/ - SET_EXPR (new_inst, copy_imm_expr (EXPR (inst))); - return (new_inst); -} - - -void -free_inst (instruction *inst) -{ - if (inst != break_inst) - /* Don't free the breakpoint insructions since we only have one. */ - { - if (EXPR (inst)) - free (EXPR (inst)); - free (inst); - } -} - - - -/* Maintain a table mapping from opcode to instruction name and - instruction type. - - Table must be sorted before first use since its entries are - alphabetical on name, not ordered by opcode. */ - - -/* Sort all instruction table before first use. */ - -void -initialize_inst_tables () -{ - sort_name_table (); - sort_i_opcode_table (); - sort_a_opcode_table (); -} - - -/* Map from opcode -> name/type. */ - -static name_val_val name_tbl [] = { -#undef OP -#define OP(NAME, OPCODE, TYPE, R_OPCODE) {NAME, OPCODE, TYPE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the opcode value). */ - -static void -sort_name_table () -{ - qsort (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - -/* Compare the VALUE1 field of two NAME_VAL_VAL entries in the format - required by qsort. */ - -static int -compare_pair_value (name_val_val *p1, name_val_val *p2) -{ - if (p1->value1 < p2->value1) - return (-1); - else if (p1->value1 > p2->value1) - return (1); - else - return (0); -} - - -/* Print the instruction stored at the memory ADDRESS. */ - -void -print_inst (mem_addr addr) -{ - char* inst_str = inst_to_string (addr); - write_output (message_out, "%s", inst_str); - free (inst_str); -} - - -char* -inst_to_string(mem_addr addr) -{ - str_stream ss; - instruction *inst; - - exception_occurred = 0; - inst = read_mem_inst (addr); - - if (exception_occurred) - { - error ("Can't print instruction not in text segment (0x%08x)\n", addr); - return ""; - } - - ss_init (&ss); - format_an_inst (&ss, inst, addr); - return ss_to_string (&ss); -} - - -void -format_an_inst (str_stream *ss, instruction *inst, mem_addr addr) -{ - name_val_val *entry; - int line_start = ss_length (ss); - - if (addr != 0 && inst_is_breakpoint (addr)) - { - delete_breakpoint (addr); - ss_printf (ss, "*"); - format_an_inst (ss, read_mem_inst (addr), addr); - add_breakpoint (addr); - return; - } - - ss_printf (ss, "[0x%08x]\t", addr); - if (inst == NULL) - { - ss_printf (ss, "\n"); - return; - } - - entry = map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - OPCODE (inst)); - if (entry == NULL) - { - ss_printf (ss, "\n", OPCODE (inst)); - return; - } - - ss_printf (ss, "0x%08x %s", (uint32)ENCODING (inst), entry->name); - switch (entry->value2) - { - case BC_TYPE_INST: - ss_printf (ss, "%d %d", CC (inst), IDISP (inst)); - break; - - case B1_TYPE_INST: - ss_printf (ss, " $%d %d", RS (inst), IDISP (inst)); - break; - - case I1s_TYPE_INST: - ss_printf (ss, " $%d, %d", RS (inst), IMM (inst)); - break; - - case I1t_TYPE_INST: - ss_printf (ss, " $%d, %d", RT (inst), IMM (inst)); - break; - - case I2_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RT (inst), RS (inst), IMM (inst)); - break; - - case B2_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RS (inst), RT (inst), IDISP (inst)); - break; - - case I2a_TYPE_INST: - ss_printf (ss, " $%d, %d($%d)", RT (inst), IMM (inst), BASE (inst)); - break; - - case R1s_TYPE_INST: - ss_printf (ss, " $%d", RS (inst)); - break; - - case R1d_TYPE_INST: - ss_printf (ss, " $%d", RD (inst)); - break; - - case R2td_TYPE_INST: - ss_printf (ss, " $%d, $%d", RT (inst), RD (inst)); - break; - - case R2st_TYPE_INST: - ss_printf (ss, " $%d, $%d", RS (inst), RT (inst)); - break; - - case R2ds_TYPE_INST: - ss_printf (ss, " $%d, $%d", RD (inst), RS (inst)); - break; - - case R2sh_TYPE_INST: - if (ENCODING (inst) == 0) - { - ss_erase (ss, 3); /* zap sll */ - ss_printf (ss, "nop"); - } - else - ss_printf (ss, " $%d, $%d, %d", RD (inst), RT (inst), SHAMT (inst)); - break; - - case R3_TYPE_INST: - ss_printf (ss, " $%d, $%d, $%d", RD (inst), RS (inst), RT (inst)); - break; - - case R3sh_TYPE_INST: - ss_printf (ss, " $%d, $%d, $%d", RD (inst), RT (inst), RS (inst)); - break; - - case FP_I2a_TYPE_INST: - ss_printf (ss, " $f%d, %d($%d)", FT (inst), IMM (inst), BASE (inst)); - break; - - case FP_R2ds_TYPE_INST: - ss_printf (ss, " $f%d, $f%d", FD (inst), FS (inst)); - break; - - case FP_R2ts_TYPE_INST: - ss_printf (ss, " $%d, $f%d", RT (inst), FS (inst)); - break; - - case FP_CMP_TYPE_INST: - if (FD (inst) == 0) - ss_printf (ss, " $f%d, $f%d", FS (inst), FT (inst)); - else - ss_printf (ss, " %d, $f%d, $f%d", FD (inst) >> 2, FS (inst), FT (inst)); - break; - - case FP_R3_TYPE_INST: - ss_printf (ss, " $f%d, $f%d, $f%d", FD (inst), FS (inst), FT (inst)); - break; - - case MOVC_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RD (inst), RS (inst), RT (inst) >> 2); - break; - - case FP_MOVC_TYPE_INST: - ss_printf (ss, " $f%d, $f%d, %d", FD (inst), FS (inst), CC (inst)); - break; - - case J_TYPE_INST: - ss_printf (ss, " 0x%08x", TARGET (inst) << 2); - break; - - case NOARG_TYPE_INST: - break; - - default: - fatal_error ("Unknown instruction type in print_inst\n"); - } - - if (EXPR (inst) != NULL && EXPR (inst)->symbol != NULL) - { - ss_printf (ss, " ["); - if (opcode_is_load_store (OPCODE (inst))) - format_imm_expr (ss, EXPR (inst), BASE (inst)); - else - format_imm_expr (ss, EXPR (inst), -1); - ss_printf (ss, "]"); - } - - if (SOURCE (inst) != NULL) - { - /* Comment is source line text of current line. */ - int gap_length = 57 - (ss_length (ss) - line_start); - for ( ; 0 < gap_length; gap_length -= 1) - { - ss_printf (ss, " "); - } - - ss_printf (ss, "; "); - ss_printf (ss, "%s", SOURCE (inst)); - } - - ss_printf (ss, "\n"); -} - - - -/* Return true if SPIM OPCODE (e.g. Y_...) represents a conditional - branch. */ - -bool -opcode_is_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1F_OP: - case Y_BC1FL_OP: - case Y_BC1T_OP: - case Y_BC1TL_OP: - case Y_BC2F_OP: - case Y_BC2FL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - case Y_BEQ_OP: - case Y_BEQL_OP: - case Y_BEQZ_POP: - case Y_BGE_POP: - case Y_BGEU_POP: - case Y_BGEZ_OP: - case Y_BGEZAL_OP: - case Y_BGEZALL_OP: - case Y_BGEZL_OP: - case Y_BGT_POP: - case Y_BGTU_POP: - case Y_BGTZ_OP: - case Y_BGTZL_OP: - case Y_BLE_POP: - case Y_BLEU_POP: - case Y_BLEZ_OP: - case Y_BLEZL_OP: - case Y_BLT_POP: - case Y_BLTU_POP: - case Y_BLTZ_OP: - case Y_BLTZAL_OP: - case Y_BLTZALL_OP: - case Y_BLTZL_OP: - case Y_BNE_OP: - case Y_BNEL_OP: - case Y_BNEZ_POP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE represents a nullified (e.g., Y_...L_OP) - conditional branch. */ - -bool -opcode_is_nullified_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1FL_OP: - case Y_BC1TL_OP: - case Y_BC2FL_OP: - case Y_BC2TL_OP: - case Y_BEQL_OP: - case Y_BGEZALL_OP: - case Y_BGEZL_OP: - case Y_BGTZL_OP: - case Y_BLEZL_OP: - case Y_BLTZALL_OP: - case Y_BLTZL_OP: - case Y_BNEL_OP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE (e.g. Y_...) represents a conditional - branch on a true condition. */ - -bool -opcode_is_true_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1T_OP: - case Y_BC1TL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE (e.g. Y_...) is a direct unconditional - branch (jump). */ - -bool -opcode_is_jump (int opcode) -{ - switch (opcode) - { - case Y_J_OP: - case Y_JAL_OP: - return true; - - default: - return false; - } -} - -/* Return true if SPIM OPCODE (e.g. Y_...) is a load or store. */ - -bool -opcode_is_load_store (int opcode) -{ - switch (opcode) - { - case Y_LB_OP: - case Y_LBU_OP: - case Y_LH_OP: - case Y_LHU_OP: - case Y_LL_OP: - case Y_LDC1_OP: - case Y_LDC2_OP: - case Y_LW_OP: - case Y_LWC1_OP: - case Y_LWC2_OP: - case Y_LWL_OP: - case Y_LWR_OP: - case Y_SB_OP: - case Y_SC_OP: - case Y_SH_OP: - case Y_SDC1_OP: - case Y_SDC2_OP: - case Y_SW_OP: - case Y_SWC1_OP: - case Y_SWC2_OP: - case Y_SWL_OP: - case Y_SWR_OP: - return true; - - default: - return false; - } -} - - -/* Return true if a breakpoint is set at ADDR. */ - -bool -inst_is_breakpoint (mem_addr addr) -{ - if (break_inst == NULL) - break_inst = make_r_type_inst (Y_BREAK_OP, 1, 0, 0); - - return (read_mem_inst (addr) == break_inst); -} - - -/* Set a breakpoint at ADDR and return the old instruction. If the - breakpoint cannot be set, return NULL. */ - -instruction * -set_breakpoint (mem_addr addr) -{ - instruction *old_inst; - - if (break_inst == NULL) - break_inst = make_r_type_inst (Y_BREAK_OP, 1, 0, 0); - - exception_occurred = 0; - old_inst = read_mem_inst (addr); - if (old_inst == break_inst) - return (NULL); - - set_mem_inst (addr, break_inst); - if (exception_occurred) - return (NULL); - else - return (old_inst); -} - - - -/* An immediate expression has the form: SYMBOL +/- IOFFSET, where either - part may be omitted. */ - -/* Make and return a new immediate expression */ - -imm_expr * -make_imm_expr (int offs, char *sym, bool is_pc_relative) -{ - imm_expr *expr = (imm_expr *) xmalloc (sizeof (imm_expr)); - - expr->offset = offs; - expr->bits = 0; - expr->pc_relative = is_pc_relative; - if (sym != NULL) - expr->symbol = lookup_label (sym); - else - expr->symbol = NULL; - return (expr); -} - - -/* Return a shallow copy of the EXPRESSION. */ - -imm_expr * -copy_imm_expr (imm_expr *old_expr) -{ - imm_expr *expr = (imm_expr *) xmalloc (sizeof (imm_expr)); - - *expr = *old_expr; - /*memcpy ((void*)expr, (void*)old_expr, sizeof (imm_expr));*/ - return (expr); -} - - -/* Return a shallow copy of an EXPRESSION that only uses the upper - sixteen bits of the expression's value. */ - -imm_expr * -upper_bits_of_expr (imm_expr *old_expr) -{ - imm_expr *expr = copy_imm_expr (old_expr); - - expr->bits = 1; - return (expr); -} - - -/* Return a shallow copy of the EXPRESSION that only uses the lower - sixteen bits of the expression's value. */ - -imm_expr * -lower_bits_of_expr (imm_expr *old_expr) -{ - imm_expr *expr = copy_imm_expr (old_expr); - - expr->bits = -1; - return (expr); -} - - -/* Return an instruction expression for a constant VALUE. */ - -imm_expr * -const_imm_expr (int32 value) -{ - return (make_imm_expr (value, NULL, false)); -} - - -/* Return a shallow copy of the EXPRESSION with the offset field - incremented by the given amount. */ - -imm_expr * -incr_expr_offset (imm_expr *expr, int32 value) -{ - imm_expr *new_expr = copy_imm_expr (expr); - - new_expr->offset += value; - return (new_expr); -} - - -/* Return the value of the EXPRESSION. */ - -int32 -eval_imm_expr (imm_expr *expr) -{ - int32 value; - - if (expr->symbol == NULL) - value = expr->offset; - else if (SYMBOL_IS_DEFINED (expr->symbol)) - { - value = expr->offset + expr->symbol->addr; - } - else - { - error ("Evaluated undefined symbol: %s\n", expr->symbol->name); - value = 0; - } - if (expr->bits > 0) - return ((value >> 16) & 0xffff); /* Use upper bits of result */ - else if (expr->bits < 0) - return (value & 0xffff); /* Use lower bits */ - else - return (value); -} - - -/* Print the EXPRESSION. */ - -static void -format_imm_expr (str_stream *ss, imm_expr *expr, int base_reg) -{ - if (expr->symbol != NULL) - { - ss_printf (ss, "%s", expr->symbol->name); - } - - if (expr->pc_relative) - ss_printf (ss, "-0x%08x", (unsigned int)-expr->offset); - else if (expr->offset < -10) - ss_printf (ss, "-%d (-0x%08x)", -expr->offset, (unsigned int)-expr->offset); - else if (expr->offset > 10) - ss_printf (ss, "+%d (0x%08x)", expr->offset, (unsigned int)expr->offset); - - if (base_reg != -1 && expr->symbol != NULL && - (expr->offset > 10 || expr->offset < -10)) - { - if (expr->offset == 0 && base_reg != 0) - ss_printf (ss, "+0"); - - if (expr->offset != 0 || base_reg != 0) - ss_printf (ss, "($%d)", base_reg); - } -} - - -/* Return true if the EXPRESSION is a constant 0. */ - -bool -is_zero_imm (imm_expr *expr) -{ - return (expr->offset == 0 && expr->symbol == NULL); -} - - - -/* Return an address expression of the form SYMBOL +/- IOFFSET (REGISTER). - Any of the three parts may be omitted. */ - -addr_expr * -make_addr_expr (int offs, char *sym, int reg_no) -{ - addr_expr *expr = (addr_expr *) xmalloc (sizeof (addr_expr)); - label *lab; - - if (reg_no == 0 && sym != NULL && (lab = lookup_label (sym))->gp_flag) - { - expr->reg_no = REG_GP; - expr->imm = make_imm_expr (offs + lab->addr - gp_midpoint, NULL, false); - } - else - { - expr->reg_no = (unsigned char)reg_no; - expr->imm = make_imm_expr (offs, (sym ? str_copy (sym) : sym), false); - } - return (expr); -} - - -imm_expr * -addr_expr_imm (addr_expr *expr) -{ - return (expr->imm); -} - - -int -addr_expr_reg (addr_expr *expr) -{ - return (expr->reg_no); -} - - - -/* Map between a SPIM instruction and the binary representation of the - instruction. */ - - -/* Maintain a table mapping from internal opcode (i_opcode) to actual - opcode (a_opcode). Table must be sorted before first use since its - entries are alphabetical on name, not ordered by opcode. */ - - -/* Map from internal opcode -> real opcode */ - -static name_val_val i_opcode_tbl [] = { -#undef OP -#define OP(NAME, I_OPCODE, TYPE, A_OPCODE) {NAME, I_OPCODE, (int)A_OPCODE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the interal opcode value). */ - -static void -sort_i_opcode_table () -{ - qsort (i_opcode_tbl, - sizeof (i_opcode_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - -#define REGS(R,O) (((R) & 0x1f) << O) - - -int32 -inst_encode (instruction *inst) -{ - int32 a_opcode = 0; - name_val_val *entry; - - if (inst == NULL) - return (0); - - entry = map_int_to_name_val_val (i_opcode_tbl, - sizeof (i_opcode_tbl) / sizeof (name_val_val), - OPCODE (inst)); - if (entry == NULL) - return 0; - - a_opcode = entry->value2; - entry = map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - OPCODE (inst)); - - switch (entry->value2) - { - case BC_TYPE_INST: - return (a_opcode - | REGS (CC (inst) << 2, 16) - | (IOFFSET (inst) & 0xffff)); - - case B1_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | (IOFFSET (inst) & 0xffff)); - - case I1s_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | (IMM (inst) & 0xffff)); - - case I1t_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | (IMM (inst) & 0xffff)); - - case I2_TYPE_INST: - case B2_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | (IMM (inst) & 0xffff)); - - case I2a_TYPE_INST: - return (a_opcode - | REGS (BASE (inst), 21) - | REGS (RT (inst), 16) - | (IOFFSET (inst) & 0xffff)); - - case R1s_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21)); - - case R1d_TYPE_INST: - return (a_opcode - | REGS (RD (inst), 11)); - - case R2td_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case R2st_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16)); - - case R2ds_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RD (inst), 11)); - - case R2sh_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (RD (inst), 11) - | REGS (SHAMT (inst), 6)); - - case R3_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case R3sh_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case FP_I2a_TYPE_INST: - return (a_opcode - | REGS (BASE (inst), 21) - | REGS (RT (inst), 16) - | (IOFFSET (inst) & 0xffff)); - - case FP_R2ds_TYPE_INST: - return (a_opcode - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case FP_R2ts_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (FS (inst), 11)); - - case FP_CMP_TYPE_INST: - return (a_opcode - | REGS (FT (inst), 16) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6) - | COND (inst)); - - case FP_R3_TYPE_INST: - return (a_opcode - | REGS (FT (inst), 16) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case MOVC_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case FP_MOVC_TYPE_INST: - return (a_opcode - | REGS (CC (inst), 18) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case J_TYPE_INST: - return (a_opcode - | TARGET (inst)); - - case NOARG_TYPE_INST: - return (a_opcode); - - default: - fatal_error ("Unknown instruction type in inst_encoding\n"); - return (0); /* Not reached */ - } -} - - -/* Maintain a table mapping from actual opcode to interal opcode. - Table must be sorted before first use since its entries are - alphabetical on name, not ordered by opcode. */ - - -/* Map from internal opcode -> real opcode */ - -static name_val_val a_opcode_tbl [] = { -#undef OP -#define OP(NAME, I_OPCODE, TYPE, A_OPCODE) {NAME, (int)A_OPCODE, (int)I_OPCODE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the interal opcode value). */ - -static void -sort_a_opcode_table () -{ - qsort (a_opcode_tbl, - sizeof (a_opcode_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - - -instruction * -inst_decode (int32 val) -{ - int32 a_opcode = val & 0xfc000000; - name_val_val *entry; - int32 i_opcode; - - /* Field classes: (opcode is continued in other part of instruction): */ - if (a_opcode == 0 || a_opcode == 0x70000000) /* SPECIAL or SPECIAL2 */ - a_opcode |= (val & 0x3f); - else if (a_opcode == 0x04000000) /* REGIMM */ - a_opcode |= (val & 0x001f0000); - else if (a_opcode == 0x40000000) /* COP0 */ - a_opcode |= (val & 0x03e00000) | (val & 0x1f); - else if (a_opcode == 0x44000000) /* COP1 */ - { - a_opcode |= (val & 0x03e00000); - if ((val & 0xff000000) == 0x45000000) - a_opcode |= (val & 0x00010000); /* BC1f/t */ - else - a_opcode |= (val & 0x3f); - } - else if (a_opcode == 0x48000000 /* COPz */ - || a_opcode == 0x4c000000) - a_opcode |= (val & 0x03e00000); - - - entry = map_int_to_name_val_val (a_opcode_tbl, - sizeof (a_opcode_tbl) / sizeof (name_val_val), - a_opcode); - if (entry == NULL) - return (mk_r_inst (val, 0, 0, 0, 0, 0)); /* Invalid inst */ - - i_opcode = entry->value2; - - switch (map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - i_opcode)->value2) - { - case BC_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case B1_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), 0, val & 0xffff)); - - case I1s_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), 0, val & 0xffff)); - - case I1t_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case I2_TYPE_INST: - case B2_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case I2a_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case R1s_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), 0, 0, 0)); - - case R1d_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, 0, BIN_RD(val), 0)); - - case R2td_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_RD(val), 0)); - - case R2st_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), 0, 0)); - - case R2ds_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), 0, BIN_RD(val), 0)); - - case R2sh_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_RD(val), BIN_SA(val))); - - case R3_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case R3sh_TYPE_INST: - return(mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case FP_I2a_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_BASE(val), BIN_FT(val), val & 0xffff)); - - case FP_R2ds_TYPE_INST: - return (mk_co_r_inst (val, i_opcode, BIN_FS(val), 0, BIN_FD(val))); - - case FP_R2ts_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_FS(val), 0)); - - case FP_CMP_TYPE_INST: - { - instruction *inst = mk_r_inst (val, i_opcode, BIN_FS(val), BIN_FT(val), BIN_FD(val), 0); - SET_COND (inst, val & 0xf); - return (inst); - } - - case FP_R3_TYPE_INST: - return (mk_co_r_inst (val, i_opcode, BIN_FS(val), BIN_FT(val), BIN_FD(val))); - - case MOVC_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case FP_MOVC_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_FS(val), BIN_RT(val), BIN_FD(val), 0)); - - case J_TYPE_INST: - return (mk_j_inst (val, i_opcode, val & 0x3ffffff)); - - - case NOARG_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, 0, 0, 0)); - - default: - return (mk_r_inst (val, 0, 0, 0, 0, 0)); /* Invalid inst */ - } -} - - -static instruction * -mk_r_inst (int32 val, int opcode, int rs, int rt, int rd, int shamt) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_RD (inst, rd); - SET_SHAMT (inst, shamt); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - -static instruction * -mk_co_r_inst (int32 val, int opcode, int fs, int ft, int fd) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_FS (inst, fs); - SET_FT (inst, ft); - SET_FD (inst, fd); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - -static instruction * -mk_i_inst (int32 val, int opcode, int rs, int rt, int offset) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_IOFFSET (inst, offset); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - -static instruction * -mk_j_inst (int32 val, int opcode, int target) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_TARGET (inst, target); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - - - -/* Code to test encode/decode of instructions. */ - -void -test_assembly (instruction *inst) -{ - instruction *new_inst = inst_decode (inst_encode (inst)); - - inst_cmp (inst, new_inst); - free_inst (new_inst); -} - - -static void -inst_cmp (instruction *inst1, instruction *inst2) -{ - static str_stream ss; - - ss_clear (&ss); - if (inst1->opcode != inst2->opcode - || inst1->encoding != inst2->encoding - || RS(inst1) != RS(inst2) - || RT(inst1) != RT(inst2) - || RD(inst1) != RD(inst2) - || SHAMT(inst1) != SHAMT(inst2)) - { - ss_printf (&ss, "=================== Not Equal ===================\n"); - format_an_inst (&ss, inst1, 0); - ss_printf (&ss, "===================\n"); - format_an_inst (&ss, inst2, 0); - ss_printf (&ss, "=================== Not Equal ===================\n"); - error(ss_to_string(&ss)); - } -} diff --git a/spim-qtbase/CPU/inst.h b/spim-qtbase/CPU/inst.h deleted file mode 100755 index 51733e9..0000000 --- a/spim-qtbase/CPU/inst.h +++ /dev/null @@ -1,280 +0,0 @@ -/* SPIM S20 MIPS simulator. - Description of a SPIM S20 instruction. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Represenation of the expression that produce a value for an instruction's - immediate field. Immediates have the form: label +/- offset. */ - -typedef struct immexpr -{ - int offset; /* Offset from symbol */ - struct lab *symbol; /* Symbolic label */ - short bits; /* > 0 => 31..16, < 0 => 15..0 */ - bool pc_relative; /* => offset from label in code */ -} imm_expr; - - -/* Representation of the expression that produce an address for an - instruction. Address have the form: label +/- offset (register). */ - -typedef struct addrexpr -{ - unsigned char reg_no; /* Register number */ - imm_expr *imm; /* The immediate part */ -} addr_expr; - - - -/* Representation of an instruction. Store the instruction fields in an - overlapping manner similar to the real encoding (but not identical, to - speed decoding in C code, as opposed to hardware).. */ - -typedef struct inst_s -{ - short opcode; - - union - { - /* R-type or I-type: */ - struct - { - unsigned char rs; - unsigned char rt; - - union - { - short imm; - - struct - { - unsigned char rd; - unsigned char shamt; - } r; - } r_i; - } r_i; - - /* J-type: */ - mem_addr target; - } r_t; - - int32 encoding; - imm_expr *expr; - char *source_line; -} instruction; - - -#define OPCODE(INST) (INST)->opcode -#define SET_OPCODE(INST, VAL) (INST)->opcode = (short)(VAL) - - -#define RS(INST) (INST)->r_t.r_i.rs -#define SET_RS(INST, VAL) (INST)->r_t.r_i.rs = (unsigned char)(VAL) - -#define RT(INST) (INST)->r_t.r_i.rt -#define SET_RT(INST, VAL) (INST)->r_t.r_i.rt = (unsigned char)(VAL) - -#define RD(INST) (INST)->r_t.r_i.r_i.r.rd -#define SET_RD(INST, VAL) (INST)->r_t.r_i.r_i.r.rd = (unsigned char)(VAL) - - -#define FS(INST) RD(INST) -#define SET_FS(INST, VAL) SET_RD(INST, VAL) - -#define FT(INST) RT(INST) -#define SET_FT(INST, VAL) SET_RT(INST, VAL) - -#define FD(INST) SHAMT(INST) -#define SET_FD(INST, VAL) SET_SHAMT(INST, VAL) - - -#define SHAMT(INST) (INST)->r_t.r_i.r_i.r.shamt -#define SET_SHAMT(INST, VAL) (INST)->r_t.r_i.r_i.r.shamt = (unsigned char)(VAL) - -#define IMM(INST) (INST)->r_t.r_i.r_i.imm -#define SET_IMM(INST, VAL) (INST)->r_t.r_i.r_i.imm = (short)(VAL) - - -#define BASE(INST) RS(INST) -#define SET_BASE(INST, VAL) SET_RS(INST, VAL) - -#define IOFFSET(INST) IMM(INST) -#define SET_IOFFSET(INST, VAL) SET_IMM(INST, VAL) -#define IDISP(INST) (SIGN_EX (IOFFSET (INST) << 2)) - - -#define COND(INST) RS(INST) -#define SET_COND(INST, VAL) SET_RS(INST, VAL) - -#define CC(INST) (RT(INST) >> 2) -#define ND(INST) ((RT(INST) & 0x2) >> 1) -#define TF(INST) (RT(INST) & 0x1) - -#define CCFP(INST) (FD(INST) >> 2) -#define NDFP(INST) ((FD(INST) & 0x2) >> 1) -#define TFF(INST) (FD(INST) & 0x1) - -#define TARGET(INST) (INST)->r_t.target -#define SET_TARGET(INST, VAL) (INST)->r_t.target = (mem_addr)(VAL) - -#define ENCODING(INST) (INST)->encoding -#define SET_ENCODING(INST, VAL) (INST)->encoding = (int32)(VAL) - -#define EXPR(INST) (INST)->expr -#define SET_EXPR(INST, VAL) (INST)->expr = (imm_expr*)(VAL) - -#define SOURCE(INST) (INST)->source_line -#define SET_SOURCE(INST, VAL) (INST)->source_line = (char *)(VAL) - - -#define COND_UN 0x1 -#define COND_EQ 0x2 -#define COND_LT 0x4 -#define COND_IN 0x8 - -/* Minimum and maximum values that fit in instruction's imm field */ -#define IMM_MIN 0xffff8000 -#define IMM_MAX 0x00007fff - -#define UIMM_MIN (unsigned)0 -#define UIMM_MAX ((unsigned)((1<<16)-1)) - - - -/* Raise an exception! */ - -extern int exception_occurred; - -#define RAISE_EXCEPTION(EXCODE, MISC) \ - { \ - raise_exception(EXCODE); \ - MISC; \ - } \ - - -#define RAISE_INTERRUPT(LEVEL) \ - { \ - /* Set IP (pending) bit for interrupt level. */ \ - CP0_Cause |= (1 << ((LEVEL) + 8)); \ - } \ - -#define CLEAR_INTERRUPT(LEVEL) \ - { \ - /* Clear IP (pending) bit for interrupt level. */ \ - CP0_Cause &= ~(1 << ((LEVEL) + 8)); \ - } \ - -/* Recognized exceptions: */ - -#define ExcCode_Int 0 /* Interrupt */ -#define ExcCode_Mod 1 /* TLB modification (not implemented) */ -#define ExcCode_TLBL 2 /* TLB exception (not implemented) */ -#define ExcCode_TLBS 3 /* TLB exception (not implemented) */ -#define ExcCode_AdEL 4 /* Address error (load/fetch) */ -#define ExcCode_AdES 5 /* Address error (store) */ -#define ExcCode_IBE 6 /* Bus error, instruction fetch */ -#define ExcCode_DBE 7 /* Bus error, data reference */ -#define ExcCode_Sys 8 /* Syscall exception */ -#define ExcCode_Bp 9 /* Breakpoint exception */ -#define ExcCode_RI 10 /* Reserve instruction */ -#define ExcCode_CpU 11 /* Coprocessor unusable */ -#define ExcCode_Ov 12 /* Arithmetic overflow */ -#define ExcCode_Tr 13 /* Trap */ -#define ExcCode_FPE 15 /* Floating point */ -#define ExcCode_C2E 18 /* Coprocessor 2 (not impelemented) */ -#define ExcCode_MDMX 22 /* MDMX unusable (not implemented) */ -#define ExcCode_WATCH 23 /* Reference to Watch (not impelemented) */ -#define ExcCode_MCheck 24 /* Machine check (not implemented) */ -#define ExcCode_CacheErr 30 /* Cache error (not impelemented) */ - - - -/* Fields in binary representation of instructions: */ - -#define BIN_REG(V,O) (((V) >> O) & 0x1f) -#define BIN_RS(V) (BIN_REG(V, 21)) -#define BIN_RT(V) (BIN_REG(V, 16)) -#define BIN_RD(V) (BIN_REG(V, 11)) -#define BIN_SA(V) (BIN_REG(V, 6)) - -#define BIN_BASE(V) (BIN_REG(V, 21)) -#define BIN_FT(V) (BIN_REG(V, 16)) -#define BIN_FS(V) (BIN_REG(V, 11)) -#define BIN_FD(V) (BIN_REG(V, 6)) - - - -/* Exported functions: */ - -imm_expr *addr_expr_imm (addr_expr *expr); -int addr_expr_reg (addr_expr *expr); -void align_text (int alignment); -imm_expr *const_imm_expr (int32 value); -imm_expr *copy_imm_expr (imm_expr *old_expr); -instruction *copy_inst (instruction *inst); -mem_addr current_text_pc (); -void enable_text_alignment (); -int32 eval_imm_expr (imm_expr *expr); -void format_an_inst (str_stream *ss, instruction *inst, mem_addr addr); -void free_inst (instruction *inst); -void i_type_inst (int opcode, int rt, int rs, imm_expr *expr); -void i_type_inst_free (int opcode, int rt, int rs, imm_expr *expr); -void increment_text_pc (int delta); -imm_expr *incr_expr_offset (imm_expr *expr, int32 value); -void initialize_inst_tables (); -instruction *inst_decode (int32 value); -int32 inst_encode (instruction *inst); -bool inst_is_breakpoint (mem_addr addr); -void j_type_inst (int opcode, imm_expr *target); -void k_text_begins_at_point (mem_addr addr); -imm_expr *lower_bits_of_expr (imm_expr *old_expr); -addr_expr *make_addr_expr (int offs, char *sym, int reg_no); -imm_expr *make_imm_expr (int offs, char *sym, bool is_pc_relative); -bool opcode_is_branch (int opcode); -bool opcode_is_nullified_branch (int opcode); -bool opcode_is_true_branch (int opcode); -bool opcode_is_jump (int opcode); -bool opcode_is_load_store (int opcode); -void print_inst (mem_addr addr); -char* inst_to_string (mem_addr addr); -void r_co_type_inst (int opcode, int fd, int fs, int ft); -void r_cond_type_inst (int opcode, int fs, int ft, int cc); -void r_sh_type_inst (int opcode, int rd, int rt, int shamt); -void r_type_inst (int opcode, int rd, int rs, int rt); -void raise_exception(int excode); -instruction *set_breakpoint (mem_addr addr); -void set_text_alignment (int alignment); -void store_instruction (instruction *inst); -void test_assembly (instruction *inst); -void text_begins_at_point (mem_addr addr); -imm_expr *upper_bits_of_expr (imm_expr *old_expr); -void user_kernel_text_segment (bool to_kernel); -bool is_zero_imm (imm_expr *expr); diff --git a/spim-qtbase/CPU/mem.cpp b/spim-qtbase/CPU/mem.cpp deleted file mode 100755 index 0d17111..0000000 --- a/spim-qtbase/CPU/mem.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to create, maintain and access memory. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" - -/* Exported Variables: */ - -reg_word R[R_LENGTH]; -reg_word HI, LO; -int HI_present, LO_present; -mem_addr PC, nPC; -double *FPR; /* Dynamically allocate so overlay */ -float *FGR; /* is possible */ -int *FWR; /* is possible */ -reg_word CCR[4][32], CPR[4][32]; - -instruction **text_seg; -bool text_modified; /* => text segment was written */ -mem_addr text_top; -mem_word *data_seg; -bool data_modified; /* => a data segment was written */ -short *data_seg_h; /* Points to same vector as DATA_SEG */ -BYTE_TYPE *data_seg_b; /* Ditto */ -mem_addr data_top; -mem_addr gp_midpoint; /* Middle of $gp area */ -mem_word *stack_seg; -short *stack_seg_h; /* Points to same vector as STACK_SEG */ -BYTE_TYPE *stack_seg_b; /* Ditto */ -mem_addr stack_bot; -instruction **k_text_seg; -mem_addr k_text_top; -mem_word *k_data_seg; -short *k_data_seg_h; -BYTE_TYPE *k_data_seg_b; -mem_addr k_data_top; - - -/* Local functions: */ - -static mem_word bad_mem_read (mem_addr addr, int mask); -static void bad_mem_write (mem_addr addr, mem_word value, int mask); -static instruction *bad_text_read (mem_addr addr); -static void bad_text_write (mem_addr addr, instruction *inst); -static void free_instructions (instruction **inst, int n); -static mem_word read_memory_mapped_IO (mem_addr addr); -static void write_memory_mapped_IO (mem_addr addr, mem_word value); - - -/* Local variables: */ - -static int32 data_size_limit, stack_size_limit, k_data_size_limit; - - - -/* Memory is allocated in five chunks: - text, data, stack, kernel text, and kernel data. - - The arrays are independent and have different semantics. - - text is allocated from 0x400000 up and only contains INSTRUCTIONs. - It does not expand. - - data is allocated from 0x10000000 up. It can be extended by the - SBRK system call. Programs can only read and write this segment. - - stack grows from 0x7fffefff down. It is automatically extended. - Programs can only read and write this segment. - - k_text is like text, except its is allocated from 0x80000000 up. - - k_data is like data, but is allocated from 0x90000000 up. - - Both kernel text and kernel data can only be accessed in kernel mode. -*/ - -/* The text segments contain pointers to instructions, not actual - instructions, so they must be allocated large enough to hold as many - pointers as there would be instructions (the two differ on machines in - which pointers are not 32 bits long). The following calculations round - up in case size is not a multiple of BYTES_PER_WORD. */ - -#define BYTES_TO_INST(N) (((N) + BYTES_PER_WORD - 1) / BYTES_PER_WORD * sizeof(instruction*)) - - -void -make_memory (int text_size, int data_size, int data_limit, - int stack_size, int stack_limit, int k_text_size, - int k_data_size, int k_data_limit) -{ - if (data_size <= 65536) - data_size = 65536; - data_size = ROUND_UP(data_size, BYTES_PER_WORD); /* Keep word aligned */ - - if (text_seg == NULL) - text_seg = (instruction **) xmalloc (BYTES_TO_INST(text_size)); - else - { - free_instructions (text_seg, (text_top - TEXT_BOT) / BYTES_PER_WORD); - text_seg = (instruction **) realloc (text_seg, BYTES_TO_INST(text_size)); - } - memclr (text_seg, BYTES_TO_INST(text_size)); - text_top = TEXT_BOT + text_size; - - data_size = ROUND_UP(data_size, BYTES_PER_WORD); /* Keep word aligned */ - if (data_seg == NULL) - data_seg = (mem_word *) xmalloc (data_size); - else - data_seg = (mem_word *) realloc (data_seg, data_size); - memclr (data_seg, data_size); - data_seg_b = (BYTE_TYPE *) data_seg; - data_seg_h = (short *) data_seg; - data_top = DATA_BOT + data_size; - data_size_limit = data_limit; - - stack_size = ROUND_UP(stack_size, BYTES_PER_WORD); /* Keep word aligned */ - if (stack_seg == NULL) - stack_seg = (mem_word *) xmalloc (stack_size); - else - stack_seg = (mem_word *) realloc (stack_seg, stack_size); - memclr (stack_seg, stack_size); - stack_seg_b = (BYTE_TYPE *) stack_seg; - stack_seg_h = (short *) stack_seg; - stack_bot = STACK_TOP - stack_size; - stack_size_limit = stack_limit; - - if (k_text_seg == NULL) - k_text_seg = (instruction **) xmalloc (BYTES_TO_INST(k_text_size)); - else - { - free_instructions (k_text_seg, - (k_text_top - K_TEXT_BOT) / BYTES_PER_WORD); - k_text_seg = (instruction **) realloc(k_text_seg, - BYTES_TO_INST(k_text_size)); - } - memclr (k_text_seg, BYTES_TO_INST(k_text_size)); - k_text_top = K_TEXT_BOT + k_text_size; - - k_data_size = ROUND_UP(k_data_size, BYTES_PER_WORD); /* Keep word aligned */ - if (k_data_seg == NULL) - k_data_seg = (mem_word *) xmalloc (k_data_size); - else - k_data_seg = (mem_word *) realloc (k_data_seg, k_data_size); - memclr (k_data_seg, k_data_size); - k_data_seg_b = (BYTE_TYPE *) k_data_seg; - k_data_seg_h = (short *) k_data_seg; - k_data_top = K_DATA_BOT + k_data_size; - k_data_size_limit = k_data_limit; - - text_modified = true; - data_modified = true; -} - - -/* Free the storage used by the old instructions in memory. */ - -static void -free_instructions (instruction **inst, int n) -{ - for ( ; n > 0; n --, inst ++) - if (*inst) - free_inst (*inst); -} - - -/* Expand the data segment by adding N bytes. */ - -void -expand_data (int addl_bytes) -{ - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = data_top - DATA_BOT; - int new_size = old_size + delta; - BYTE_TYPE *p; - - if ((addl_bytes < 0) || (new_size > data_size_limit)) - { - error ("Can't expand data segment by %d bytes to %d bytes\n", - addl_bytes, new_size); - run_error ("Use -ldata # with # > %d\n", new_size); - } - data_seg = (mem_word *) realloc (data_seg, new_size); - if (data_seg == NULL) - fatal_error ("realloc failed in expand_data\n"); - - data_seg_b = (BYTE_TYPE *) data_seg; - data_seg_h = (short *) data_seg; - data_top += delta; - - /* Zero new memory */ - for (p = data_seg_b + old_size; p < data_seg_b + new_size; ) - *p ++ = 0; -} - - -/* Expand the stack segment by adding N bytes. Can't use REALLOC - since it copies from bottom of memory blocks and stack grows down from - top of its block. */ - -void -expand_stack (int addl_bytes) -{ - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = STACK_TOP - stack_bot; - int new_size = old_size + MAX (delta, old_size); - mem_word *new_seg; - mem_word *po, *pn; - - if ((addl_bytes < 0) || (new_size > stack_size_limit)) - { - run_error ("Can't expand stack segment by %d bytes to %d bytes.\nUse -lstack # with # > %d\n", - addl_bytes, new_size, new_size); - } - - new_seg = (mem_word *) xmalloc (new_size); - memset(new_seg, 0, new_size); - - po = stack_seg + (old_size / BYTES_PER_WORD - 1); - pn = new_seg + (new_size / BYTES_PER_WORD - 1); - for ( ; po >= stack_seg ; ) *pn -- = *po --; - - free (stack_seg); - stack_seg = new_seg; - stack_seg_b = (BYTE_TYPE *) stack_seg; - stack_seg_h = (short *) stack_seg; - stack_bot -= (new_size - old_size); -} - - -/* Expand the kernel data segment by adding N bytes. */ - -void -expand_k_data (int addl_bytes) -{ - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = k_data_top - K_DATA_BOT; - int new_size = old_size + delta; - BYTE_TYPE *p; - - if ((addl_bytes < 0) || (new_size > k_data_size_limit)) - { - run_error ("Can't expand kernel data segment by %d bytes to %d bytes.\nUse -lkdata # with # > %d\n", - addl_bytes, new_size, new_size); - } - k_data_seg = (mem_word *) realloc (k_data_seg, new_size); - if (k_data_seg == NULL) - fatal_error ("realloc failed in expand_k_data\n"); - - k_data_seg_b = (BYTE_TYPE *) k_data_seg; - k_data_seg_h = (short *) k_data_seg; - k_data_top += delta; - - /* Zero new memory */ - for (p = k_data_seg_b + old_size / BYTES_PER_WORD; - p < k_data_seg_b + new_size / BYTES_PER_WORD; ) - *p ++ = 0; -} - - - -/* Access memory */ - -void* -mem_reference(mem_addr addr) -{ - if ((addr >= TEXT_BOT) && (addr < text_top)) - return addr - TEXT_BOT + (char*) text_seg; - else if ((addr >= DATA_BOT) && (addr < data_top)) - return addr - DATA_BOT + (char*) data_seg; - else if ((addr >= stack_bot) && (addr < STACK_TOP)) - return addr - stack_bot + (char*) stack_seg; - else if ((addr >= K_TEXT_BOT) && (addr < k_text_top)) - return addr - K_TEXT_BOT + (char*) k_text_seg; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top)) - return addr - K_DATA_BOT + (char*) k_data_seg; - else - { - run_error ("Memory address out of bounds\n"); - return NULL; - } -} - - -instruction* -read_mem_inst(mem_addr addr) -{ - if ((addr >= TEXT_BOT) && (addr < text_top) && !(addr & 0x3)) - return text_seg [(addr - TEXT_BOT) >> 2]; - else if ((addr >= K_TEXT_BOT) && (addr < k_text_top) && !(addr & 0x3)) - return k_text_seg [(addr - K_TEXT_BOT) >> 2]; - else - return bad_text_read (addr); -} - - -reg_word -read_mem_byte(mem_addr addr) -{ - if ((addr >= DATA_BOT) && (addr < data_top)) - return data_seg_b [addr - DATA_BOT]; - else if ((addr >= stack_bot) && (addr < STACK_TOP)) - return stack_seg_b [addr - stack_bot]; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top)) - return k_data_seg_b [addr - K_DATA_BOT]; - else - return bad_mem_read (addr, 0); -} - - -reg_word -read_mem_half(mem_addr addr) -{ - if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x1)) - return data_seg_h [(addr - DATA_BOT) >> 1]; - else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x1)) - return stack_seg_h [(addr - stack_bot) >> 1]; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x1)) - return k_data_seg_h [(addr - K_DATA_BOT) >> 1]; - else - return bad_mem_read (addr, 0x1); -} - - -reg_word -read_mem_word(mem_addr addr) -{ - if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x3)) - return data_seg [(addr - DATA_BOT) >> 2]; - else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x3)) - return stack_seg [(addr - stack_bot) >> 2]; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x3)) - return k_data_seg [(addr - K_DATA_BOT) >> 2]; - else - return bad_mem_read (addr, 0x3); -} - - -void -set_mem_inst(mem_addr addr, instruction* inst) -{ - text_modified = true; - if ((addr >= TEXT_BOT) && (addr < text_top) && !(addr & 0x3)) - text_seg [(addr - TEXT_BOT) >> 2] = inst; - else if ((addr >= K_TEXT_BOT) && (addr < k_text_top) && !(addr & 0x3)) - k_text_seg [(addr - K_TEXT_BOT) >> 2] = inst; - else - bad_text_write (addr, inst); -} - - -void -set_mem_byte(mem_addr addr, reg_word value) -{ - data_modified = true; - if ((addr >= DATA_BOT) && (addr < data_top)) - data_seg_b [addr - DATA_BOT] = (BYTE_TYPE) value; - else if ((addr >= stack_bot) && (addr < STACK_TOP)) - stack_seg_b [addr - stack_bot] = (BYTE_TYPE) value; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top)) - k_data_seg_b [addr - K_DATA_BOT] = (BYTE_TYPE) value; - else - bad_mem_write (addr, value, 0); -} - - -void -set_mem_half(mem_addr addr, reg_word value) -{ - data_modified = true; - if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x1)) - data_seg_h [(addr - DATA_BOT) >> 1] = (short) value; - else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x1)) - stack_seg_h [(addr - stack_bot) >> 1] = (short) value; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x1)) - k_data_seg_h [(addr - K_DATA_BOT) >> 1] = (short) value; - else - bad_mem_write (addr, value, 0x1); -} - - -void -set_mem_word(mem_addr addr, reg_word value) -{ - data_modified = true; - if ((addr >= DATA_BOT) && (addr < data_top) && !(addr & 0x3)) - data_seg [(addr - DATA_BOT) >> 2] = (mem_word) value; - else if ((addr >= stack_bot) && (addr < STACK_TOP) && !(addr & 0x3)) - stack_seg [(addr - stack_bot) >> 2] = (mem_word) value; - else if ((addr >= K_DATA_BOT) && (addr < k_data_top) && !(addr & 0x3)) - k_data_seg [(addr - K_DATA_BOT) >> 2] = (mem_word) value; - else - bad_mem_write (addr, value, 0x3); -} - - -/* Handle the infrequent and erroneous cases in memory accesses. */ - -static instruction * -bad_text_read (mem_addr addr) -{ - RAISE_EXCEPTION (ExcCode_IBE, CP0_BadVAddr = addr); - return (inst_decode (0)); -} - - -static void -bad_text_write (mem_addr addr, instruction *inst) -{ - RAISE_EXCEPTION (ExcCode_IBE, CP0_BadVAddr = addr); - set_mem_word (addr, ENCODING (inst)); -} - - -static mem_word -bad_mem_read (mem_addr addr, int mask) -{ - mem_word tmp; - - if ((addr & mask) != 0) - RAISE_EXCEPTION (ExcCode_AdEL, CP0_BadVAddr = addr) - else if (addr >= TEXT_BOT && addr < text_top) - switch (mask) - { - case 0x0: - tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = (unsigned)tmp >> (8 * (3 - (addr & 0x3))); -#else - tmp = (unsigned)tmp >> (8 * (addr & 0x3)); -#endif - return (0xff & tmp); - - case 0x1: - tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = (unsigned)tmp >> (8 * (2 - (addr & 0x2))); -#else - tmp = (unsigned)tmp >> (8 * (addr & 0x2)); -#endif - return (0xffff & tmp); - - case 0x3: - { - instruction *inst = text_seg [(addr - TEXT_BOT) >> 2]; - if (inst == NULL) - return 0; - else - return (ENCODING (inst)); - } - - default: - run_error ("Bad mask (0x%x) in bad_mem_read\n", mask); - } - else if (addr > data_top - && addr < stack_bot - /* If more than 16 MB below stack, probably is bad data ref */ - && addr > stack_bot - 16*K*K) - { - /* Grow stack segment */ - expand_stack (stack_bot - addr + 4); - return (0); - } - else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP) - return (read_memory_mapped_IO (addr)); - else - /* Address out of range */ - RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr) - return (0); -} - - -static void -bad_mem_write (mem_addr addr, mem_word value, int mask) -{ - mem_word tmp; - - if ((addr & mask) != 0) - /* Unaligned address fault */ - RAISE_EXCEPTION (ExcCode_AdES, CP0_BadVAddr = addr) - else if (addr >= TEXT_BOT && addr < text_top) - { - switch (mask) - { - case 0x0: - tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = ((tmp & ~(0xff << (8 * (3 - (addr & 0x3))))) - | (value & 0xff) << (8 * (3 - (addr & 0x3)))); -#else - tmp = ((tmp & ~(0xff << (8 * (addr & 0x3)))) - | (value & 0xff) << (8 * (addr & 0x3))); -#endif - break; - - case 0x1: - tmp = ENCODING (text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = ((tmp & ~(0xffff << (8 * (2 - (addr & 0x2))))) - | (value & 0xffff) << (8 * (2 - (addr & 0x2)))); -#else - tmp = ((tmp & ~(0xffff << (8 * (addr & 0x2)))) - | (value & 0xffff) << (8 * (addr & 0x2))); -#endif - break; - - case 0x3: - tmp = value; - break; - - default: - tmp = 0; - run_error ("Bad mask (0x%x) in bad_mem_read\n", mask); - } - - if (text_seg [(addr - TEXT_BOT) >> 2] != NULL) - { - free_inst (text_seg[(addr - TEXT_BOT) >> 2]); - } - text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp); - - text_modified = true; - } - else if (addr > data_top - && addr < stack_bot - /* If more than 16 MB below stack, probably is bad data ref */ - && addr > stack_bot - 16*K*K) - { - /* Grow stack segment */ - expand_stack (stack_bot - addr + 4); - if (addr >= stack_bot) - { - if (mask == 0) - stack_seg_b [addr - stack_bot] = (char)value; - else if (mask == 1) - stack_seg_h [(addr - stack_bot) >> 1] = (short)value; - else - stack_seg [(addr - stack_bot) >> 2] = value; - } - else - RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr) - - data_modified = true; - } - else if (MM_IO_BOT <= addr && addr <= MM_IO_TOP) - write_memory_mapped_IO (addr, value); - else - /* Address out of range */ - RAISE_EXCEPTION (ExcCode_DBE, CP0_BadVAddr = addr) -} - - - -/* Memory-mapped IO routines. */ - -static int recv_control = 0; /* No input */ -static int recv_buffer; -static int recv_buffer_full_timer = 0; - -static int trans_control = TRANS_READY; /* Ready to write */ -static int trans_buffer; -static int trans_buffer_full_timer = 0; - - -/* Check if input is available and output is possible. If so, update the - memory-mapped control registers and buffers. */ - -void -check_memory_mapped_IO () -{ - if (recv_buffer_full_timer > 0) - { - /* Do not check for more input until this interval expires. */ - recv_buffer_full_timer -= 1; - } - else if (console_input_available ()) - { - /* Read new char into the buffer and raise an interrupt, if interrupts - are enabled for device. */ - /* assert(recv_buffer_full_timer == 0); */ - recv_buffer = get_console_char (); - recv_control |= RECV_READY; - recv_buffer_full_timer = RECV_INTERVAL; - if (recv_control & RECV_INT_ENABLE) - { - RAISE_INTERRUPT (RECV_INT_LEVEL); - } - } - - if (trans_buffer_full_timer > 0) - { - /* Do not allow output until this interval expires. */ - trans_buffer_full_timer -= 1; - } - else if (!(trans_control & TRANS_READY)) - { - /* Done writing: empty the buffer and raise an interrupt, if interrupts - are enabled for device. */ - /* assert(trans_buffer_full_timer == 0); */ - trans_control |= TRANS_READY; - if (trans_control & TRANS_INT_ENABLE) - { - RAISE_INTERRUPT (TRANS_INT_LEVEL); - } - } -} - - -/* Invoked on a write to the memory-mapped IO area. */ - -static void -write_memory_mapped_IO (mem_addr addr, mem_word value) -{ - switch (addr) - { - case TRANS_CTRL_ADDR: - /* Program can only set the interrupt enable, not ready, bit. */ - if ((value & TRANS_INT_ENABLE) != 0) - { - /* Enable interrupts: */ - trans_control |= TRANS_INT_ENABLE; - if (trans_control & TRANS_READY) - { - /* Raise interrupt on enabling a ready transmitter */ - RAISE_INTERRUPT (TRANS_INT_LEVEL); - } - } - else - { - /* Disable interrupts: */ - trans_control &= ~TRANS_INT_ENABLE; - CLEAR_INTERRUPT (TRANS_INT_LEVEL); /* Clear IP bit in Cause */ - } - break; - - case TRANS_BUFFER_ADDR: - /* Ignore write if device is not ready. */ - if ((trans_control & TRANS_READY) != 0) - { - /* Write char: */ - trans_buffer = value & 0xff; - put_console_char ((char)trans_buffer); - /* Device is busy for a while: */ - trans_control &= ~TRANS_READY; - trans_buffer_full_timer = TRANS_LATENCY; - CLEAR_INTERRUPT (TRANS_INT_LEVEL); /* Clear IP bit in Cause */ - } - break; - - case RECV_CTRL_ADDR: - /* Program can only set the interrupt enable, not ready, bit. */ - if ((value & RECV_INT_ENABLE) != 0) - { - /* Enable interrupts: */ - recv_control |= RECV_INT_ENABLE; - if (recv_control & RECV_READY) - { - /* Raise interrupt on enabling a ready receiver */ - RAISE_INTERRUPT (RECV_INT_LEVEL); - } - } - else - { - /* Disable interrupts: */ - recv_control &= ~RECV_INT_ENABLE; - CLEAR_INTERRUPT (RECV_INT_LEVEL); /* Clear IP bit in Cause */ - } - break; - - case RECV_BUFFER_ADDR: - /* Nop: program can't change buffer. */ - break; - - default: - run_error ("Write to unused memory-mapped IO address (0x%x)\n", addr); - } -} - - -/* Invoked on a read in the memory-mapped IO area. */ - -static mem_word -read_memory_mapped_IO (mem_addr addr) -{ - switch (addr) - { - case TRANS_CTRL_ADDR: - return (trans_control); - - case TRANS_BUFFER_ADDR: - return (trans_buffer & 0xff); - - case RECV_CTRL_ADDR: - return (recv_control); - - case RECV_BUFFER_ADDR: - recv_control &= ~RECV_READY; /* Buffer now empty */ - recv_buffer_full_timer = 0; - CLEAR_INTERRUPT (RECV_INT_LEVEL); /* Clear IP bit in Cause */ - return (recv_buffer & 0xff); - - default: - run_error ("Read from unused memory-mapped IO address (0x%x)\n", addr); - return (0); - } -} - - - -/* Misc. routines */ - -void -print_mem (mem_addr addr) -{ - mem_word value; - - if ((addr & 0x3) != 0) - addr &= ~0x3; /* Address must be word-aligned */ - - if (TEXT_BOT <= addr && addr < text_top) - print_inst (addr); - else if (DATA_BOT <= addr && addr < data_top) - { - value = read_mem_word (addr); - write_output (message_out, "Data seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else if (stack_bot <= addr && addr < STACK_TOP) - { - value = read_mem_word (addr); - write_output (message_out, "Stack seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else if (K_TEXT_BOT <= addr && addr < k_text_top) - print_inst (addr); - else if (K_DATA_BOT <= addr && addr < k_data_top) - { - value = read_mem_word (addr); - write_output (message_out, - "Kernel Data seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else - error ("Address 0x%08x (%d) to print_mem is out of bounds\n", addr, addr); -} diff --git a/spim-qtbase/CPU/mem.h b/spim-qtbase/CPU/mem.h deleted file mode 100755 index 018cbd6..0000000 --- a/spim-qtbase/CPU/mem.h +++ /dev/null @@ -1,161 +0,0 @@ -/* SPIM S20 MIPS simulator. - Macros for accessing memory. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* A note on directions: "Bottom" of memory is the direction of - decreasing addresses. "Top" is the direction of increasing addresses.*/ - - -/* Type of contents of a memory word. */ - -typedef int32 /*@alt unsigned int @*/ mem_word; - - -/* The text segment and boundaries. */ - -extern instruction **text_seg; - -extern bool text_modified; /* => text segment was written */ - -#define TEXT_BOT ((mem_addr) 0x400000) - -extern mem_addr text_top; - - -/* Amount to grow text segment when we run out of space for instructions. */ - -#define TEXT_CHUNK_SIZE 4096 - - -/* The data segment and boundaries. */ - -extern mem_word *data_seg; - -extern bool data_modified; /* => a data segment was written */ - -extern short *data_seg_h; /* Points to same vector as DATA_SEG */ - -#define BYTE_TYPE signed char - - -extern BYTE_TYPE *data_seg_b; /* Ditto */ - -#define DATA_BOT ((mem_addr) 0x10000000) - -extern mem_addr data_top; - -extern mem_addr gp_midpoint; /* Middle of $gp area */ - - -/* The stack segment and boundaries. */ - -extern mem_word *stack_seg; - -extern short *stack_seg_h; /* Points to same vector as STACK_SEG */ - -extern BYTE_TYPE *stack_seg_b; /* Ditto */ - -extern mem_addr stack_bot; - -/* Exclusive, but include 4K at top of stack. */ - -#define STACK_TOP ((mem_addr) 0x80000000) - - -/* The kernel text segment and boundaries. */ - -extern instruction **k_text_seg; - -#define K_TEXT_BOT ((mem_addr) 0x80000000) - -extern mem_addr k_text_top; - - -/* Kernel data segment and boundaries. */ - -extern mem_word *k_data_seg; - -extern short *k_data_seg_h; - -extern BYTE_TYPE *k_data_seg_b; - -#define K_DATA_BOT ((mem_addr) 0x90000000) - -extern mem_addr k_data_top; - - -/* Memory-mapped IO area: */ -#define MM_IO_BOT ((mem_addr) 0xffff0000) -#define MM_IO_TOP ((mem_addr) 0xffffffff) - - -/* Read from console: */ -#define RECV_CTRL_ADDR ((mem_addr) 0xffff0000) -#define RECV_BUFFER_ADDR ((mem_addr) 0xffff0004) - -#define RECV_READY 0x1 -#define RECV_INT_ENABLE 0x2 - -#define RECV_INT_LEVEL 3 /* HW Interrupt 1 */ - - -/* Write to console: */ -#define TRANS_CTRL_ADDR ((mem_addr) 0xffff0008) -#define TRANS_BUFFER_ADDR ((mem_addr) 0xffff000c) - -#define TRANS_READY 0x1 -#define TRANS_INT_ENABLE 0x2 - -#define TRANS_INT_LEVEL 2 /* HW Interrupt 0 */ - - - - -/* Exported functions: */ - -void check_memory_mapped_IO (); -void expand_data (int addl_bytes); -void expand_k_data (int addl_bytes); -void expand_stack (int addl_bytes); -void make_memory (int text_size, int data_size, int data_limit, - int stack_size, int stack_limit, int k_text_size, - int k_data_size, int k_data_limit); -void* mem_reference(mem_addr addr); -void print_mem (mem_addr addr); -instruction* read_mem_inst(mem_addr addr); -reg_word read_mem_byte(mem_addr addr); -reg_word read_mem_half(mem_addr addr); -reg_word read_mem_word(mem_addr addr); -void set_mem_inst(mem_addr addr, instruction* inst); -void set_mem_byte(mem_addr addr, reg_word value); -void set_mem_half(mem_addr addr, reg_word value); -void set_mem_word(mem_addr addr, reg_word value); diff --git a/spim-qtbase/CPU/op.h b/spim-qtbase/CPU/op.h deleted file mode 100755 index 4b46df5..0000000 --- a/spim-qtbase/CPU/op.h +++ /dev/null @@ -1,525 +0,0 @@ -/* SPIM S20 MIPS simulator. - This file describes the MIPS instructions, the assembler pseudo - instructions, the assembler pseudo-ops, and the spim commands. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Type of each entry: */ - -#define ASM_DIR 0 -#define PSEUDO_OP 1 - -#define BC_TYPE_INST 10 -#define B1_TYPE_INST 11 -#define I1s_TYPE_INST 12 -#define I1t_TYPE_INST 13 -#define I2_TYPE_INST 14 -#define B2_TYPE_INST 15 -#define I2a_TYPE_INST 16 - -#define R1s_TYPE_INST 20 -#define R1d_TYPE_INST 21 -#define R2st_TYPE_INST 22 -#define R2ds_TYPE_INST 23 -#define R2td_TYPE_INST 24 -#define R2sh_TYPE_INST 25 -#define R3_TYPE_INST 26 -#define R3sh_TYPE_INST 27 - -#define FP_I2a_TYPE_INST 30 -#define FP_R2ds_TYPE_INST 31 -#define FP_R2ts_TYPE_INST 32 -#define FP_CMP_TYPE_INST 33 -#define FP_R3_TYPE_INST 34 -#define FP_R4_TYPE_INST 35 -#define FP_MOVC_TYPE_INST 36 -#define MOVC_TYPE_INST 37 - -#define J_TYPE_INST 40 -#define NOARG_TYPE_INST 42 - - -/* Information on each keyword token that can be read by spim. Must be - sorted in alphabetical order. */ - -OP(".alias", Y_ALIAS_DIR, ASM_DIR, -1) -OP(".align", Y_ALIGN_DIR, ASM_DIR, -1) -OP(".ascii", Y_ASCII_DIR, ASM_DIR, -1) -OP(".asciiz", Y_ASCIIZ_DIR, ASM_DIR, -1) -OP(".asm0", Y_ASM0_DIR, ASM_DIR, -1) -OP(".bgnb", Y_BGNB_DIR, ASM_DIR, -1) -OP(".byte", Y_BYTE_DIR, ASM_DIR, -1) -OP(".comm", Y_COMM_DIR, ASM_DIR, -1) -OP(".data", Y_DATA_DIR, ASM_DIR, -1) -OP(".double", Y_DOUBLE_DIR, ASM_DIR, -1) -OP(".end", Y_END_DIR, ASM_DIR, -1) -OP(".endb", Y_ENDB_DIR, ASM_DIR, -1) -OP(".endr", Y_ENDR_DIR, ASM_DIR, -1) -OP(".ent", Y_ENT_DIR, ASM_DIR, -1) -OP(".err", Y_ERR_DIR, ASM_DIR, -1) -OP(".extern", Y_EXTERN_DIR, ASM_DIR, -1) -OP(".file", Y_FILE_DIR, ASM_DIR, -1) -OP(".float", Y_FLOAT_DIR, ASM_DIR, -1) -OP(".fmask", Y_FMASK_DIR, ASM_DIR, -1) -OP(".frame", Y_FRAME_DIR, ASM_DIR, -1) -OP(".globl", Y_GLOBAL_DIR, ASM_DIR, -1) -OP(".half", Y_HALF_DIR, ASM_DIR, -1) -OP(".kdata", Y_K_DATA_DIR, ASM_DIR, -1) -OP(".ktext", Y_K_TEXT_DIR, ASM_DIR, -1) -OP(".lab", Y_LABEL_DIR, ASM_DIR, -1) -OP(".lcomm", Y_LCOMM_DIR, ASM_DIR, -1) -OP(".livereg", Y_LIVEREG_DIR, ASM_DIR, -1) -OP(".loc", Y_LOC_DIR, ASM_DIR, -1) -OP(".mask", Y_MASK_DIR, ASM_DIR, -1) -OP(".noalias", Y_NOALIAS_DIR, ASM_DIR, -1) -OP(".option", Y_OPTIONS_DIR, ASM_DIR, -1) -OP(".rdata", Y_RDATA_DIR, ASM_DIR, -1) -OP(".repeat", Y_REPEAT_DIR, ASM_DIR, -1) -OP(".sdata", Y_SDATA_DIR, ASM_DIR, -1) -OP(".set", Y_SET_DIR, ASM_DIR, -1) -OP(".space", Y_SPACE_DIR, ASM_DIR, -1) -OP(".struct", Y_STRUCT_DIR, ASM_DIR, -1) -OP(".text", Y_TEXT_DIR, ASM_DIR, -1) -OP(".verstamp",Y_VERSTAMP_DIR, ASM_DIR, -1) -OP(".vreg", Y_VREG_DIR, ASM_DIR, -1) -OP(".word", Y_WORD_DIR, ASM_DIR, -1) - -OP("abs", Y_ABS_POP, PSEUDO_OP, -1) -OP("abs.d", Y_ABS_D_OP, FP_R2ds_TYPE_INST, 0x46200005) -OP("abs.ps", Y_ABS_PS_OP, FP_R2ds_TYPE_INST, 0x46600005) /* MIPS32 Rev 2 */ -OP("abs.s", Y_ABS_S_OP, FP_R2ds_TYPE_INST, 0x46000005) - -OP("add", Y_ADD_OP, R3_TYPE_INST, 0x00000020) -OP("add.d", Y_ADD_D_OP, FP_R3_TYPE_INST, 0x46200000) -OP("add.ps", Y_ADD_PS_OP, FP_R3_TYPE_INST, 0x46600000) /* MIPS32 Rev 2 */ -OP("add.s", Y_ADD_S_OP, FP_R3_TYPE_INST, 0x46000000) -OP("addi", Y_ADDI_OP, I2_TYPE_INST, 0x20000000) -OP("addiu", Y_ADDIU_OP, I2_TYPE_INST, 0x24000000) -OP("addu", Y_ADDU_OP, R3_TYPE_INST, 0x00000021) - -OP("alnv.ps", Y_ALNV_PS_OP, FP_R4_TYPE_INST, 0x4c00001e) /* MIPS32 Rev 2 */ - -OP("and", Y_AND_OP, R3_TYPE_INST, 0x00000024) -OP("andi", Y_ANDI_OP, I2_TYPE_INST, 0x30000000) - -OP("b", Y_B_POP, PSEUDO_OP, -1) -OP("bal", Y_BAL_POP, PSEUDO_OP, -1) - -OP("bc1f", Y_BC1F_OP, BC_TYPE_INST, 0x45000000) -OP("bc1fl", Y_BC1FL_OP, BC_TYPE_INST, 0x45020000) /* MIPS32 */ -OP("bc1t", Y_BC1T_OP, BC_TYPE_INST, 0x45010000) -OP("bc1tl", Y_BC1TL_OP, BC_TYPE_INST, 0x45030000) /* MIPS32 */ - -OP("bc2f", Y_BC2F_OP, BC_TYPE_INST, 0x49000000) -OP("bc2fl", Y_BC2FL_OP, BC_TYPE_INST, 0x49020000) /* MIPS32 */ -OP("bc2t", Y_BC2T_OP, BC_TYPE_INST, 0x49010000) -OP("bc2tl", Y_BC2TL_OP, BC_TYPE_INST, 0x49030000) /* MIPS32 */ - -OP("beq", Y_BEQ_OP, B2_TYPE_INST, 0x10000000) -OP("beql", Y_BEQL_OP, B2_TYPE_INST, 0x50000000) /* MIPS32 */ -OP("beqz", Y_BEQZ_POP, PSEUDO_OP, -1) -OP("bge", Y_BGE_POP, PSEUDO_OP, -1) -OP("bgeu", Y_BGEU_POP, PSEUDO_OP, -1) -OP("bgez", Y_BGEZ_OP, B1_TYPE_INST, 0x04010000) -OP("bgezal", Y_BGEZAL_OP, B1_TYPE_INST, 0x04110000) -OP("bgezall", Y_BGEZALL_OP, B1_TYPE_INST, 0x04130000) /* MIPS32 */ -OP("bgezl", Y_BGEZL_OP, B1_TYPE_INST, 0x04030000) /* MIPS32 */ -OP("bgt", Y_BGT_POP, PSEUDO_OP, -1) -OP("bgtu", Y_BGTU_POP, PSEUDO_OP, -1) -OP("bgtz", Y_BGTZ_OP, B1_TYPE_INST, 0x1c000000) -OP("bgtzl", Y_BGTZL_OP, B1_TYPE_INST, 0x5c000000) /* MIPS32 */ -OP("ble", Y_BLE_POP, PSEUDO_OP, -1) -OP("bleu", Y_BLEU_POP, PSEUDO_OP, -1) -OP("blez", Y_BLEZ_OP, B1_TYPE_INST, 0x18000000) -OP("blezl", Y_BLEZL_OP, B1_TYPE_INST, 0x58000000) /* MIPS32 */ -OP("blt", Y_BLT_POP, PSEUDO_OP, -1) -OP("bltu", Y_BLTU_POP, PSEUDO_OP, -1) -OP("bltz", Y_BLTZ_OP, B1_TYPE_INST, 0x04000000) -OP("bltzal", Y_BLTZAL_OP, B1_TYPE_INST, 0x04100000) -OP("bltzall", Y_BLTZALL_OP, B1_TYPE_INST, 0x04120000) /* MIPS32 */ -OP("bltzl", Y_BLTZL_OP, B1_TYPE_INST, 0x04020000) /* MIPS32 */ -OP("bne", Y_BNE_OP, B2_TYPE_INST, 0x14000000) -OP("bnel", Y_BNEL_OP, B2_TYPE_INST, 0x54000000) /* MIPS32 */ -OP("bnez", Y_BNEZ_POP, PSEUDO_OP, -1) - -OP("break", Y_BREAK_OP, NOARG_TYPE_INST, 0x0000000d) - -OP("c.eq.d", Y_C_EQ_D_OP, FP_CMP_TYPE_INST, 0x46200032) -OP("c.eq.ps", Y_C_EQ_PS_OP, FP_CMP_TYPE_INST, 0x46600032) /* MIPS32 Rev 2 */ -OP("c.eq.s", Y_C_EQ_S_OP, FP_CMP_TYPE_INST, 0x46000032) -OP("c.f.d", Y_C_F_D_OP, FP_CMP_TYPE_INST, 0x46200030) -OP("c.f.ps", Y_C_F_PS_OP, FP_CMP_TYPE_INST, 0x46600030) /* MIPS32 Rev 2 */ -OP("c.f.s", Y_C_F_S_OP, FP_CMP_TYPE_INST, 0x46000030) -OP("c.le.d", Y_C_LE_D_OP, FP_CMP_TYPE_INST, 0x4620003e) -OP("c.le.ps", Y_C_LE_PS_OP, FP_CMP_TYPE_INST, 0x4660003e) /* MIPS32 Rev 2 */ -OP("c.le.s", Y_C_LE_S_OP, FP_CMP_TYPE_INST, 0x4600003e) -OP("c.lt.d", Y_C_LT_D_OP, FP_CMP_TYPE_INST, 0x4620003c) -OP("c.lt.ps", Y_C_LT_PS_OP, FP_CMP_TYPE_INST, 0x4660003c) /* MIPS32 Rev 2 */ -OP("c.lt.s", Y_C_LT_S_OP, FP_CMP_TYPE_INST, 0x4600003c) -OP("c.nge.d", Y_C_NGE_D_OP, FP_CMP_TYPE_INST, 0x4620003d) -OP("c.nge.ps", Y_C_NGE_PS_OP, FP_CMP_TYPE_INST, 0x4660003d) /* MIPS32 Rev 2 */ -OP("c.nge.s", Y_C_NGE_S_OP, FP_CMP_TYPE_INST, 0x4600003d) -OP("c.ngl.d", Y_C_NGL_D_OP, FP_CMP_TYPE_INST, 0x4620003b) -OP("c.ngl.ps", Y_C_NGL_PS_OP, FP_CMP_TYPE_INST, 0x4660003b) /* MIPS32 Rev 2 */ -OP("c.ngl.s", Y_C_NGL_S_OP, FP_CMP_TYPE_INST, 0x4600003b) -OP("c.ngle.d", Y_C_NGLE_D_OP, FP_CMP_TYPE_INST, 0x46200039) -OP("c.ngle.ps", Y_C_NGLE_PS_OP, FP_CMP_TYPE_INST, 0x46600039) /* MIPS32 Rev 2 */ -OP("c.ngle.s", Y_C_NGLE_S_OP, FP_CMP_TYPE_INST, 0x46000039) -OP("c.ngt.d", Y_C_NGT_D_OP, FP_CMP_TYPE_INST, 0x4620003f) -OP("c.ngt.ps", Y_C_NGT_PS_OP, FP_CMP_TYPE_INST, 0x4660003f) /* MIPS32 Rev 2 */ -OP("c.ngt.s", Y_C_NGT_S_OP, FP_CMP_TYPE_INST, 0x4600003f) -OP("c.ole.d", Y_C_OLE_D_OP, FP_CMP_TYPE_INST, 0x46200036) -OP("c.ole.ps", Y_C_OLE_PS_OP, FP_CMP_TYPE_INST, 0x46600036) /* MIPS32 Rev 2 */ -OP("c.ole.s", Y_C_OLE_S_OP, FP_CMP_TYPE_INST, 0x46000036) -OP("c.olt.d", Y_C_OLT_D_OP, FP_CMP_TYPE_INST, 0x46200034) -OP("c.olt.ps", Y_C_OLT_PS_OP, FP_CMP_TYPE_INST, 0x46600034) /* MIPS32 Rev 2 */ -OP("c.olt.s", Y_C_OLT_S_OP, FP_CMP_TYPE_INST, 0x46000034) -OP("c.seq.d", Y_C_SEQ_D_OP, FP_CMP_TYPE_INST, 0x4620003a) -OP("c.seq.ps", Y_C_SEQ_PS_OP, FP_CMP_TYPE_INST, 0x4660003a) /* MIPS32 Rev 2 */ -OP("c.seq.s", Y_C_SEQ_S_OP, FP_CMP_TYPE_INST, 0x4600003a) -OP("c.sf.d", Y_C_SF_D_OP, FP_CMP_TYPE_INST, 0x46200038) -OP("c.sf.ps", Y_C_SF_PS_OP, FP_CMP_TYPE_INST, 0x46600038) /* MIPS32 Rev 2 */ -OP("c.sf.s", Y_C_SF_S_OP, FP_CMP_TYPE_INST, 0x46000038) -OP("c.ueq.d", Y_C_UEQ_D_OP, FP_CMP_TYPE_INST, 0x46200033) -OP("c.ueq.ps", Y_C_UEQ_PS_OP, FP_CMP_TYPE_INST, 0x46600033) /* MIPS32 Rev 2 */ -OP("c.ueq.s", Y_C_UEQ_S_OP, FP_CMP_TYPE_INST, 0x46000033) -OP("c.ule.d", Y_C_ULE_D_OP, FP_CMP_TYPE_INST, 0x46200037) -OP("c.ule.ps", Y_C_ULE_PS_OP, FP_CMP_TYPE_INST, 0x46600037) /* MIPS32 Rev 2 */ -OP("c.ule.s", Y_C_ULE_S_OP, FP_CMP_TYPE_INST, 0x46000037) -OP("c.ult.d", Y_C_ULT_D_OP, FP_CMP_TYPE_INST, 0x46200035) -OP("c.ult.ps", Y_C_ULT_PS_OP, FP_CMP_TYPE_INST, 0x46600035) /* MIPS32 Rev 2 */ -OP("c.ult.s", Y_C_ULT_S_OP, FP_CMP_TYPE_INST, 0x46000035) -OP("c.un.d", Y_C_UN_D_OP, FP_CMP_TYPE_INST, 0x46200031) -OP("c.un.ps", Y_C_UN_PS_OP, FP_CMP_TYPE_INST, 0x46600031) /* MIPS32 Rev 2 */ -OP("c.un.s", Y_C_UN_S_OP, FP_CMP_TYPE_INST, 0x46000031) - -OP("cache", Y_CACHE_OP, I2_TYPE_INST, 0xbc000000) /* MIPS32 */ - -OP("ceil.l.d", Y_CEIL_L_D_OP, FP_R2ds_TYPE_INST, 0x4620000a) /* MIPS32 Rev 2 */ -OP("ceil.l.s", Y_CEIL_L_S_OP, FP_R2ds_TYPE_INST, 0x4600000a) /* MIPS32 Rev 2 */ -OP("ceil.w.d", Y_CEIL_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000e) /* MIPS32 */ -OP("ceil.w.s", Y_CEIL_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000e) /* MIPS32 */ - -OP("cfc0", Y_CFC0_OP, FP_R2ts_TYPE_INST, 0x40400000) -OP("cfc1", Y_CFC1_OP, FP_R2ts_TYPE_INST, 0x44400000) -OP("cfc2", Y_CFC2_OP, FP_R2ts_TYPE_INST, 0x48400000) - -OP("clo", Y_CLO_OP, R3_TYPE_INST, 0x70000021) -OP("clz", Y_CLZ_OP, R3_TYPE_INST, 0x70000020) - -OP("cop2", Y_COP2_OP, J_TYPE_INST, 0x4a000000) - -OP("ctc0", Y_CTC0_OP, FP_R2ts_TYPE_INST, 0x40c00000) -OP("ctc1", Y_CTC1_OP, FP_R2ts_TYPE_INST, 0x44c00000) -OP("ctc2", Y_CTC2_OP, FP_R2ts_TYPE_INST, 0x48c00000) - -OP("cvt.d.l", Y_CVT_D_L_OP, FP_R2ds_TYPE_INST, 0x46b00021) /* MIPS32 Rev 2 */ -OP("cvt.d.s", Y_CVT_D_S_OP, FP_R2ds_TYPE_INST, 0x46000021) -OP("cvt.d.w", Y_CVT_D_W_OP, FP_R2ds_TYPE_INST, 0x46200021) -OP("cvt.l.d", Y_CVT_L_D_OP, FP_R2ds_TYPE_INST, 0x46200025) /* MIPS32 Rev 2 */ -OP("cvt.l.s", Y_CVT_L_S_OP, FP_R2ds_TYPE_INST, 0x46000025) /* MIPS32 Rev 2 */ -OP("cvt.ps.s", Y_CVT_PS_S_OP, FP_R2ds_TYPE_INST, 0x46000026) /* MIPS32 Rev 2 */ -OP("cvt.s.d", Y_CVT_S_D_OP, FP_R2ds_TYPE_INST, 0x46200020) -OP("cvt.s.l", Y_CVT_S_L_OP, FP_R2ds_TYPE_INST, 0x46b00020) /* MIPS32 Rev 2 */ -OP("cvt.s.pl", Y_CVT_S_PL_OP, FP_R2ds_TYPE_INST, 0x46c00024) /* MIPS32 Rev 2 */ -OP("cvt.s.pu", Y_CVT_S_PU_OP, FP_R2ds_TYPE_INST, 0x46c00020) /* MIPS32 Rev 2 */ -OP("cvt.s.w", Y_CVT_S_W_OP, FP_R2ds_TYPE_INST, 0x46800020) -OP("cvt.w.d", Y_CVT_W_D_OP, FP_R2ds_TYPE_INST, 0x46200024) -OP("cvt.w.s", Y_CVT_W_S_OP, FP_R2ds_TYPE_INST, 0x46000024) - -OP("deret", Y_DERET_OP, NOARG_TYPE_INST, 0x4200001f) /* MIPS32 Rev 2 */ -OP("di", Y_DI_OP, I1t_TYPE_INST, 0x41606000) /* MIPS32 Rev 2 */ - -OP("div", Y_DIV_OP, R2st_TYPE_INST, 0x0000001a) -OP("div.d", Y_DIV_D_OP, FP_R3_TYPE_INST, 0x46200003) -OP("div.s", Y_DIV_S_OP, FP_R3_TYPE_INST, 0x46000003) -OP("divu", Y_DIVU_OP, R2st_TYPE_INST, 0x0000001b) - -OP("ehb", Y_EHB_OP, NOARG_TYPE_INST, 0x000000c0) /* MIPS32 Rev 2 */ -OP("ei", Y_EI_OP, I1t_TYPE_INST, 0x41606020) /* MIPS32 Rev 2 */ -OP("eret", Y_ERET_OP, NOARG_TYPE_INST, 0x42000018) /* MIPS32 */ -OP("ext", Y_EXT_OP, FP_R2ds_TYPE_INST, 0x7c000000) /* MIPS32 Rev 2 */ - -OP("floor.l.d", Y_FLOOR_L_D_OP, FP_R2ds_TYPE_INST, 0x4620000b) /* MIPS32 Rev 2 */ -OP("floor.l.s", Y_FLOOR_L_S_OP, FP_R2ds_TYPE_INST, 0x4600000b) /* MIPS32 Rev 2 */ -OP("floor.w.d", Y_FLOOR_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000f) /* MIPS32 */ -OP("floor.w.s", Y_FLOOR_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000f) /* MIPS32 */ - -OP("ins", Y_INS_OP, FP_R2ds_TYPE_INST, 0x7c000004) /* MIPS32 Rev 2 */ - -OP("j", Y_J_OP, J_TYPE_INST, 0x08000000) -OP("jal", Y_JAL_OP, J_TYPE_INST, 0x0c000000) -OP("jalr", Y_JALR_OP, R2ds_TYPE_INST, 0x00000009) -OP("jalr.hb", Y_JALR_HB_OP, R2ds_TYPE_INST, 0x00000409) /* MIPS32 Rev 2 */ - -OP("jr", Y_JR_OP, R1s_TYPE_INST, 0x00000008) -OP("jr.hb", Y_JR_HB_OP, R1s_TYPE_INST, 0x00000408) /* MIPS32 Rev 2 */ - -OP("l.d", Y_L_D_POP, PSEUDO_OP, -1) -OP("l.s", Y_L_S_POP, PSEUDO_OP, -1) - -OP("la", Y_LA_POP, PSEUDO_OP, -1) -OP("lb", Y_LB_OP, I2a_TYPE_INST, 0x80000000) -OP("lbu", Y_LBU_OP, I2a_TYPE_INST, 0x90000000) -OP("ld", Y_LD_POP, PSEUDO_OP, -1) -OP("ldc1", Y_LDC1_OP, FP_I2a_TYPE_INST, 0xd4000000) /* MIPS32 */ -OP("ldc2", Y_LDC2_OP, I2a_TYPE_INST, 0xd8000000) /* MIPS32 */ -OP("ldxc1", Y_LDXC1_OP, FP_R3_TYPE_INST, 0x4c000001) /* MIPS32 Rev 2 */ -OP("lh", Y_LH_OP, I2a_TYPE_INST, 0x84000000) -OP("lhu", Y_LHU_OP, I2a_TYPE_INST, 0x94000000) - -OP("li", Y_LI_POP, PSEUDO_OP, -1) -OP("li.d", Y_LI_D_POP, PSEUDO_OP, -1) -OP("li.s", Y_LI_S_POP, PSEUDO_OP, -1) - -OP("ll", Y_LL_OP, I2a_TYPE_INST, 0xc0000000) /* MIPS32 */ - -OP("lui", Y_LUI_OP, I1t_TYPE_INST, 0x3c000000) -OP("luxc1", Y_LUXC1_OP, FP_R3_TYPE_INST, 0x4c000005) /* MIPS32 Rev 2 */ - -OP("lw", Y_LW_OP, I2a_TYPE_INST, 0x8c000000) -OP("lwc1", Y_LWC1_OP, FP_I2a_TYPE_INST, 0xc4000000) -OP("lwc2", Y_LWC2_OP, I2a_TYPE_INST, 0xc8000000) -OP("lwl", Y_LWL_OP, I2a_TYPE_INST, 0x88000000) -OP("lwr", Y_LWR_OP, I2a_TYPE_INST, 0x98000000) -OP("lwxc1", Y_LWXC1_OP, FP_R3_TYPE_INST, 0x4c000000) /* MIPS32 Rev 2 */ - -OP("madd", Y_MADD_OP, R2st_TYPE_INST, 0x70000000) /* MIPS32 */ -OP("madd.d", Y_MADD_D_OP, FP_R4_TYPE_INST, 0x4c000001) /* MIPS32 Rev 2 */ -OP("madd.ps", Y_MADD_PS_OP, FP_R4_TYPE_INST, 0x4c000006) /* MIPS32 Rev 2 */ -OP("madd.s", Y_MADD_S_OP, FP_R4_TYPE_INST, 0x4c000000) /* MIPS32 Rev 2 */ -OP("maddu", Y_MADDU_OP, R2st_TYPE_INST, 0x70000001) /* MIPS32 */ - -OP("mfc0", Y_MFC0_OP, R2td_TYPE_INST, 0x40000000) -OP("mfc1", Y_MFC1_OP, FP_R2ts_TYPE_INST, 0x44000000) -OP("mfc1.d", Y_MFC1_D_POP, PSEUDO_OP, -1) -OP("mfc2", Y_MFC2_OP, R2td_TYPE_INST, 0x48000000) -OP("mfhc1", Y_MFHC1_OP, FP_R2ts_TYPE_INST, 0x44600000) /* MIPS32 Rev 2 */ -OP("mfhc2", Y_MFHC2_OP, R2td_TYPE_INST, 0x48600000) /* MIPS32 Rev 2 */ -OP("mfhi", Y_MFHI_OP, R1d_TYPE_INST, 0x00000010) -OP("mflo", Y_MFLO_OP, R1d_TYPE_INST, 0x00000012) - -OP("mov.d", Y_MOV_D_OP, FP_R2ds_TYPE_INST, 0x46200006) -OP("mov.ps", Y_MOV_PS_OP, FP_R2ds_TYPE_INST, 0x46c00006) /* MIPS32 Rev 2 */ -OP("mov.s", Y_MOV_S_OP, FP_R2ds_TYPE_INST, 0x46000006) -OP("move", Y_MOVE_POP, PSEUDO_OP, -1) - -OP("movf", Y_MOVF_OP, MOVC_TYPE_INST, 0x00000001) /* MIPS32 */ -OP("movf.d", Y_MOVF_D_OP, FP_MOVC_TYPE_INST, 0x46200011) /* MIPS32 */ -OP("movf.ps", Y_MOVF_PS_OP, FP_MOVC_TYPE_INST, 0x46c00011) /* MIPS32 Rev 2 */ -OP("movf.s", Y_MOVF_S_OP, FP_MOVC_TYPE_INST, 0x46000011) /* MIPS32 */ - -OP("movn", Y_MOVN_OP, R3_TYPE_INST, 0x0000000b) /* MIPS32 */ -OP("movn.d", Y_MOVN_D_OP, FP_MOVC_TYPE_INST, 0x46200013) /* MIPS32 */ -OP("movn.ps", Y_MOVN_PS_OP, FP_MOVC_TYPE_INST, 0x46c00013) /* MIPS32 Rev 2 */ -OP("movn.s", Y_MOVN_S_OP, FP_MOVC_TYPE_INST, 0x46000013) /* MIPS32 */ - -OP("movt", Y_MOVT_OP, MOVC_TYPE_INST, 0x00010001) /* MIPS32 */ -OP("movt.d", Y_MOVT_D_OP, FP_MOVC_TYPE_INST, 0x46210011) /* MIPS32 */ -OP("movt.ps", Y_MOVT_PS_OP, FP_MOVC_TYPE_INST, 0x46c10011) /* MIPS32 Rev 2 */ -OP("movt.s", Y_MOVT_S_OP, FP_MOVC_TYPE_INST, 0x46010011) /* MIPS32 */ - -OP("movz", Y_MOVZ_OP, R3_TYPE_INST, 0x0000000a) /* MIPS32 */ -OP("movz.d", Y_MOVZ_D_OP, FP_MOVC_TYPE_INST, 0x46200012) /* MIPS32 */ -OP("movz.ps", Y_MOVZ_PS_OP, FP_MOVC_TYPE_INST, 0x46c00012) /* MIPS32 Rev 2 */ -OP("movz.s", Y_MOVZ_S_OP, FP_MOVC_TYPE_INST, 0x46000012) /* MIPS32 */ - -OP("msub", Y_MSUB_OP, R2st_TYPE_INST, 0x70000004) /* MIPS32 */ -OP("msub.d", Y_MSUB_D_OP, FP_R4_TYPE_INST, 0x4c000021) /* MIPS32 Rev 2 */ -OP("msub.ps", Y_MSUB_PS_OP, FP_R4_TYPE_INST, 0x4c000026) /* MIPS32 Rev 2 */ -OP("msub.s", Y_MSUB_S_OP, FP_R4_TYPE_INST, 0x4c000020) /* MIPS32 Rev 2 */ -OP("msubu", Y_MSUBU_OP, R2st_TYPE_INST, 0x70000005) /* MIPS32 */ - -OP("mtc0", Y_MTC0_OP, R2td_TYPE_INST, 0x40800000) -OP("mtc1", Y_MTC1_OP, FP_R2ts_TYPE_INST, 0x44800000) -OP("mtc1.d", Y_MTC1_D_POP, PSEUDO_OP, -1) -OP("mtc2", Y_MTC2_OP, R2td_TYPE_INST, 0x48800000) -OP("mthc1", Y_MTHC1_OP, FP_R2ts_TYPE_INST, 0x44e00000) /* MIPS32 Rev 2 */ -OP("mthc2", Y_MTHC2_OP, R2td_TYPE_INST, 0x48e00000) /* MIPS32 Rev 2 */ - -OP("mthi", Y_MTHI_OP, R1s_TYPE_INST, 0x00000011) -OP("mtlo", Y_MTLO_OP, R1s_TYPE_INST, 0x00000013) - -OP("mul", Y_MUL_OP, R3_TYPE_INST, 0x70000002) /* MIPS32 */ -OP("mul.d", Y_MUL_D_OP, FP_R3_TYPE_INST, 0x46200002) -OP("mul.ps", Y_MUL_PS_OP, FP_R3_TYPE_INST, 0x46c00002) /* MIPS32 Rev 2 */ -OP("mul.s", Y_MUL_S_OP, FP_R3_TYPE_INST, 0x46000002) -OP("mulo", Y_MULO_POP, PSEUDO_OP, -1) -OP("mulou", Y_MULOU_POP, PSEUDO_OP, -1) -OP("mult", Y_MULT_OP, R2st_TYPE_INST, 0x00000018) -OP("multu", Y_MULTU_OP, R2st_TYPE_INST, 0x00000019) - -OP("neg", Y_NEG_POP, PSEUDO_OP, -1) -OP("neg.d", Y_NEG_D_OP, FP_R2ds_TYPE_INST, 0x46200007) -OP("neg.ps", Y_NEG_PS_OP, FP_R2ds_TYPE_INST, 0x46c00007) /* MIPS32 Rev 2 */ -OP("neg.s", Y_NEG_S_OP, FP_R2ds_TYPE_INST, 0x46000007) -OP("negu", Y_NEGU_POP, PSEUDO_OP, -1) - -OP("nmadd.d", Y_NMADD_D_OP, FP_R4_TYPE_INST, 0x4c000031) /* MIPS32 Rev 2 */ -OP("nmadd.ps", Y_NMADD_PS_OP, FP_R4_TYPE_INST, 0x4c000036) /* MIPS32 Rev 2 */ -OP("nmadd.s", Y_NMADD_S_OP, FP_R4_TYPE_INST, 0x4c000030) /* MIPS32 Rev 2 */ -OP("nmsub.d", Y_NMSUB_D_OP, FP_R4_TYPE_INST, 0x4c000039) /* MIPS32 Rev 2 */ -OP("nmsub.ps", Y_NMSUB_PS_OP, FP_R4_TYPE_INST, 0x4c00003e) /* MIPS32 Rev 2 */ -OP("nmsub.s", Y_NMSUB_S_OP, FP_R4_TYPE_INST, 0x4c000038) /* MIPS32 Rev 2 */ - -OP("nop", Y_NOP_POP, PSEUDO_OP, -1) -OP("nor", Y_NOR_OP, R3_TYPE_INST, 0x00000027) -OP("not", Y_NOT_POP, PSEUDO_OP, -1) -OP("or", Y_OR_OP, R3_TYPE_INST, 0x00000025) -OP("ori", Y_ORI_OP, I2_TYPE_INST, 0x34000000) - -OP("pll.ps", Y_PLL_PS_OP, FP_R3_TYPE_INST, 0x46c0002c) /* MIPS32 Rev 2 */ -OP("plu.ps", Y_PLU_PS_OP, FP_R3_TYPE_INST, 0x46c0002d) /* MIPS32 Rev 2 */ - -OP("pref", Y_PREF_OP, I2_TYPE_INST, 0xcc000000) /* MIPS32 */ -OP("prefx", Y_PREFX_OP, R2st_TYPE_INST, 0x4600000f) /* MIPS32 Rev 2 */ -OP("pul.ps", Y_PUL_PS_OP, FP_R3_TYPE_INST, 0x46c0002e) /* MIPS32 Rev 2 */ -OP("puu.ps", Y_PUU_PS_OP, FP_R3_TYPE_INST, 0x46c0002f) /* MIPS32 Rev 2 */ - -OP("rdhwr", Y_RDHWR_OP, R3_TYPE_INST, 0x7c00003b) /* MIPS32 Rev 2 */ -OP("rdpgpr", Y_RDPGPR_OP, R2td_TYPE_INST, 0x41400000) /* MIPS32 Rev 2 */ - -OP("recip.d", Y_RECIP_D_OP, FP_R2ds_TYPE_INST, 0x46200015) /* MIPS32 Rev 2 */ -OP("recip.s", Y_RECIP_S_OP, FP_R2ds_TYPE_INST, 0x46000015) /* MIPS32 Rev 2 */ - -OP("rem", Y_REM_POP, PSEUDO_OP, -1) -OP("remu", Y_REMU_POP, PSEUDO_OP, -1) - -OP("rfe", Y_RFE_OP, NOARG_TYPE_INST, 0x42000010) - -OP("rol", Y_ROL_POP, PSEUDO_OP, -1) -OP("ror", Y_ROR_POP, PSEUDO_OP, -1) -OP("rotr", Y_ROTR_OP, R2sh_TYPE_INST, 0x00200002) /* MIPS32 Rev 2 */ -OP("rotrv", Y_ROTRV_OP, R2sh_TYPE_INST, 0x00200003) /* MIPS32 Rev 2 */ - -OP("round.l.d", Y_ROUND_L_D_OP, FP_R2ds_TYPE_INST, 0x46200008) /* MIPS32 Rev 2 */ -OP("round.l.s", Y_ROUND_L_S_OP, FP_R2ds_TYPE_INST, 0x46000008) /* MIPS32 Rev 2 */ -OP("round.w.d", Y_ROUND_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000c) /* MIPS32 */ -OP("round.w.s", Y_ROUND_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000c) /* MIPS32 */ - -OP("rsqrt.d", Y_RSQRT_D_OP, FP_R2ds_TYPE_INST, 0x46200016) /* MIPS32 Rev 2 */ -OP("rsqrt.s", Y_RSQRT_S_OP, FP_R2ds_TYPE_INST, 0x46000016) /* MIPS32 Rev 2 */ - -OP("s.d", Y_S_D_POP, PSEUDO_OP, -1) -OP("s.s", Y_S_S_POP, PSEUDO_OP, -1) - -OP("sb", Y_SB_OP, I2a_TYPE_INST, 0xa0000000) -OP("sc", Y_SC_OP, I2a_TYPE_INST, 0xe0000000) /* MIPS32 */ -OP("sd", Y_SD_POP, PSEUDO_OP, -1) -OP("sdbbp", Y_SDBBP_OP, NOARG_TYPE_INST, 0x7000003f) /* MIPS32 Rev 2*/ -OP("sdc1", Y_SDC1_OP, FP_I2a_TYPE_INST, 0xf4000000) /* MIPS32 */ -OP("sdc2", Y_SDC2_OP, I2a_TYPE_INST, 0xf8000000) /* MIPS32 */ -OP("sdxc1", Y_SDXC1_OP, FP_R3_TYPE_INST, 0x46000009) /* MIPS32 Rev 2 */ - -OP("seb", Y_SEB_OP, R2td_TYPE_INST, 0x7c000420) /* MIPS32 Rev 2 */ -OP("seh", Y_SEH_OP, R2td_TYPE_INST, 0x7c000620) /* MIPS32 Rev 2 */ -OP("seq", Y_SEQ_POP, PSEUDO_OP, -1) -OP("sge", Y_SGE_POP, PSEUDO_OP, -1) -OP("sgeu", Y_SGEU_POP, PSEUDO_OP, -1) -OP("sgt", Y_SGT_POP, PSEUDO_OP, -1) -OP("sgtu", Y_SGTU_POP, PSEUDO_OP, -1) - -OP("sh", Y_SH_OP, I2a_TYPE_INST, 0xa4000000) -OP("sle", Y_SLE_POP, PSEUDO_OP, -1) -OP("sleu", Y_SLEU_POP, PSEUDO_OP, -1) -OP("sll", Y_SLL_OP, R2sh_TYPE_INST, 0x00000000) -OP("sllv", Y_SLLV_OP, R3sh_TYPE_INST, 0x00000004) - -OP("slt", Y_SLT_OP, R3_TYPE_INST, 0x0000002a) -OP("slti", Y_SLTI_OP, I2_TYPE_INST, 0x28000000) -OP("sltiu", Y_SLTIU_OP, I2_TYPE_INST, 0x2c000000) -OP("sltu", Y_SLTU_OP, R3_TYPE_INST, 0x0000002b) -OP("sne", Y_SNE_POP, PSEUDO_OP, -1) - -OP("sqrt.d", Y_SQRT_D_OP, FP_R2ds_TYPE_INST, 0x46200004) /* MIPS32 */ -OP("sqrt.s", Y_SQRT_S_OP, FP_R2ds_TYPE_INST, 0x46000004) /* MIPS32 */ - -OP("sra", Y_SRA_OP, R2sh_TYPE_INST, 0x00000003) -OP("srav", Y_SRAV_OP, R3sh_TYPE_INST, 0x00000007) -OP("srl", Y_SRL_OP, R2sh_TYPE_INST, 0x00000002) -OP("srlv", Y_SRLV_OP, R3sh_TYPE_INST, 0x00000006) - -OP("ssnop", Y_SSNOP_OP, R2sh_TYPE_INST, 0x00000040) /* MIPS32 */ - -OP("sub", Y_SUB_OP, R3_TYPE_INST, 0x00000022) -OP("sub.d", Y_SUB_D_OP, FP_R3_TYPE_INST, 0x46200001) -OP("sub.ps", Y_SUB_PS_OP, FP_R3_TYPE_INST, 0x46600001) /* MIPS32 Rev 2 */ -OP("sub.s", Y_SUB_S_OP, FP_R3_TYPE_INST, 0x46000001) -OP("subu", Y_SUBU_OP, R3_TYPE_INST, 0x00000023) - -OP("suxc1", Y_SUXC1_OP, FP_R3_TYPE_INST, 0x4600000d) /* MIPS32 Rev 2 */ - -OP("sw", Y_SW_OP, I2a_TYPE_INST, 0xac000000) -OP("swc1", Y_SWC1_OP, FP_I2a_TYPE_INST, 0xe4000000) -OP("swc2", Y_SWC2_OP, I2a_TYPE_INST, 0xe8000000) -OP("swl", Y_SWL_OP, I2a_TYPE_INST, 0xa8000000) -OP("swr", Y_SWR_OP, I2a_TYPE_INST, 0xb8000000) -OP("swxc1", Y_SWXC1_OP, FP_R3_TYPE_INST, 0x46000008) /* MIPS32 Rev 2 */ - -OP("sync", Y_SYNC_OP, NOARG_TYPE_INST, 0x0000000f) /* MIPS32 */ -OP("synci", Y_SYNCI_OP, I2_TYPE_INST, 0x04140000) /* MIPS32 Rev 2 */ -OP("syscall", Y_SYSCALL_OP, NOARG_TYPE_INST, 0x0000000c) - -OP("teq", Y_TEQ_OP, R2st_TYPE_INST, 0x00000034) /* MIPS32 */ -OP("teqi", Y_TEQI_OP, I1s_TYPE_INST, 0x040c0000) /* MIPS32 */ -OP("tge", Y_TGE_OP, R2st_TYPE_INST, 0x00000030) /* MIPS32 */ -OP("tgei", Y_TGEI_OP, I1s_TYPE_INST, 0x04080000) /* MIPS32 */ -OP("tgeiu", Y_TGEIU_OP, I1s_TYPE_INST, 0x04090000) /* MIPS32 */ -OP("tgeu", Y_TGEU_OP, R2st_TYPE_INST, 0x00000031) /* MIPS32 */ - -OP("tlbp", Y_TLBP_OP, NOARG_TYPE_INST, 0x42000008) -OP("tlbr", Y_TLBR_OP, NOARG_TYPE_INST, 0x42000001) -OP("tlbwi", Y_TLBWI_OP, NOARG_TYPE_INST, 0x42000002) -OP("tlbwr", Y_TLBWR_OP, NOARG_TYPE_INST, 0x42000006) - -OP("tlt", Y_TLT_OP, R2st_TYPE_INST, 0x00000032) /* MIPS32 */ -OP("tlti", Y_TLTI_OP, I1s_TYPE_INST, 0x040a0000) /* MIPS32 */ -OP("tltiu", Y_TLTIU_OP, I1s_TYPE_INST, 0x040b0000) /* MIPS32 */ -OP("tltu", Y_TLTU_OP, R2st_TYPE_INST, 0x00000033) /* MIPS32 */ -OP("tne", Y_TNE_OP, R2st_TYPE_INST, 0x00000036) /* MIPS32 */ -OP("tnei", Y_TNEI_OP, I1s_TYPE_INST, 0x040e0000) /* MIPS32 */ - -OP("trunc.l.d", Y_TRUNC_L_D_OP, FP_R2ds_TYPE_INST, 0x46200009) /* MIPS32 Rev 2 */ -OP("trunc.l.s", Y_TRUNC_L_S_OP, FP_R2ds_TYPE_INST, 0x46000009) /* MIPS32 Rev 2 */ -OP("trunc.w.d", Y_TRUNC_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000d) /* MIPS32 */ -OP("trunc.w.s", Y_TRUNC_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000d) /* MIPS32 */ - -OP("ulh", Y_ULH_POP, PSEUDO_OP, -1) -OP("ulhu", Y_ULHU_POP, PSEUDO_OP, -1) -OP("ulw", Y_ULW_POP, PSEUDO_OP, -1) -OP("ush", Y_USH_POP, PSEUDO_OP, -1) -OP("usw", Y_USW_POP, PSEUDO_OP, -1) - -OP("wrpgpr", Y_WRPGPR_OP, R2td_TYPE_INST, 0x41c00000) /* MIPS32 Rev 2 */ -OP("wsbh", Y_WSBH_OP, R2td_TYPE_INST, 0x7c0000a0) /* MIPS32 Rev 2 */ - -OP("xor", Y_XOR_OP, R3_TYPE_INST, 0x00000026) -OP("xori", Y_XORI_OP, I2_TYPE_INST, 0x38000000) diff --git a/spim-qtbase/CPU/parser.h b/spim-qtbase/CPU/parser.h deleted file mode 100755 index 0e120f8..0000000 --- a/spim-qtbase/CPU/parser.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to parser for instructions and assembler directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -void fix_current_label_address (mem_addr new_addr); -int imm_op_to_op (int opcode); -void initialize_parser (char *file_name); -int op_to_imm_op (int opcode); -void yyerror (char *s); -int yyparse (); - - -/* Exported Variables: */ - -extern bool data_dir; /* => item in data segment */ - -extern bool text_dir; /* => item in text segment */ - -extern bool parse_error_occurred; /* => parse resulted in error */ diff --git a/spim-qtbase/CPU/parser.y b/spim-qtbase/CPU/parser.y deleted file mode 100755 index eceee93..0000000 --- a/spim-qtbase/CPU/parser.y +++ /dev/null @@ -1,2967 +0,0 @@ -/* SPIM S20 MIPS simulator. - Parser for instructions and assembler directives. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -%expect 25 /* Supress warning about 25 shift-reduce conflicts */ - -%start LINE - -%token Y_EOF - -%token Y_NL -%token Y_INT -%token Y_ID -%token Y_REG -%token Y_FP_REG -%token Y_STR -%token Y_FP - -/* MIPS instructions op codes: */ - -%token Y_ABS_D_OP -%token Y_ABS_PS_OP -%token Y_ABS_S_OP -%token Y_ADD_D_OP -%token Y_ADD_OP -%token Y_ADD_PS_OP -%token Y_ADD_S_OP -%token Y_ADDI_OP -%token Y_ADDIU_OP -%token Y_ADDU_OP -%token Y_ALNV_PS_OP -%token Y_AND_OP -%token Y_ANDI_OP -%token Y_BC1F_OP -%token Y_BC1FL_OP -%token Y_BC1T_OP -%token Y_BC1TL_OP -%token Y_BC2F_OP -%token Y_BC2FL_OP -%token Y_BC2T_OP -%token Y_BC2TL_OP -%token Y_BEQ_OP -%token Y_BEQL_OP -%token Y_BGEZ_OP -%token Y_BGEZAL_OP -%token Y_BGEZALL_OP -%token Y_BGEZL_OP -%token Y_BGTZ_OP -%token Y_BGTZL_OP -%token Y_BLEZ_OP -%token Y_BLEZL_OP -%token Y_BLTZ_OP -%token Y_BLTZAL_OP -%token Y_BLTZALL_OP -%token Y_BLTZL_OP -%token Y_BNE_OP -%token Y_BNEL_OP -%token Y_BREAK_OP -%token Y_C_EQ_D_OP -%token Y_C_EQ_PS_OP -%token Y_C_EQ_S_OP -%token Y_C_F_D_OP -%token Y_C_F_PS_OP -%token Y_C_F_S_OP -%token Y_C_LE_D_OP -%token Y_C_LE_PS_OP -%token Y_C_LE_S_OP -%token Y_C_LT_D_OP -%token Y_C_LT_PS_OP -%token Y_C_LT_S_OP -%token Y_C_NGE_D_OP -%token Y_C_NGE_PS_OP -%token Y_C_NGE_S_OP -%token Y_C_NGL_D_OP -%token Y_C_NGL_PS_OP -%token Y_C_NGL_S_OP -%token Y_C_NGLE_D_OP -%token Y_C_NGLE_PS_OP -%token Y_C_NGLE_S_OP -%token Y_C_NGT_D_OP -%token Y_C_NGT_PS_OP -%token Y_C_NGT_S_OP -%token Y_C_OLE_D_OP -%token Y_C_OLE_PS_OP -%token Y_C_OLE_S_OP -%token Y_C_OLT_D_OP -%token Y_C_OLT_PS_OP -%token Y_C_OLT_S_OP -%token Y_C_SEQ_D_OP -%token Y_C_SEQ_PS_OP -%token Y_C_SEQ_S_OP -%token Y_C_SF_D_OP -%token Y_C_SF_PS_OP -%token Y_C_SF_S_OP -%token Y_C_UEQ_D_OP -%token Y_C_UEQ_PS_OP -%token Y_C_UEQ_S_OP -%token Y_C_ULE_D_OP -%token Y_C_ULE_PS_OP -%token Y_C_ULE_S_OP -%token Y_C_ULT_D_OP -%token Y_C_ULT_PS_OP -%token Y_C_ULT_S_OP -%token Y_C_UN_D_OP -%token Y_C_UN_PS_OP -%token Y_C_UN_S_OP -%token Y_CACHE_OP -%token Y_CEIL_L_D_OP -%token Y_CEIL_L_S_OP -%token Y_CEIL_W_D_OP -%token Y_CEIL_W_S_OP -%token Y_CFC0_OP -%token Y_CFC1_OP -%token Y_CFC2_OP -%token Y_CLO_OP -%token Y_CLZ_OP -%token Y_COP2_OP -%token Y_CTC0_OP -%token Y_CTC1_OP -%token Y_CTC2_OP -%token Y_CVT_D_L_OP -%token Y_CVT_D_S_OP -%token Y_CVT_D_W_OP -%token Y_CVT_L_D_OP -%token Y_CVT_L_S_OP -%token Y_CVT_PS_S_OP -%token Y_CVT_S_D_OP -%token Y_CVT_S_L_OP -%token Y_CVT_S_PL_OP -%token Y_CVT_S_PU_OP -%token Y_CVT_S_W_OP -%token Y_CVT_W_D_OP -%token Y_CVT_W_S_OP -%token Y_DERET_OP -%token Y_DI_OP -%token Y_DIV_D_OP -%token Y_DIV_OP -%token Y_DIV_S_OP -%token Y_DIVU_OP -%token Y_EHB_OP -%token Y_EI_OP -%token Y_ERET_OP -%token Y_EXT_OP -%token Y_FLOOR_L_D_OP -%token Y_FLOOR_L_S_OP -%token Y_FLOOR_W_D_OP -%token Y_FLOOR_W_S_OP -%token Y_INS_OP -%token Y_J_OP -%token Y_JAL_OP -%token Y_JALR_HB_OP -%token Y_JALR_OP -%token Y_JR_HB_OP -%token Y_JR_OP -%token Y_LB_OP -%token Y_LBU_OP -%token Y_LDC1_OP -%token Y_LDC2_OP -%token Y_LDXC1_OP -%token Y_LH_OP -%token Y_LHU_OP -%token Y_LL_OP -%token Y_LUI_OP -%token Y_LUXC1_OP -%token Y_LW_OP -%token Y_LWC1_OP -%token Y_LWC2_OP -%token Y_LWL_OP -%token Y_LWR_OP -%token Y_LWXC1_OP -%token Y_MADD_D_OP -%token Y_MADD_OP -%token Y_MADD_PS_OP -%token Y_MADD_S_OP -%token Y_MADDU_OP -%token Y_MFC0_OP -%token Y_MFC1_OP -%token Y_MFC2_OP -%token Y_MFHC1_OP -%token Y_MFHC2_OP -%token Y_MFHI_OP -%token Y_MFLO_OP -%token Y_MOV_D_OP -%token Y_MOV_PS_OP -%token Y_MOV_S_OP -%token Y_MOVF_D_OP -%token Y_MOVF_OP -%token Y_MOVF_PS_OP -%token Y_MOVF_S_OP -%token Y_MOVN_D_OP -%token Y_MOVN_OP -%token Y_MOVN_PS_OP -%token Y_MOVN_S_OP -%token Y_MOVT_D_OP -%token Y_MOVT_OP -%token Y_MOVT_PS_OP -%token Y_MOVT_S_OP -%token Y_MOVZ_D_OP -%token Y_MOVZ_OP -%token Y_MOVZ_PS_OP -%token Y_MOVZ_S_OP -%token Y_MSUB_D_OP -%token Y_MSUB_OP -%token Y_MSUB_PS_OP -%token Y_MSUB_S_OP -%token Y_MSUBU_OP -%token Y_MTC0_OP -%token Y_MTC1_OP -%token Y_MTC2_OP -%token Y_MTHC1_OP -%token Y_MTHC2_OP -%token Y_MTHI_OP -%token Y_MTLO_OP -%token Y_MUL_D_OP -%token Y_MUL_PS_OP -%token Y_MUL_S_OP -%token Y_MUL_OP -%token Y_MULT_OP -%token Y_MULTU_OP -%token Y_NEG_D_OP -%token Y_NEG_PS_OP -%token Y_NEG_S_OP -%token Y_NMADD_D_OP -%token Y_NMADD_PS_OP -%token Y_NMADD_S_OP -%token Y_NMSUB_D_OP -%token Y_NMSUB_PS_OP -%token Y_NMSUB_S_OP -%token Y_NOR_OP -%token Y_OR_OP -%token Y_ORI_OP -%token Y_PFW_OP -%token Y_PLL_PS_OP -%token Y_PLU_PS_OP -%token Y_PREF_OP -%token Y_PREFX_OP -%token Y_PUL_PS_OP -%token Y_PUU_PS_OP -%token Y_RDHWR_OP -%token Y_RDPGPR_OP -%token Y_RECIP_D_OP -%token Y_RECIP_S_OP -%token Y_RFE_OP -%token Y_ROTR_OP -%token Y_ROTRV_OP -%token Y_ROUND_L_D_OP -%token Y_ROUND_L_S_OP -%token Y_ROUND_W_D_OP -%token Y_ROUND_W_S_OP -%token Y_RSQRT_D_OP -%token Y_RSQRT_S_OP -%token Y_SB_OP -%token Y_SC_OP -%token Y_SDBBP_OP -%token Y_SDC1_OP -%token Y_SDC2_OP -%token Y_SDXC1_OP -%token Y_SEB_OP -%token Y_SEH_OP -%token Y_SH_OP -%token Y_SLL_OP -%token Y_SLLV_OP -%token Y_SLT_OP -%token Y_SLTI_OP -%token Y_SLTIU_OP -%token Y_SLTU_OP -%token Y_SQRT_D_OP -%token Y_SQRT_S_OP -%token Y_SRA_OP -%token Y_SRAV_OP -%token Y_SRL_OP -%token Y_SRLV_OP -%token Y_SSNOP_OP -%token Y_SUB_D_OP -%token Y_SUB_OP -%token Y_SUB_PS_OP -%token Y_SUB_S_OP -%token Y_SUBU_OP -%token Y_SUXC1_OP -%token Y_SW_OP -%token Y_SWC1_OP -%token Y_SWC2_OP -%token Y_SWL_OP -%token Y_SWR_OP -%token Y_SWXC1_OP -%token Y_SYNC_OP -%token Y_SYNCI_OP -%token Y_SYSCALL_OP -%token Y_TEQ_OP -%token Y_TEQI_OP -%token Y_TGE_OP -%token Y_TGEI_OP -%token Y_TGEIU_OP -%token Y_TGEU_OP -%token Y_TLBP_OP -%token Y_TLBR_OP -%token Y_TLBWI_OP -%token Y_TLBWR_OP -%token Y_TLT_OP -%token Y_TLTI_OP -%token Y_TLTIU_OP -%token Y_TLTU_OP -%token Y_TNE_OP -%token Y_TNEI_OP -%token Y_TRUNC_L_D_OP -%token Y_TRUNC_L_S_OP -%token Y_TRUNC_W_D_OP -%token Y_TRUNC_W_S_OP -%token Y_WRPGPR_OP -%token Y_WSBH_OP -%token Y_XOR_OP -%token Y_XORI_OP - - -/* Assembler pseudo operations op codes: */ - -%token Y_ABS_POP -%token Y_B_POP -%token Y_BAL_POP -%token Y_BEQZ_POP -%token Y_BGE_POP -%token Y_BGEU_POP -%token Y_BGT_POP -%token Y_BGTU_POP -%token Y_BLE_POP -%token Y_BLEU_POP -%token Y_BLT_POP -%token Y_BLTU_POP -%token Y_BNEZ_POP -%token Y_LA_POP -%token Y_LD_POP -%token Y_L_D_POP -%token Y_L_S_POP -%token Y_LI_D_POP -%token Y_LI_POP -%token Y_LI_S_POP -%token Y_MFC1_D_POP -%token Y_MOVE_POP -%token Y_MTC1_D_POP -%token Y_MULO_POP -%token Y_MULOU_POP -%token Y_NEG_POP -%token Y_NEGU_POP -%token Y_NOP_POP -%token Y_NOT_POP -%token Y_REM_POP -%token Y_REMU_POP -%token Y_ROL_POP -%token Y_ROR_POP -%token Y_S_D_POP -%token Y_S_S_POP -%token Y_SD_POP -%token Y_SEQ_POP -%token Y_SGE_POP -%token Y_SGEU_POP -%token Y_SGT_POP -%token Y_SGTU_POP -%token Y_SLE_POP -%token Y_SLEU_POP -%token Y_SNE_POP -%token Y_ULH_POP -%token Y_ULHU_POP -%token Y_ULW_POP -%token Y_USH_POP -%token Y_USW_POP - -/* Assembler directives: */ - -%token Y_ALIAS_DIR -%token Y_ALIGN_DIR -%token Y_ASCII_DIR -%token Y_ASCIIZ_DIR -%token Y_ASM0_DIR -%token Y_BGNB_DIR -%token Y_BYTE_DIR -%token Y_COMM_DIR -%token Y_DATA_DIR -%token Y_DOUBLE_DIR -%token Y_END_DIR -%token Y_ENDB_DIR -%token Y_ENDR_DIR -%token Y_ENT_DIR -%token Y_ERR_DIR -%token Y_EXTERN_DIR -%token Y_FILE_DIR -%token Y_FLOAT_DIR -%token Y_FMASK_DIR -%token Y_FRAME_DIR -%token Y_GLOBAL_DIR -%token Y_HALF_DIR -%token Y_K_DATA_DIR -%token Y_K_TEXT_DIR -%token Y_LABEL_DIR -%token Y_LCOMM_DIR -%token Y_LIVEREG_DIR -%token Y_LOC_DIR -%token Y_MASK_DIR -%token Y_NOALIAS_DIR -%token Y_OPTIONS_DIR -%token Y_RDATA_DIR -%token Y_REPEAT_DIR -%token Y_SDATA_DIR -%token Y_SET_DIR -%token Y_SPACE_DIR -%token Y_STRUCT_DIR -%token Y_TEXT_DIR -%token Y_VERSTAMP_DIR -%token Y_VREG_DIR -%token Y_WORD_DIR - -%{ -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "data.h" -#include "scanner.h" -#include "parser.h" - - -/* return (0) */ -#define LINE_PARSE_DONE YYACCEPT - -/* return (1) */ -#define FILE_PARSE_DONE YYABORT - -typedef struct ll -{ - label *head; - struct ll *tail; -} label_list; - - -/* Exported Variables: */ - -bool data_dir; /* => item in data segment */ - -bool text_dir; /* => item in text segment */ - -bool parse_error_occurred; /* => parse resulted in error */ - - -/* Local functions: */ - -static imm_expr *branch_offset (int n_inst); -static int cc_to_rt (int cc, int nd, int tf); -static void check_imm_range (imm_expr*, int32, int32); -static void check_uimm_range (imm_expr*, uint32, uint32); -static void clear_labels (); -static label_list *cons_label (label *head, label_list *tail); -static void div_inst (int op, int rd, int rs, int rt, int const_divisor); -static void mips32_r2_inst (); -static void mult_inst (int op, int rd, int rs, int rt); -static void nop_inst (); -static void set_eq_inst (int op, int rd, int rs, int rt); -static void set_ge_inst (int op, int rd, int rs, int rt); -static void set_gt_inst (int op, int rd, int rs, int rt); -static void set_le_inst (int op, int rd, int rs, int rt); -static void store_word_data (int value); -static void trap_inst (); -static void yywarn (char*); - - -/* Local variables: */ - -static bool null_term; /* => string terminate by \0 */ - -static void (*store_op) (int); /* Function to store items in an EXPR_LST */ -static void (*store_fp_op) (double*); /* Ditto FP_EXPR_LST */ - -static label_list *this_line_labels = NULL; /* List of label for curent line */ - -static bool noat_flag = 0; /* => program can use $1 */ - -static char *input_file_name; /* Name of file being parsed */ - -%} - - - -%% - -LINE: {parse_error_occurred = false; scanner_start_line (); } LBL_CMD ; - -LBL_CMD: OPT_LBL CMD - | CMD - ; - - -OPT_LBL: ID ':' { - /* Call outside of cons_label, since an error sets that variable to NULL. */ - label* l = record_label ((char*)$1.p, - text_dir ? current_text_pc () : current_data_pc (), - 0); - this_line_labels = cons_label (l, this_line_labels); - free ((char*)$1.p); - } - - | ID '=' EXPR - { - label *l = record_label ((char*)$1.p, (mem_addr)$3.i, 1); - free ((char*)$1.p); - - l->const_flag = 1; - clear_labels (); - } - ; - - -CMD: ASM_CODE - { - clear_labels (); - } - TERM - - | ASM_DIRECTIVE - { - clear_labels (); - } - TERM - - | TERM - ; - - -TERM: Y_NL - { - LINE_PARSE_DONE; - } - - | Y_EOF - { - clear_labels (); - FILE_PARSE_DONE; - } - ; - - - -ASM_CODE: LOAD_OPS DEST ADDRESS - { - i_type_inst ($1.i == Y_LD_POP ? Y_LW_OP : $1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - if ($1.i == Y_LD_POP) - i_type_inst_free (Y_LW_OP, - $2.i + 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 4)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADC_OPS COP_REG ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADFP_OPS F_SRC1 ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADI_OPS DEST UIMM16 - { - i_type_inst_free ($1.i, $2.i, 0, (imm_expr *)$3.p); - } - - - | Y_LA_POP DEST ADDRESS - { - if (addr_expr_reg ((addr_expr *)$3.p)) - i_type_inst (Y_ADDI_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - else - i_type_inst (Y_ORI_OP, $2.i, 0, - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_LI_POP DEST IMM32 - { - i_type_inst_free (Y_ORI_OP, $2.i, 0, (imm_expr *)$3.p); - } - - - | Y_LI_D_POP F_DEST Y_FP - { - int *x = (int *) $3.p; - - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*x)); - r_co_type_inst (Y_MTC1_OP, 0, $2.i, 1); - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*(x+1))); - r_co_type_inst (Y_MTC1_OP, 0, $2.i + 1, 1); - } - - - | Y_LI_S_POP F_DEST Y_FP - { - float x = (float) *((double *) $3.p); - int *y = (int *) &x; - - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*y)); - r_co_type_inst (Y_MTC1_OP, 0, $2.i, 1); - } - - - | Y_ULW_POP DEST ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (Y_LWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_LWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); -#else - i_type_inst_free (Y_LWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); - i_type_inst (Y_LWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | ULOADH_POPS DEST ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (($1.i == Y_ULH_POP ? Y_LB_OP : Y_LBU_OP), - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_LBU_OP, 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); -#else - i_type_inst_free (($1.i == Y_ULH_POP ? Y_LB_OP : Y_LBU_OP), - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); - i_type_inst (Y_LBU_OP, 1, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - r_sh_type_inst (Y_SLL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | LOADFP_INDEX_OPS F_DEST ADDRESS - { - mips32_r2_inst (); - } - - - | STORE_OPS SRC1 ADDRESS - { - i_type_inst ($1.i == Y_SD_POP ? Y_SW_OP : $1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - if ($1.i == Y_SD_POP) - i_type_inst_free (Y_SW_OP, $2.i + 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 4)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREC_OPS COP_REG ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_USW_POP SRC1 ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (Y_SWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_SWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); -#else - i_type_inst_free (Y_SWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); - i_type_inst (Y_SWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_USH_POP SRC1 ADDRESS - { - i_type_inst (Y_SB_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - - /* ROL SRC, SRC, 8 */ - r_sh_type_inst (Y_SLL_OP, 1, $2.i, 24); - r_sh_type_inst (Y_SRL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - - i_type_inst_free (Y_SB_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); - /* ROR SRC, SRC, 8 */ - r_sh_type_inst (Y_SRL_OP, 1, $2.i, 24); - r_sh_type_inst (Y_SLL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREFP_OPS F_SRC1 ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREFP_INDEX_OPS F_DEST ADDRESS - { - mips32_r2_inst (); - } - - - | SYS_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | PREFETCH_OPS ADDRESS - { - mips32_r2_inst (); - } - - - | CACHE_OPS Y_INT ADDRESS - { - i_type_inst_free ($1.i, $2.i, 0, (imm_expr *)$3.p); - } - - - | TLB_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | Y_SYNC_OP - { - r_type_inst ($1.i, 0, 0, 0); - } - - | Y_SYNC_OP Y_INT - { - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | Y_BREAK_OP Y_INT - { - if ($2.i == 1) - yyerror ("Breakpoint 1 is reserved for debugger"); - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | Y_NOP_POP - { - nop_inst (); - } - - - | Y_SSNOP_OP - { - r_sh_type_inst (Y_SLL_OP, 0, 0, 1); /* SLL r0 r0 1 */ - } - - - | Y_ABS_POP DEST SRC1 - { - if ($2.i != $3.i) - r_type_inst (Y_ADDU_OP, $2.i, 0, $3.i); - - i_type_inst_free (Y_BGEZ_OP, 0, $3.i, branch_offset (3)); - nop_inst(); - r_type_inst (Y_SUB_OP, $2.i, 0, $3.i); - } - - - | Y_NEG_POP DEST SRC1 - { - r_type_inst (Y_SUB_OP, $2.i, 0, $3.i); - } - - - | Y_NEGU_POP DEST SRC1 - { - r_type_inst (Y_SUBU_OP, $2.i, 0, $3.i); - } - - - | Y_NOT_POP DEST SRC1 - { - r_type_inst (Y_NOR_OP, $2.i, $3.i, 0); - } - - - | Y_MOVE_POP DEST SRC1 - { - r_type_inst (Y_ADDU_OP, $2.i, 0, $3.i); - } - - - | NULLARY_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | NULLARY_OPS_REV2 - { - mips32_r2_inst (); - } - - - | COUNT_LEADING_OPS DEST SRC1 - { - /* RT must be equal to RD */ - r_type_inst ($1.i, $2.i, $3.i, $2.i); - } - - - | UNARY_OPS_REV2 DEST - { - mips32_r2_inst (); - } - - - | BINARYI_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | BINARYI_OPS DEST SRC1 IMM32 - { - i_type_inst_free (op_to_imm_op ($1.i), $2.i, $3.i, - (imm_expr *)$4.p); - } - - | BINARYI_OPS DEST IMM32 - { - i_type_inst_free (op_to_imm_op ($1.i), $2.i, $2.i, - (imm_expr *)$3.p); - } - - - | BINARYIR_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $4.i, $3.i); - } - - | BINARYIR_OPS DEST SRC1 Y_INT - { - r_sh_type_inst (op_to_imm_op ($1.i), $2.i, $3.i, $4.i); - } - - | BINARYIR_OPS DEST Y_INT - { - r_sh_type_inst (op_to_imm_op ($1.i), $2.i, $2.i, $3.i); - } - - - | BINARY_ARITHI_OPS DEST SRC1 IMM16 - { - i_type_inst_free ($1.i, $2.i, $3.i, (imm_expr *)$4.p); - } - - | BINARY_ARITHI_OPS DEST IMM16 - { - i_type_inst_free ($1.i, $2.i, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_LOGICALI_OPS DEST SRC1 UIMM16 - { - i_type_inst_free ($1.i, $2.i, $3.i, (imm_expr *)$4.p); - } - - | BINARY_LOGICALI_OPS DEST UIMM16 - { - i_type_inst_free ($1.i, $2.i, $2.i, (imm_expr *)$3.p); - } - - - | SHIFT_OPS DEST SRC1 Y_INT - { - if (($4.i < 0) || (31 < $4.i)) - yywarn ("Shift distance can only be in the range 0..31"); - r_sh_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SHIFT_OPS DEST SRC1 SRC2 - { - r_type_inst (imm_op_to_op ($1.i), $2.i, $4.i, $3.i); - } - - - | SHIFT_OPS_REV2 DEST SRC1 Y_INT - { - mips32_r2_inst (); - } - - | SHIFTV_OPS_REV2 DEST SRC1 SRC2 - { - mips32_r2_inst (); - } - - - | BINARY_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | BINARY_OPS DEST SRC1 IMM32 - { - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - r_type_inst ($1.i, - $2.i, - $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - } - free ((imm_expr *)$4.p); - } - - | BINARY_OPS DEST IMM32 - { - check_uimm_range ((imm_expr *)$3.p, UIMM_MIN, UIMM_MAX); - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (!is_zero_imm ((imm_expr *)$3.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - r_type_inst ($1.i, - $2.i, - $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1)); - } - free ((imm_expr *)$3.p); - } - - - | BINARY_OPS_REV2 DEST SRC1 - { - mips32_r2_inst (); - } - - - | SUB_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SUB_OPS DEST SRC1 IMM32 - { - int val = eval_imm_expr ((imm_expr *)$4.p); - - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - i_type_inst ($1.i == Y_SUB_OP ? Y_ADDI_OP - : $1.i == Y_SUBU_OP ? Y_ADDIU_OP - : (fatal_error ("Bad SUB_OP\n"), 0), - $2.i, - $3.i, - make_imm_expr (-val, NULL, false)); - free ((imm_expr *)$4.p); - } - - | SUB_OPS DEST IMM32 - { - int val = eval_imm_expr ((imm_expr *)$3.p); - - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - i_type_inst ($1.i == Y_SUB_OP ? Y_ADDI_OP - : $1.i == Y_SUBU_OP ? Y_ADDIU_OP - : (fatal_error ("Bad SUB_OP\n"), 0), - $2.i, - $2.i, - make_imm_expr (-val, NULL, false)); - free ((imm_expr *)$3.p); - } - - - | DIV_POPS DEST SRC1 - { - /* The hardware divide operation (ignore 1st arg) */ - if ($1.i != Y_DIV_OP && $1.i != Y_DIVU_OP) - yyerror ("REM requires 3 arguments"); - else - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - | DIV_POPS DEST SRC1 SRC2 - { - /* Pseudo divide operations */ - div_inst ($1.i, $2.i, $3.i, $4.i, 0); - } - - | DIV_POPS DEST SRC1 IMM32 - { - if (is_zero_imm ((imm_expr *)$4.p)) - yyerror ("Divide by zero"); - else - { - /* Use $at */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - div_inst ($1.i, $2.i, $3.i, 1, 1); - } - } - - - | MUL_POPS DEST SRC1 SRC2 - { - mult_inst ($1.i, $2.i, $3.i, $4.i); - } - - | MUL_POPS DEST SRC1 IMM32 - { - if (is_zero_imm ((imm_expr *)$4.p)) - /* Optimize: n * 0 == 0 */ - i_type_inst_free (Y_ORI_OP, $2.i, 0, (imm_expr *)$4.p); - else - { - /* Use $at */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - mult_inst ($1.i, $2.i, $3.i, 1); - } - } - - - | MULT_OPS SRC1 SRC2 - { - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - - | MULT_OPS3 DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | MULT_OPS3 DEST SRC1 IMM32 - { - /* Special case, for backward compatibility with pseudo-op - MULT instruction */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); /* Use $at */ - r_type_inst ($1.i, $2.i, $3.i, 1); - } - - - | Y_ROR_POP DEST SRC1 SRC2 - { - r_type_inst (Y_SUBU_OP, 1, 0, $4.i); - r_type_inst (Y_SLLV_OP, 1, 1, $3.i); - r_type_inst (Y_SRLV_OP, $2.i, $4.i, $3.i); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - } - - - | Y_ROL_POP DEST SRC1 SRC2 - { - r_type_inst (Y_SUBU_OP, 1, 0, $4.i); - r_type_inst (Y_SRLV_OP, 1, 1, $3.i); - r_type_inst (Y_SLLV_OP, $2.i, $4.i, $3.i); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - } - - - | Y_ROR_POP DEST SRC1 IMM32 - { - long dist = eval_imm_expr ((imm_expr *)$4.p); - - check_imm_range ((imm_expr *)$4.p, 0, 31); - r_sh_type_inst (Y_SLL_OP, 1, $3.i, -dist); - r_sh_type_inst (Y_SRL_OP, $2.i, $3.i, dist); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free ((imm_expr *)$4.p); - } - - - | Y_ROL_POP DEST SRC1 IMM32 - { - long dist = eval_imm_expr ((imm_expr *)$4.p); - - check_imm_range ((imm_expr *)$4.p, 0, 31); - r_sh_type_inst (Y_SRL_OP, 1, $3.i, -dist); - r_sh_type_inst (Y_SLL_OP, $2.i, $3.i, dist); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free ((imm_expr *)$4.p); - } - - - | BF_OPS_REV2 F_DEST F_SRC2 Y_INT Y_INT - { - mips32_r2_inst (); - } - - - | SET_LE_POPS DEST SRC1 SRC2 - { - set_le_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_LE_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_le_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | SET_GT_POPS DEST SRC1 SRC2 - { - set_gt_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_GT_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_gt_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - - | SET_GE_POPS DEST SRC1 SRC2 - { - set_ge_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_GE_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_ge_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | SET_EQ_POPS DEST SRC1 SRC2 - { - set_eq_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_EQ_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_eq_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | BR_COP_OPS LABEL - { - /* RS and RT fields contain information on test */ - int nd = opcode_is_nullified_branch ($1.i) ? 1 : 0; - int tf = opcode_is_true_branch ($1.i) ? 1 : 0; - i_type_inst_free ($1.i, - cc_to_rt (0, nd, tf), - BIN_RS ($1.i), - (imm_expr *)$2.p); - } - - | BR_COP_OPS CC_REG LABEL - { - /* RS and RT fields contain information on test */ - int nd = opcode_is_nullified_branch ($1.i) ? 1 : 0; - int tf = opcode_is_true_branch ($1.i) ? 1 : 0; - i_type_inst_free ($1.i, - cc_to_rt ($2.i, nd, tf), - BIN_RS ($1.i), - (imm_expr *)$3.p); - } - - - | UNARY_BR_OPS SRC1 LABEL - { - i_type_inst_free ($1.i, 0, $2.i, (imm_expr *)$3.p); - } - - - | UNARY_BR_POPS SRC1 LABEL - { - i_type_inst_free ($1.i == Y_BEQZ_POP ? Y_BEQ_OP : Y_BNE_OP, - 0, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_BR_OPS SRC1 SRC2 LABEL - { - i_type_inst_free ($1.i, $3.i, $2.i, (imm_expr *)$4.p); - } - - | BINARY_BR_OPS SRC1 BR_IMM32 LABEL - { - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (is_zero_imm ((imm_expr *)$3.p)) - i_type_inst ($1.i, $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1), - (imm_expr *)$4.p); - else - { - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst ($1.i, $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1), - (imm_expr *)$4.p); - } - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | BR_GT_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BGT_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $3.i, $2.i); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_GT_POPS SRC1 BR_IMM32 LABEL - { - if ($1.i == Y_BGT_POP) - { - /* Use $at */ - i_type_inst_free (Y_SLTI_OP, 1, $2.i, - incr_expr_offset ((imm_expr *)$3.p, 1)); - i_type_inst (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - else - { - /* Use $at */ - /* Can't add 1 to immediate since 0xffffffff+1 = 0 < 1 */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst_free (Y_BEQ_OP, $2.i, 1, branch_offset (3)); - r_type_inst (Y_SLTU_OP, 1, $2.i, 1); - i_type_inst (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | BR_GE_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BGE_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $2.i, $3.i); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_GE_POPS SRC1 BR_IMM32 LABEL - { - i_type_inst ($1.i == Y_BGE_POP ? Y_SLTI_OP : Y_SLTIU_OP, - 1, $2.i, (imm_expr *)$3.p); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - free ((imm_expr *)$3.p); - } - - - | BR_LT_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BLT_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $2.i, $3.i); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_LT_POPS SRC1 BR_IMM32 LABEL - { - i_type_inst ($1.i == Y_BLT_POP ? Y_SLTI_OP : Y_SLTIU_OP, - 1, $2.i, (imm_expr *)$3.p); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - free ((imm_expr *)$3.p); - } - - - | BR_LE_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BLE_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $3.i, $2.i); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_LE_POPS SRC1 BR_IMM32 LABEL - { - if ($1.i == Y_BLE_POP) - { - /* Use $at */ - i_type_inst_free (Y_SLTI_OP, 1, $2.i, - incr_expr_offset ((imm_expr *)$3.p, 1)); - i_type_inst (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - else - { - /* Use $at */ - /* Can't add 1 to immediate since 0xffffffff+1 = 0 < 1 */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst (Y_BEQ_OP, $2.i, 1, (imm_expr *)$4.p); - r_type_inst (Y_SLTU_OP, 1, $2.i, 1); - i_type_inst (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | J_OPS LABEL - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - j_type_inst (Y_J_OP, (imm_expr *)$2.p); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - j_type_inst (Y_JAL_OP, (imm_expr *)$2.p); - free ((imm_expr *)$2.p); - } - - | J_OPS SRC1 - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - r_type_inst (Y_JR_OP, 0, $2.i, 0); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - r_type_inst (Y_JALR_OP, 31, $2.i, 0); - } - - | J_OPS DEST SRC1 - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - r_type_inst (Y_JR_OP, 0, $3.i, 0); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - r_type_inst (Y_JALR_OP, $2.i, $3.i, 0); - } - - - | B_OPS LABEL - { - i_type_inst_free (($1.i == Y_BAL_POP ? Y_BGEZAL_OP : Y_BGEZ_OP), - 0, 0, (imm_expr *)$2.p); - } - - - | BINARYI_TRAP_OPS SRC1 IMM16 - { - i_type_inst_free ($1.i, 0, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_TRAP_OPS SRC1 SRC2 - { - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - - | FP_MOVE_OPS F_DEST F_SRC1 - { - r_co_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_MOVE_OPS_REV2 F_DEST F_SRC1 - { - mips32_r2_inst (); - } - - - | MOVEC_OPS DEST SRC1 REG - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | MOVECC_OPS DEST SRC1 Y_INT - { - r_type_inst ($1.i, - $2.i, - $3.i, - (($4.i & 0x7) << 2)); - } - - - | FP_MOVEC_OPS F_DEST F_SRC1 REG - { - r_co_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | FP_MOVEC_OPS_REV2 F_DEST F_SRC1 REG - { - mips32_r2_inst (); - } - - - | FP_MOVECC_OPS F_DEST F_SRC1 - { - r_co_type_inst ($1.i, $2.i, $3.i, cc_to_rt (0, 0, 0)); - } - - - | FP_MOVECC_OPS F_DEST F_SRC1 CC_REG - { - r_co_type_inst ($1.i, $2.i, $3.i, cc_to_rt ($4.i, 0, 0)); - } - - - | FP_MOVECC_OPS_REV2 F_DEST F_SRC1 CC_REG - { - mips32_r2_inst (); - } - - - | MOVE_FROM_HILO_OPS REG - { - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | MOVE_TO_HILO_OPS REG - { - r_type_inst ($1.i, 0, $2.i, 0); - } - - - - | MOVE_COP_OPS REG COP_REG - { - if ($1.i == Y_MFC1_D_POP) - { - r_co_type_inst (Y_MFC1_OP, 0, $3.i, $2.i); - r_co_type_inst (Y_MFC1_OP, 0, $3.i + 1, $2.i + 1); - } - else if ($1.i == Y_MTC1_D_POP) - { - r_co_type_inst (Y_MTC1_OP, 0, $3.i, $2.i); - r_co_type_inst (Y_MTC1_OP, 0, $3.i + 1, $2.i + 1); - } - else - r_co_type_inst ($1.i, 0, $3.i, $2.i); - } - - - | MOVE_COP_OPS_REV2 REG COP_REG - { - mips32_r2_inst (); - } - - - | CTL_COP_OPS REG COP_REG - { - r_co_type_inst ($1.i, 0, $3.i, $2.i); - } - - - | FP_UNARY_OPS F_DEST F_SRC2 - { - r_co_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_UNARY_OPS_REV2 F_DEST F_SRC2 - { - mips32_r2_inst (); - } - - - | FP_BINARY_OPS F_DEST F_SRC1 F_SRC2 - { - r_co_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | FP_BINARY_OPS_REV2 F_DEST F_SRC1 F_SRC2 - { - mips32_r2_inst (); - } - - - | FP_TERNARY_OPS_REV2 F_DEST F_SRC1 F_SRC2 FP_REGISTER - { - mips32_r2_inst (); - } - - - | FP_CMP_OPS F_SRC1 F_SRC2 - { - r_cond_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_CMP_OPS CC_REG F_SRC1 F_SRC2 - { - r_cond_type_inst ($1.i, $3.i, $4.i, $2.i); - } - - - | FP_CMP_OPS_REV2 F_SRC1 F_SRC2 - { - mips32_r2_inst (); - } - - - | Y_COP2_OP IMM32 - { - i_type_inst_free ($1.i, 0, 0, (imm_expr *)$2.p); - } - ; - - - -LOAD_OPS: Y_LB_OP - | Y_LBU_OP - | Y_LH_OP - | Y_LHU_OP - | Y_LL_OP - | Y_LW_OP - | Y_LWL_OP - | Y_LWR_OP - | Y_PFW_OP - | Y_LD_POP - ; - -LOADI_OPS: Y_LUI_OP - ; - -ULOADH_POPS: Y_ULH_POP - | Y_ULHU_POP - ; - -LOADC_OPS: Y_LDC2_OP - | Y_LWC2_OP - ; - -LOADFP_OPS: Y_LDC1_OP - | Y_LWC1_OP - | Y_L_D_POP { $$.i = Y_LDC1_OP; } - | Y_L_S_POP { $$.i = Y_LWC1_OP; } - ; - -LOADFP_INDEX_OPS: Y_LDXC1_OP - | Y_LUXC1_OP - | Y_LWXC1_OP - ; - -STORE_OPS: Y_SB_OP - | Y_SC_OP - | Y_SH_OP - | Y_SW_OP - | Y_SWL_OP - | Y_SWR_OP - | Y_SD_POP - ; - -STOREC_OPS: Y_SWC2_OP - | Y_SDC2_OP - | Y_S_D_POP { $$.i = Y_SDC1_OP; } - | Y_S_S_POP { $$.i = Y_SWC1_OP; } - ; - -STOREFP_OPS: Y_SWC1_OP - | Y_SDC1_OP - ; - -STOREFP_INDEX_OPS: Y_SDXC1_OP - | Y_SUXC1_OP - | Y_SWXC1_OP - ; - -SYS_OPS: Y_RFE_OP - { -#ifdef MIPS1 - yywarn ("RFE should only be used when SPIM is compiled as a MIPS-I processor"); -#endif - } - | Y_SYSCALL_OP - ; - -PREFETCH_OPS: Y_PREFX_OP - | Y_SYNCI_OP - ; - -CACHE_OPS: Y_CACHE_OP - | Y_PREF_OP - ; - -TLB_OPS: Y_TLBP_OP - | Y_TLBR_OP - | Y_TLBWI_OP - | Y_TLBWR_OP - ; - -NULLARY_OPS: Y_ERET_OP - { -#ifdef MIPS1 - yywarn ("ERET should only be used when SPIM is compiled as a MIPS32 processor"); -#endif - } - ; - -NULLARY_OPS_REV2: Y_DERET_OP - | Y_EHB_OP - | Y_SDBBP_OP - ; - -COUNT_LEADING_OPS: Y_CLO_OP - | Y_CLZ_OP - ; - -UNARY_OPS_REV2: Y_DI_OP - | Y_EI_OP - ; - -/* These binary operations have immediate analogues. */ - -BINARYI_OPS: Y_ADD_OP - | Y_ADDU_OP - | Y_AND_OP - | Y_XOR_OP - | Y_OR_OP - | Y_SLT_OP - | Y_SLTU_OP - ; - -BINARYIR_OPS: Y_SLLV_OP - | Y_SRAV_OP - | Y_SRLV_OP - ; - -BINARY_ARITHI_OPS: Y_ADDI_OP - | Y_ADDIU_OP - | Y_SLTI_OP - | Y_SLTIU_OP - ; - -BINARY_LOGICALI_OPS: Y_ANDI_OP - | Y_ORI_OP - | Y_XORI_OP - ; - -SHIFT_OPS: Y_SLL_OP - | Y_SRA_OP - | Y_SRL_OP - ; - -SHIFT_OPS_REV2: Y_ROTR_OP - ; - -SHIFTV_OPS_REV2: Y_ROTRV_OP - ; - - -/* These binary operations do not have immediate analogues. */ - -BINARY_OPS: Y_NOR_OP - ; - -BINARY_OPS_REV2: Y_RDHWR_OP - | Y_RDPGPR_OP - | Y_SEB_OP - | Y_SEH_OP - | Y_WRPGPR_OP - | Y_WSBH_OP - ; - -SUB_OPS: Y_SUB_OP - | Y_SUBU_OP - ; - -DIV_POPS: Y_DIV_OP - | Y_DIVU_OP - | Y_REM_POP - | Y_REMU_POP - ; - -MUL_POPS: Y_MULO_POP - | Y_MULOU_POP - ; - -SET_LE_POPS: Y_SLE_POP - | Y_SLEU_POP - ; - -SET_GT_POPS: Y_SGT_POP - | Y_SGTU_POP - ; - -SET_GE_POPS: Y_SGE_POP - | Y_SGEU_POP - ; - -SET_EQ_POPS: Y_SEQ_POP - | Y_SNE_POP - ; - -MULT_OPS: Y_MULT_OP - | Y_MULTU_OP - | Y_MADD_OP - | Y_MADDU_OP - | Y_MSUB_OP - | Y_MSUBU_OP - ; - -MULT_OPS3: Y_MUL_OP - ; - -BF_OPS_REV2: Y_EXT_OP - | Y_INS_OP - ; - -BR_COP_OPS: Y_BC1F_OP - | Y_BC1FL_OP - | Y_BC1T_OP - | Y_BC1TL_OP - | Y_BC2F_OP - | Y_BC2FL_OP - | Y_BC2T_OP - | Y_BC2TL_OP - ; - -UNARY_BR_OPS: Y_BGEZ_OP - | Y_BGEZL_OP - | Y_BGEZAL_OP - | Y_BGEZALL_OP - | Y_BGTZ_OP - | Y_BGTZL_OP - | Y_BLEZ_OP - | Y_BLEZL_OP - | Y_BLTZ_OP - | Y_BLTZL_OP - | Y_BLTZAL_OP - | Y_BLTZALL_OP - ; - -UNARY_BR_POPS: Y_BEQZ_POP - | Y_BNEZ_POP - ; - -BINARY_BR_OPS: Y_BEQ_OP - | Y_BEQL_OP - | Y_BNE_OP - | Y_BNEL_OP - ; - -BR_GT_POPS: Y_BGT_POP - | Y_BGTU_POP - -BR_GE_POPS: Y_BGE_POP - | Y_BGEU_POP - -BR_LT_POPS: Y_BLT_POP - | Y_BLTU_POP - -BR_LE_POPS: Y_BLE_POP - | Y_BLEU_POP - ; - -J_OPS: Y_J_OP - | Y_JR_OP - | Y_JR_HB_OP { yywarn ("Warning:IPS32 Rev 2 '.HB' extension is not implemented and is ignored"); } - | Y_JAL_OP - | Y_JALR_OP - | Y_JALR_HB_OP { yywarn ("Warning:IPS32 Rev 2 '.HB' extension is not implemented and is ignored"); } - ; - -B_OPS: Y_B_POP - | Y_BAL_POP - ; - - -BINARYI_TRAP_OPS: Y_TEQI_OP - | Y_TGEI_OP - | Y_TGEIU_OP - | Y_TLTI_OP - | Y_TLTIU_OP - | Y_TNEI_OP - ; - -BINARY_TRAP_OPS: Y_TEQ_OP - | Y_TGE_OP - | Y_TGEU_OP - | Y_TLT_OP - | Y_TLTU_OP - | Y_TNE_OP - ; - - -MOVE_FROM_HILO_OPS: Y_MFHI_OP - | Y_MFLO_OP - ; - -MOVE_TO_HILO_OPS: Y_MTHI_OP - | Y_MTLO_OP - ; - -MOVEC_OPS: Y_MOVN_OP - | Y_MOVZ_OP - ; - -MOVE_COP_OPS: Y_MFC0_OP - | Y_MFC1_OP - | Y_MFC1_D_POP - | Y_MFC2_OP - | Y_MTC0_OP - | Y_MTC1_OP - | Y_MTC1_D_POP - | Y_MTC2_OP - ; - -MOVE_COP_OPS_REV2: Y_MFHC1_OP - | Y_MFHC2_OP - | Y_MTHC1_OP - | Y_MTHC2_OP - ; - -CTL_COP_OPS: Y_CFC0_OP - | Y_CFC1_OP - | Y_CFC2_OP - | Y_CTC0_OP - | Y_CTC1_OP - | Y_CTC2_OP - ; - -/* Floating point operations */ - -FP_MOVE_OPS: Y_MOV_S_OP - | Y_MOV_D_OP - ; - -FP_MOVE_OPS_REV2: Y_MOV_PS_OP - ; - - -MOVECC_OPS: Y_MOVF_OP - | Y_MOVT_OP - ; - - -FP_MOVEC_OPS: Y_MOVN_D_OP - | Y_MOVN_S_OP - | Y_MOVZ_D_OP - | Y_MOVZ_S_OP - ; - -FP_MOVEC_OPS_REV2: Y_MOVN_PS_OP - | Y_MOVZ_PS_OP - ; - - -FP_MOVECC_OPS: Y_MOVF_D_OP - | Y_MOVF_S_OP - | Y_MOVT_D_OP - | Y_MOVT_S_OP - ; - -FP_MOVECC_OPS_REV2: Y_MOVF_PS_OP - | Y_MOVT_PS_OP - ; - -FP_UNARY_OPS: Y_ABS_S_OP - | Y_ABS_D_OP - | Y_CEIL_W_D_OP - | Y_CEIL_W_S_OP - | Y_CVT_D_S_OP - | Y_CVT_D_W_OP - | Y_CVT_S_D_OP - | Y_CVT_S_W_OP - | Y_CVT_W_D_OP - | Y_CVT_W_S_OP - | Y_FLOOR_W_D_OP - | Y_FLOOR_W_S_OP - | Y_NEG_S_OP - | Y_NEG_D_OP - | Y_ROUND_W_D_OP - | Y_ROUND_W_S_OP - | Y_SQRT_D_OP - | Y_SQRT_S_OP - | Y_TRUNC_W_D_OP - | Y_TRUNC_W_S_OP - ; - -FP_UNARY_OPS_REV2: Y_ABS_PS_OP - | Y_CEIL_L_D_OP - | Y_CEIL_L_S_OP - | Y_CVT_D_L_OP - | Y_CVT_L_D_OP - | Y_CVT_L_S_OP - | Y_CVT_PS_S_OP - | Y_CVT_S_L_OP - | Y_CVT_S_PL_OP - | Y_CVT_S_PU_OP - | Y_FLOOR_L_D_OP - | Y_FLOOR_L_S_OP - | Y_NEG_PS_OP - | Y_RECIP_D_OP - | Y_RECIP_S_OP - | Y_ROUND_L_D_OP - | Y_ROUND_L_S_OP - | Y_RSQRT_D_OP - | Y_RSQRT_S_OP - | Y_TRUNC_L_D_OP - | Y_TRUNC_L_S_OP - ; - -FP_BINARY_OPS: Y_ADD_S_OP - | Y_ADD_D_OP - | Y_DIV_S_OP - | Y_DIV_D_OP - | Y_MUL_S_OP - | Y_MUL_D_OP - | Y_SUB_S_OP - | Y_SUB_D_OP - ; - -FP_BINARY_OPS_REV2: Y_ADD_PS_OP - | Y_MUL_PS_OP - | Y_PLL_PS_OP - | Y_PLU_PS_OP - | Y_PUL_PS_OP - | Y_PUU_PS_OP - ; - -FP_TERNARY_OPS_REV2: Y_ALNV_PS_OP - | Y_MADD_D_OP - | Y_MADD_PS_OP - | Y_MADD_S_OP - | Y_MSUB_D_OP - | Y_MSUB_PS_OP - | Y_MSUB_S_OP - | Y_NMADD_D_OP - | Y_NMADD_PS_OP - | Y_NMADD_S_OP - | Y_NMSUB_D_OP - | Y_NMSUB_PS_OP - | Y_NMSUB_S_OP - ; - -FP_CMP_OPS: Y_C_F_S_OP - | Y_C_UN_S_OP - | Y_C_EQ_S_OP - | Y_C_UEQ_S_OP - | Y_C_OLT_S_OP - | Y_C_OLE_S_OP - | Y_C_ULT_S_OP - | Y_C_ULE_S_OP - | Y_C_SF_S_OP - | Y_C_NGLE_S_OP - | Y_C_SEQ_S_OP - | Y_C_NGL_S_OP - | Y_C_LT_S_OP - | Y_C_NGE_S_OP - | Y_C_LE_S_OP - | Y_C_NGT_S_OP - | Y_C_F_D_OP - | Y_C_UN_D_OP - | Y_C_EQ_D_OP - | Y_C_UEQ_D_OP - | Y_C_OLT_D_OP - | Y_C_OLE_D_OP - | Y_C_ULT_D_OP - | Y_C_ULE_D_OP - | Y_C_SF_D_OP - | Y_C_NGLE_D_OP - | Y_C_SEQ_D_OP - | Y_C_NGL_D_OP - | Y_C_LT_D_OP - | Y_C_NGE_D_OP - | Y_C_LE_D_OP - | Y_C_NGT_D_OP - ; - -FP_CMP_OPS_REV2: Y_C_EQ_PS_OP - | Y_C_F_PS_OP - | Y_C_LT_PS_OP - | Y_C_LE_PS_OP - | Y_C_NGE_PS_OP - | Y_C_NGL_PS_OP - | Y_C_NGLE_PS_OP - | Y_C_NGT_PS_OP - | Y_C_OLE_PS_OP - | Y_C_OLT_PS_OP - | Y_C_SEQ_PS_OP - | Y_C_SF_PS_OP - | Y_C_UEQ_PS_OP - | Y_C_ULE_PS_OP - | Y_C_ULT_PS_OP - | Y_C_UN_PS_OP - ; - - - -ASM_DIRECTIVE: Y_ALIAS_DIR Y_REG Y_REG - - | Y_ALIGN_DIR EXPR - { - if (text_dir) - align_text ($2.i); - else - align_data ($2.i); - } - - | Y_ASCII_DIR {null_term = false;} STR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - | Y_ASCIIZ_DIR {null_term = true;} STR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_ASM0_DIR - - | Y_BGNB_DIR Y_INT - - - | Y_BYTE_DIR - {store_op = store_byte;} - EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_COMM_DIR ID EXPR - { - align_data (2); - if (lookup_label ((char*)$2.p)->addr == 0) - { - (void)record_label ((char*)$2.p, current_data_pc (), 1); - free ((char*)$2.p); - } - increment_data_pc ($3.i); - } - - - | Y_DATA_DIR - {user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_DATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_K_DATA_DIR - { - user_kernel_data_segment (true); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_K_DATA_DIR Y_INT - { - user_kernel_data_segment (true); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_DOUBLE_DIR - { - store_fp_op = store_double; - if (data_dir) set_data_alignment (3); - } - FP_EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_END_DIR OPTIONAL_ID - - | Y_ENDB_DIR Y_INT - - | Y_ENDR_DIR - - | Y_ENT_DIR ID - - | Y_ENT_DIR ID Y_INT - - - | Y_EXTERN_DIR ID EXPR - { - extern_directive ((char*)$2.p, $3.i); - } - - - | Y_ERR_DIR - { - fatal_error ("File contains an .err directive\n"); - } - - - | Y_FILE_DIR Y_INT Y_STR - - - | Y_FLOAT_DIR - { - store_fp_op = store_float; - if (data_dir) set_data_alignment (2); - } - FP_EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_FMASK_DIR Y_INT Y_INT - - | Y_FRAME_DIR REGISTER Y_INT REGISTER - - - | Y_GLOBAL_DIR ID - { - (void)make_label_global ((char*)$2.p); - free ((char*)$2.p); - } - - - | Y_HALF_DIR - { - store_op = store_half; - if (data_dir) set_data_alignment (1); - } - EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_LABEL_DIR ID - { - (void)record_label ((char*)$2.p, - text_dir ? current_text_pc () : current_data_pc (), - 1); - free ((char*)$2.p); - } - - - | Y_LCOMM_DIR ID EXPR - { - lcomm_directive ((char*)$2.p, $3.i); - } - - - /* Produced by cc 2.10 */ - | Y_LIVEREG_DIR Y_INT Y_INT - - - | Y_LOC_DIR Y_INT Y_INT - - | Y_MASK_DIR Y_INT Y_INT - - | Y_NOALIAS_DIR Y_REG Y_REG - - | Y_OPTIONS_DIR ID - - | Y_REPEAT_DIR EXPR - { - yyerror ("Warning: repeat directive ignored"); - } - - - | Y_RDATA_DIR - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_RDATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_SDATA_DIR - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_SDATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_SET_DIR ID - { - if (streq ((char*)$2.p, "noat")) - noat_flag = true; - else if (streq ((char*)$2.p, "at")) - noat_flag = false; - } - - - | Y_SPACE_DIR EXPR - { - if (data_dir) - increment_data_pc ($2.i); - else if (text_dir) - increment_text_pc ($2.i); - } - - - | Y_STRUCT_DIR EXPR - { - yyerror ("Warning: struct directive ignored"); - } - - - | Y_TEXT_DIR - { - user_kernel_text_segment (false); - data_dir = false; text_dir = true; - enable_text_alignment (); - } - - | Y_TEXT_DIR Y_INT - { - user_kernel_text_segment (false); - data_dir = false; text_dir = true; - enable_text_alignment (); - set_text_pc ($2.i); - } - - - | Y_K_TEXT_DIR - { - user_kernel_text_segment (true); - data_dir = false; text_dir = true; - enable_text_alignment (); - } - - | Y_K_TEXT_DIR Y_INT - { - user_kernel_text_segment (true); - data_dir = false; text_dir = true; - enable_text_alignment (); - set_text_pc ($2.i); - } - - - | Y_VERSTAMP_DIR Y_INT Y_INT - - | Y_VREG_DIR REGISTER Y_INT Y_INT - - - | Y_WORD_DIR - { - store_op = store_word_data; - if (data_dir) set_data_alignment (2); - } - EXPR_LST - - ; - - - -ADDRESS: {only_id = 1;} ADDR {only_id = 0; $$ = $2;} - -ADDR: '(' REGISTER ')' - { - $$.p = make_addr_expr (0, NULL, $2.i); - } - - | ABS_ADDR - { - $$.p = make_addr_expr ($1.i, NULL, 0); - } - - | ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr ($1.i, NULL, $3.i); - } - - | Y_ID - { - $$.p = make_addr_expr (0, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | Y_ID '(' REGISTER ')' - { - $$.p = make_addr_expr (0, (char*)$1.p, $3.i); - free ((char*)$1.p); - } - - | Y_ID '+' ABS_ADDR - { - $$.p = make_addr_expr ($3.i, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | ABS_ADDR '+' ID - { - $$.p = make_addr_expr ($1.i, (char*)$3.p, 0); - } - - | Y_ID '-' ABS_ADDR - { - $$.p = make_addr_expr (- $3.i, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | Y_ID '+' ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr ($3.i, (char*)$1.p, $5.i); - free ((char*)$1.p); - } - - | Y_ID '-' ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr (- $3.i, (char*)$1.p, $5.i); - free ((char*)$1.p); - } - ; - - -BR_IMM32: {only_id = 1;} IMM32 {only_id = 0; $$ = $2;} - -IMM16: IMM32 - { - check_imm_range ((imm_expr*)$1.p, IMM_MIN, IMM_MAX); - $$ = $1; - } - -UIMM16: IMM32 - { - check_uimm_range ((imm_expr*)$1.p, UIMM_MIN, UIMM_MAX); - $$ = $1; - } - - -IMM32: ABS_ADDR - { - $$.p = make_imm_expr ($1.i, NULL, false); - } - - | '(' ABS_ADDR ')' '>' '>' Y_INT - { - $$.p = make_imm_expr ($2.i >> $6.i, NULL, false); - } - - | ID - { - $$.p = make_imm_expr (0, (char*)$1.p, false); - } - - | Y_ID '+' ABS_ADDR - { - $$.p = make_imm_expr ($3.i, (char*)$1.p, false); - free ((char*)$1.p); - } - - | Y_ID '-' ABS_ADDR - { - $$.p = make_imm_expr (- $3.i, (char*)$1.p, false); - free ((char*)$1.p); - } - ; - - -ABS_ADDR: Y_INT - - | Y_INT '+' Y_INT - {$$.i = $1.i + $3.i;} - - | Y_INT Y_INT - { - /* This is actually: Y_INT '-' Y_INT, since the binary - subtract operator gets scanned as a unary negation - operator. */ - if ($2.i >= 0) yyerror ("Syntax error"); - $$.i = $1.i - -$2.i; - } - ; - -SRC1: REGISTER ; - -SRC2: REGISTER ; - -DEST: REGISTER ; - -REG: REGISTER ; - -REGISTER: Y_REG - { - if ($1.i < 0 || $1.i > 31) - yyerror ("Register number out of range"); - if ($1.i == 1 && !bare_machine && !noat_flag) - yyerror ("Register 1 is reserved for assembler"); - $$ = $1; - } - -F_DEST: FP_REGISTER ; - -F_SRC1: FP_REGISTER ; - -F_SRC2: FP_REGISTER ; - -FP_REGISTER: Y_FP_REG - { - if ($1.i < 0 || $1.i > 31) - yyerror ("FP register number out of range"); - $$ = $1; - } - - -CC_REG: Y_INT - { - if ($1.i < 0 || $1.i > 7) - yyerror ("CC register number out of range"); - $$ = $1; - } - - -COP_REG: Y_REG - - | Y_FP_REG - - ; - - -LABEL: ID - { - $$.p = make_imm_expr (-(int)current_text_pc (), (char*)$1.p, true); - } - - -STR_LST: STR_LST STR - | STR - ; - - -STR: Y_STR - { - store_string ((char*)$1.p, strlen((char*)$1.p), null_term); - free ((char*)$1.p); - } - | Y_STR ':' Y_INT - { - int i; - - for (i = 0; i < $3.i; i ++) - store_string ((char*)$1.p, strlen((char*)$1.p), null_term); - free ((char*)$1.p); - } - ; - - -EXPRESSION: {only_id = 1;} EXPR {only_id = 0; $$ = $2;} - -EXPR: - TRM - | - EXPR '+' TRM - { $$.i = $1.i + $3.i; } - | - EXPR '-' TRM - { $$.i = $1.i - $3.i; } - ; - -TRM: - FACTOR - | - TRM '*' FACTOR - { $$.i = $1.i * $3.i; } - | - TRM '/' FACTOR - { $$.i = $1.i / $3.i; } - ; - -FACTOR: Y_INT - - | '(' EXPR ')' - { $$.i = $2.i; } - - | ID - { - label *l = lookup_label ((char*)$1.p); - if (l->addr == 0) - { - record_data_uses_symbol (current_data_pc (), l); - $$.p = NULL; - } - else - $$.i = l->addr; - } - - -EXPR_LST: EXPR_LST EXPRESSION - { - store_op ($2.i); - } - | EXPRESSION - { - store_op ($1.i); - } - | EXPRESSION ':' EXPR - { - int i; - - for (i = 0; i < $3.i; i ++) - store_op ($1.i); - } - ; - - -FP_EXPR_LST: FP_EXPR_LST Y_FP - { - store_fp_op ((double*)$2.p); - } - | Y_FP - { - store_fp_op ((double*)$1.p); - } - ; - - -OPTIONAL_ID: {only_id = 1;} OPT_ID {only_id = 0; $$ = $2;} - -OPT_ID: ID - | {$$.p = (void*)NULL;} - ; - - -ID: {only_id = 1;} Y_ID {only_id = 0; $$ = $2;} - - -%% - -/* Maintain and update the address of labels for the current line. */ - -void -fix_current_label_address (mem_addr new_addr) -{ - label_list *l; - - for (l = this_line_labels; l != NULL; l = l->tail) - { - l->head->addr = new_addr; - } - clear_labels (); -} - - -static label_list * -cons_label (label *head, label_list *tail) -{ - label_list *c = (label_list *) malloc (sizeof (label_list)); - - c->head = head; - c->tail = tail; - return (c); -} - - -static void -clear_labels () -{ - label_list *n; - - for ( ; this_line_labels != NULL; this_line_labels = n) - { - resolve_label_uses (this_line_labels->head); - n = this_line_labels->tail; - free (this_line_labels); - } - this_line_labels = NULL; -} - - -/* Operations on op codes. */ - -int -op_to_imm_op (int opcode) -{ - switch (opcode) - { - case Y_ADD_OP: return (Y_ADDI_OP); - case Y_ADDU_OP: return (Y_ADDIU_OP); - case Y_AND_OP: return (Y_ANDI_OP); - case Y_OR_OP: return (Y_ORI_OP); - case Y_XOR_OP: return (Y_XORI_OP); - case Y_SLT_OP: return (Y_SLTI_OP); - case Y_SLTU_OP: return (Y_SLTIU_OP); - case Y_SLLV_OP: return (Y_SLL_OP); - case Y_SRAV_OP: return (Y_SRA_OP); - case Y_SRLV_OP: return (Y_SRL_OP); - default: fatal_error ("Can't convert op to immediate op\n"); return (0); - } -} - - -int -imm_op_to_op (int opcode) -{ - switch (opcode) - { - case Y_ADDI_OP: return (Y_ADD_OP); - case Y_ADDIU_OP: return (Y_ADDU_OP); - case Y_ANDI_OP: return (Y_AND_OP); - case Y_ORI_OP: return (Y_OR_OP); - case Y_XORI_OP: return (Y_XOR_OP); - case Y_SLTI_OP: return (Y_SLT_OP); - case Y_SLTIU_OP: return (Y_SLTU_OP); - case Y_J_OP: return (Y_JR_OP); - case Y_LUI_OP: return (Y_ADDU_OP); - case Y_SLL_OP: return (Y_SLLV_OP); - case Y_SRA_OP: return (Y_SRAV_OP); - case Y_SRL_OP: return (Y_SRLV_OP); - default: fatal_error ("Can't convert immediate op to op\n"); return (0); - } -} - - -static void -nop_inst () -{ - r_type_inst (Y_SLL_OP, 0, 0, 0); /* = 0 */ -} - - -static void -trap_inst () -{ - r_type_inst (Y_BREAK_OP, 0, 0, 0); -} - - -static imm_expr * -branch_offset (int n_inst) -{ - return (const_imm_expr (n_inst << 2)); /* Later shifted right 2 places */ -} - - -static void -div_inst (int op, int rd, int rs, int rt, int const_divisor) -{ - if (rd != 0 && !const_divisor) - { - i_type_inst_free (Y_BNE_OP, 0, rt, branch_offset (3)); - nop_inst(); - trap_inst (); - } - - if (op == Y_DIV_OP || op == Y_REM_POP) - r_type_inst (Y_DIV_OP, 0, rs, rt); - else - r_type_inst (Y_DIVU_OP, 0, rs, rt); - - if (rd != 0) - { - if (op == Y_DIV_OP || op == Y_DIVU_OP) - /* Quotient */ - r_type_inst (Y_MFLO_OP, rd, 0, 0); - else - /* Remainder */ - r_type_inst (Y_MFHI_OP, rd, 0, 0); - } -} - - -static void -mult_inst (int op, int rd, int rs, int rt) -{ - if (op == Y_MULOU_POP) - r_type_inst (Y_MULTU_OP, 0, rs, rt); - else - r_type_inst (Y_MULT_OP, 0, rs, rt); - if (op == Y_MULOU_POP && rd != 0) - { - r_type_inst (Y_MFHI_OP, 1, 0, 0); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, branch_offset (3)); - nop_inst(); - trap_inst (); - } - else if (op == Y_MULO_POP && rd != 0) - { - r_type_inst (Y_MFHI_OP, 1, 0, 0); /* use $at */ - r_type_inst (Y_MFLO_OP, rd, 0, 0); - r_sh_type_inst (Y_SRA_OP, rd, rd, 31); - i_type_inst_free (Y_BEQ_OP, rd, 1, branch_offset (3)); - nop_inst(); - trap_inst (); - } - if (rd != 0) - r_type_inst (Y_MFLO_OP, rd, 0, 0); -} - - -static void -set_le_inst (int op, int rd, int rs, int rt) -{ - i_type_inst_free (Y_BNE_OP, rs, rt, branch_offset (3)); - i_type_inst_free (Y_ORI_OP, rd, 0, const_imm_expr (1)); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (3)); - nop_inst(); - r_type_inst ((op == Y_SLE_POP ? Y_SLT_OP : Y_SLTU_OP), rd, rs, rt); -} - - -static void -set_gt_inst (int op, int rd, int rs, int rt) -{ - r_type_inst (op == Y_SGT_POP ? Y_SLT_OP : Y_SLTU_OP, rd, rt, rs); -} - - -static void -set_ge_inst (int op, int rd, int rs, int rt) -{ - i_type_inst_free (Y_BNE_OP, rs, rt, branch_offset (3)); - i_type_inst_free (Y_ORI_OP, rd, 0, const_imm_expr (1)); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (3)); - nop_inst(); - r_type_inst (op == Y_SGE_POP ? Y_SLT_OP : Y_SLTU_OP, rd, rt, rs); -} - - -static void -set_eq_inst (int op, int rd, int rs, int rt) -{ - imm_expr *if_eq, *if_neq; - - if (op == Y_SEQ_POP) - if_eq = const_imm_expr (1), if_neq = const_imm_expr (0); - else - if_eq = const_imm_expr (0), if_neq = const_imm_expr (1); - - i_type_inst_free (Y_BEQ_OP, rs, rt, branch_offset (3)); - /* RD <- 0 (if not equal) */ - i_type_inst_free (Y_ORI_OP, rd, 0, if_neq); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (3)); /* Branch always */ - nop_inst(); - /* RD <- 1 */ - i_type_inst_free (Y_ORI_OP, rd, 0, if_eq); -} - - -/* Store the value either as a datum or instruction. */ - -static void -store_word_data (int value) -{ - if (data_dir) - store_word (value); - else if (text_dir) - store_instruction (inst_decode (value)); -} - - - -void -initialize_parser (char *file_name) -{ - input_file_name = file_name; - only_id = 0; - data_dir = false; - text_dir = true; -} - - -static void -check_imm_range (imm_expr* expr, int32 min, int32 max) -{ - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* If expression can be evaluated, compare its value against the limits - and complain if the value is out of bounds. */ - int32 value = eval_imm_expr (expr); - - if (value < min || max < value) - { - char str[200]; - sprintf (str, "immediate value (%d) out of range (%d .. %d)", - value, min, max); - yywarn (str); - } - } -} - - -static void -check_uimm_range (imm_expr* expr, uint32 min, uint32 max) -{ - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* If expression can be evaluated, compare its value against the limits - and complain if the value is out of bounds. */ - uint32 value = (uint32)eval_imm_expr (expr); - - if (value < min || max < value) - { - char str[200]; - sprintf (str, "immediate value (%d) out of range (%d .. %d)", - (int32)value, (int32)min, (int32)max); - yywarn (str); - } - } -} - -void -yyerror (char *s) -{ - parse_error_occurred = true; - clear_labels (); - yywarn (s); -} - - -void -yywarn (char *s) -{ - error ("spim: (parser) %s on line %d of file %s\n%s", s, line_no, input_file_name, erroneous_line ()); -} - - -static void -mips32_r2_inst () -{ - yyerror ("Warning: MIPS32 Rev 2 instruction is not implemented. Instruction ignored."); -} - - -static int -cc_to_rt (int cc, int nd, int tf) -{ - return (cc << 2) | (nd << 1) | tf; -} diff --git a/spim-qtbase/CPU/reg.h b/spim-qtbase/CPU/reg.h deleted file mode 100755 index 87e2195..0000000 --- a/spim-qtbase/CPU/reg.h +++ /dev/null @@ -1,240 +0,0 @@ -/* SPIM S20 MIPS simulator. - Declarations of registers and code for accessing them. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -typedef int32 /*@alt unsigned int @*/ reg_word; -typedef uint32 u_reg_word; - - -/* General purpose registers: */ - -#define R_LENGTH 32 - -extern reg_word R[R_LENGTH]; - -extern reg_word HI, LO; - -extern mem_addr PC, nPC; - - -/* Argument passing registers */ - -#define REG_V0 2 -#define REG_A0 4 -#define REG_A1 5 -#define REG_A2 6 -#define REG_A3 7 -#define REG_FA0 12 -#define REG_SP 29 - - -/* Result registers */ - -#define REG_RES 2 -#define REG_FRES 0 - - -/* $gp registers */ - -#define REG_GP 28 - -extern char *int_reg_names[]; - - - -/* Coprocessor registers: */ - -extern reg_word CCR[4][32], CPR[4][32]; - - - -/* Exeception handling registers (Coprocessor 0): */ - -/* BadVAddr register: */ -#define CP0_BadVAddr_Reg 8 -#define CP0_BadVAddr (CPR[0][CP0_BadVAddr_Reg]) - -/* Count register: */ -#define CP0_Count_Reg 9 -#define CP0_Count (CPR[0][CP0_Count_Reg]) /* ToDo */ - -/* Compare register: */ -#define CP0_Compare_Reg 11 -#define CP0_Compare (CPR[0][CP0_Compare_Reg]) /* ToDo */ - -/* Status register: */ -#define CP0_Status_Reg 12 -#define CP0_Status (CPR[0][CP0_Status_Reg]) -/* Implemented fields: */ -#define CP0_Status_CU 0xf0000000 -#define CP0_Status_IM 0x0000ff00 -#define CP0_Status_IM7 0x00008000 /* HW Int 5 */ -#define CP0_Status_IM6 0x00004000 /* HW Int 4 */ -#define CP0_Status_IM5 0x00002000 /* HW Int 3 */ -#define CP0_Status_IM4 0x00001000 /* HW Int 2 */ -#define CP0_Status_IM3 0x00000800 /* HW Int 1 */ -#define CP0_Status_IM2 0x00000400 /* HW Int 0 */ -#define CP0_Status_IM1 0x00000200 /* SW Int 1 */ -#define CP0_Status_IM0 0x00000100 /* SW Int 0 */ -#define CP0_Status_UM 0x00000010 -#define CP0_Status_EXL 0x00000002 -#define CP0_Status_IE 0x00000001 -#define CP0_Status_Mask (CP0_Status_CU \ - | CP0_Status_UM \ - | CP0_Status_IM \ - | CP0_Status_EXL \ - | CP0_Status_IE) - -/* Cause register: */ -#define CP0_Cause_Reg 13 -#define CP0_Cause (CPR[0][CP0_Cause_Reg]) -/* Implemented fields: */ -#define CP0_Cause_BD 0x80000000 -#define CP0_Cause_IP 0x0000ff00 -#define CP0_Cause_IP7 0x00008000 /* HW Int 5 */ -#define CP0_Cause_IP6 0x00004000 /* HW Int 4 */ -#define CP0_Cause_IP5 0x00002000 /* HW Int 3 */ -#define CP0_Cause_IP4 0x00001000 /* HW Int 2 */ -#define CP0_Cause_IP3 0x00000800 /* HW Int 1 */ -#define CP0_Cause_IP2 0x00000400 /* HW Int 0 */ -#define CP0_Cause_IP1 0x00000200 /* SW Int 1 */ -#define CP0_Cause_IP0 0x00000100 /* SW Int 0 */ -#define CP0_Cause_ExcCode 0x0000007c -#define CP0_Cause_Mask (CP0_Cause_BD \ - | CP0_Cause_IP \ - | CP0_Cause_IP7 \ - | CP0_Cause_IP6 \ - | CP0_Cause_IP5 \ - | CP0_Cause_IP4 \ - | CP0_Cause_IP3 \ - | CP0_Cause_IP2 \ - | CP0_Cause_ExcCode) -#define CP0_ExCode ((CP0_Cause & CP0_Cause_ExcCode) >> 2) - -/* EPC register: */ -#define CP0_EPC_Reg 14 -#define CP0_EPC (CPR[0][CP0_EPC_Reg]) - -/* Config register: */ -#define CP0_Config_Reg 16 -#define CP0_Config (CPR[0][CP0_Config_Reg]) -/* Implemented fields: */ -#define CP0_Config_BE 0x000080000 -#define CP0_Config_AT 0x000060000 -#define CP0_Config_AR 0x00001c000 -#define CP0_Config_MT 0x000000380 -#define CP0_Config_Mask (CP0_Config_BE \ - | CP0_Config_AT \ - | CP0_Config_AR \ - | CP0_Config_MT) - - - -/* Floating Point Coprocessor (1) registers. - - This is the MIPS32, Revision 1 FPU register set. It contains 32, 32-bit - registers (either 32 single or 16 double precision), as in the R2010. - The MIPS32, Revision 2 or MIPS64 register set has 32 of each type of - register. */ - -#define FGR_LENGTH 32 -#define FPR_LENGTH 16 - -extern double *FPR; /* Dynamically allocate so overlay */ -extern float *FGR; /* is possible */ -extern int *FWR; /* is possible */ - - -#define FPR_S(REGNO) (FGR[REGNO]) - -#define FPR_D(REGNO) (((REGNO) & 0x1) \ - ? (run_error ("Odd FP double register number\n") , 0.0) \ - : FPR[(REGNO) / 2]) - -#define FPR_W(REGNO) (FWR[REGNO]) - - -#define SET_FPR_S(REGNO, VALUE) {FGR[REGNO] = (float) (VALUE);} - -#define SET_FPR_D(REGNO, VALUE) {if ((REGNO) & 0x1) \ - run_error ("Odd FP double register number\n"); \ - else FPR[(REGNO) / 2] = (double) (VALUE);} - -#define SET_FPR_W(REGNO, VALUE) {FWR[REGNO] = (int32) (VALUE);} - - -/* Floating point control registers: */ - -#define FCR (CPR[1]) - - -#define FIR_REG 0 -#define FIR (FCR[FIR_REG]) - -/* Implemented fields: */ -#define FIR_W 0x0008000 -#define FIR_D 0x0001000 -#define FIR_S 0x0000800 -#define FIR_MASK (FIR_W | FIR_D | FIR_S) - - -#define FCSR_REG 31 -#define FCSR (FCR[FCSR_REG]) - -/* Implemented fields: */ -#define FCSR_FCC 0xfe800000 -#define FCSR_MASK (FCSR_FCC) -#define CC0_bit 23 -#define CC1_bit 25 -#define CC_mask(n) ((((n) == 0) || ((n) > 7)) ? (1 << CC0_bit) : (1 << (CC1_bit + (n) - 1))) -#define FCC(n) (((FCSR & CC_mask(n)) == 0) ? 0 : 1) -#define SET_FCC(n, v) if ((v) == 0) { FCSR &= ~CC_mask(n); } else { FCSR |= CC_mask(n); } - -/* Floating point Cause (not implemented): */ -#define FCSR_Cause_E 0x00020000 -#define FCSR_Cause_V 0x00010000 -#define FCSR_Cause_Z 0x00008000 -#define FCSR_Cause_O 0x00004000 -#define FCSR_Cause_U 0x00002000 -#define FCSR_Cause_I 0x00001000 -/* Floating point Enables (not implemented): */ -#define FCSR_Enable_V 0x00000800 -#define FCSR_Enable_Z 0x00000400 -#define FCSR_Enable_O 0x00000200 -#define FCSR_Enable_U 0x00000100 -#define FCSR_Enable_I 0x00000080 -/* Floating point Flags (not implemented): */ -#define FCSR_Flag_V 0x00000040 -#define FCSR_Flag_Z 0x00000020 -#define FCSR_Flag_O 0x00000010 -#define FCSR_Flag_U 0x00000008 -#define FCSR_Flag_I 0x00000004 diff --git a/spim-qtbase/CPU/run.cpp b/spim-qtbase/CPU/run.cpp deleted file mode 100755 index a82c835..0000000 --- a/spim-qtbase/CPU/run.cpp +++ /dev/null @@ -1,1849 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM instructions. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifdef mips -#define _IEEE 1 -#include -#else -#define NaN(X) ((X) != (X)) -#endif - -#include -#include - -#ifdef _WIN32 -#define VC_EXTRALEAN -#include -#else -#include -#include -#include -#include -#endif - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser_yacc.h" -#include "syscall.h" -#include "run.h" - -bool force_break = false; /* For the execution env. to force an execution break */ - -#ifdef _MSC_BUILD -/* Disable MS VS warning about constant predicate in conditional. */ -#pragma warning(disable: 4127) -#endif - - -/* Local functions: */ - -static void bump_CP0_timer (); -static void set_fpu_cc (int cond, int cc, int less, int equal, int unordered); -static void signed_multiply (reg_word v1, reg_word v2); -static void start_CP0_timer (); -#ifdef _WIN32 -void CALLBACK timer_completion_routine(LPVOID lpArgToCompletionRoutine, - DWORD dwTimerLowValue, DWORD dwTimerHighValue); -#endif -static void unsigned_multiply (reg_word v1, reg_word v2); - - -#define SIGN_BIT(X) ((X) & 0x80000000) - -#define ARITH_OVFL(RESULT, OP1, OP2) (SIGN_BIT (OP1) == SIGN_BIT (OP2) \ - && SIGN_BIT (OP1) != SIGN_BIT (RESULT)) - - - -/* True when delayed_branches is true and instruction is executing in delay -slot of another instruction. */ -static int running_in_delay_slot = 0; - - -/* Executed delayed branch and jump instructions by running the - instruction from the delay slot before transfering control. Note, - in branches that don't jump, the instruction in the delay slot is - executed by falling through normally. - - We take advantage of the MIPS architecture, which leaves undefined - the result of executing a delayed instruction in a delay slot. Here - we execute the second branch. */ - -#define BRANCH_INST(TEST, TARGET, NULLIFY) \ - { \ - if (TEST) \ - { \ - mem_addr target = (TARGET); \ - if (delayed_branches) \ - { \ - /* +4 since jump in delay slot */ \ - target += BYTES_PER_WORD; \ - } \ - JUMP_INST(target) \ - } \ - else if (NULLIFY) \ - { \ - /* If test fails and nullify bit set, skip\ - instruction in delay slot. */ \ - PC += BYTES_PER_WORD; \ - } \ - } - - -#define JUMP_INST(TARGET) \ - { \ - if (delayed_branches) \ - { \ - running_in_delay_slot = 1; \ - run_spim (PC + BYTES_PER_WORD, 1, display);\ - running_in_delay_slot = 0; \ - } \ - /* -4 since PC is bumped after this inst */ \ - PC = (TARGET) - BYTES_PER_WORD; \ - } - - -/* If the delayed_load flag is false, the result from a load is available - immediate. If the delayed_load flag is true, the result from a load is - not available until the subsequent instruction has executed (as in the - real machine). We need a two element shift register for the value and its - destination, as the instruction following the load can itself be a load - instruction. */ - -#define LOAD_INST(DEST_A, LD, MASK) \ - { \ - LOAD_INST_BASE (DEST_A, (LD & (MASK))) \ - } - - -#define LOAD_INST_BASE(DEST_A, VALUE) \ - { \ - if (delayed_loads) \ - { \ - delayed_load_addr1 = (DEST_A); \ - delayed_load_value1 = (VALUE); \ - } \ - else \ - { \ - *(DEST_A) = (VALUE); \ - } \ - } - - -#define DO_DELAYED_UPDATE() \ - if (delayed_loads) \ - { \ - /* Check for delayed updates */ \ - if (delayed_load_addr2 != NULL) \ - { \ - *delayed_load_addr2 = delayed_load_value2; \ - } \ - delayed_load_addr2 = delayed_load_addr1; \ - delayed_load_value2 = delayed_load_value1; \ - delayed_load_addr1 = NULL; \ - } - - - -/* Run the program stored in memory, starting at address PC for - STEPS_TO_RUN instruction executions. If flag DISPLAY is true, print - each instruction before it executes. Return true if program's - execution can continue. */ - -bool -run_spim (mem_addr initial_PC, int steps_to_run, bool display) -{ - instruction *inst; - static reg_word *delayed_load_addr1 = NULL, delayed_load_value1; - static reg_word *delayed_load_addr2 = NULL, delayed_load_value2; - int step, step_size, next_step; - - PC = initial_PC; - if (!bare_machine && mapped_io) - next_step = IO_INTERVAL; - else - next_step = steps_to_run; /* Run to completion */ - - /* Start a timer running */ - start_CP0_timer(); - - for (step_size = MIN (next_step, steps_to_run); - steps_to_run > 0; - steps_to_run -= step_size, step_size = MIN (next_step, steps_to_run)) - { - if (!bare_machine && mapped_io) - /* Every IO_INTERVAL steps, check if memory-mapped IO registers - have changed. */ - check_memory_mapped_IO (); - /* else run inner loop for all steps */ - - if ((CP0_Status & CP0_Status_IE) - && !(CP0_Status & CP0_Status_EXL) - && ((CP0_Cause & CP0_Cause_IP) & (CP0_Status & CP0_Status_IM))) - { - /* There is an interrupt to process if IE bit set, EXL bit not - set, and non-masked IP bit set */ - raise_exception (ExcCode_Int); - /* Handle interrupt now, before instruction executes, so that - EPC points to unexecuted instructions, which is the one to - return to. */ - handle_exception (); - } - - force_break = false; - for (step = 0; step < step_size; step += 1) - { - if (force_break) - { - return true; - } - - R[0] = 0; /* Maintain invariant value */ - -#ifdef _WIN32 - SleepEx(0, TRUE); /* Put thread in awaitable state for WaitableTimer */ -#else - { - /* Poll for timer expiration */ - struct itimerval time; - if (-1 == getitimer (ITIMER_REAL, &time)) - { - perror ("getitmer failed"); - } - if (time.it_value.tv_usec == 0 && time.it_value.tv_sec == 0) - { - /* Timer expired */ - bump_CP0_timer (); - - /* Restart timer for next interval */ - start_CP0_timer (); - } - } -#endif - - exception_occurred = 0; - inst = read_mem_inst (PC); - if (exception_occurred) /* In reading instruction */ - { - exception_occurred = 0; - handle_exception (); - continue; - } - else if (inst == NULL) - { - run_error ("Attempt to execute non-instruction at 0x%08x\n", PC); - return false; - } - else if (EXPR (inst) != NULL - && EXPR (inst)->symbol != NULL - && EXPR (inst)->symbol->addr == 0) - { - run_error ("Instruction references undefined symbol at 0x%08x\n %s", PC, inst_to_string(PC)); - return false; - } - - if (display) - print_inst (PC); - -#ifdef TEST_ASM - test_assembly (inst); -#endif - - DO_DELAYED_UPDATE (); - - switch (OPCODE (inst)) - { - case Y_ADD_OP: - { - reg_word vs = R[RS (inst)], vt = R[RT (inst)]; - reg_word sum = vs + vt; - - if (ARITH_OVFL (sum, vs, vt)) - RAISE_EXCEPTION (ExcCode_Ov, break); - R[RD (inst)] = sum; - break; - } - - case Y_ADDI_OP: - { - reg_word vs = R[RS (inst)], imm = (short) IMM (inst); - reg_word sum = vs + imm; - - if (ARITH_OVFL (sum, vs, imm)) - RAISE_EXCEPTION (ExcCode_Ov, break); - R[RT (inst)] = sum; - break; - } - - case Y_ADDIU_OP: - R[RT (inst)] = R[RS (inst)] + (short) IMM (inst); - break; - - case Y_ADDU_OP: - R[RD (inst)] = R[RS (inst)] + R[RT (inst)]; - break; - - case Y_AND_OP: - R[RD (inst)] = R[RS (inst)] & R[RT (inst)]; - break; - - case Y_ANDI_OP: - R[RT (inst)] = R[RS (inst)] & (0xffff & IMM (inst)); - break; - - case Y_BC2F_OP: - case Y_BC2FL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_BEQ_OP: - BRANCH_INST (R[RS (inst)] == R[RT (inst)], - PC + IDISP (inst), - 0); - break; - - case Y_BEQL_OP: - BRANCH_INST (R[RS (inst)] == R[RT (inst)], - PC + IDISP (inst), - 1); - break; - - case Y_BGEZ_OP: - BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 0); - break; - - case Y_BGEZL_OP: - BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 1); - break; - - case Y_BGEZAL_OP: - R[31] = PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 0); - break; - - case Y_BGEZALL_OP: - R[31] = PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 1); - break; - - case Y_BGTZ_OP: - BRANCH_INST (R[RS (inst)] != 0 && SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 0); - break; - - case Y_BGTZL_OP: - BRANCH_INST (R[RS (inst)] != 0 && SIGN_BIT (R[RS (inst)]) == 0, - PC + IDISP (inst), - 1); - break; - - case Y_BLEZ_OP: - BRANCH_INST (R[RS (inst)] == 0 || SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 0); - break; - - case Y_BLEZL_OP: - BRANCH_INST (R[RS (inst)] == 0 || SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 1); - break; - - case Y_BLTZ_OP: - BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 0); - break; - - case Y_BLTZL_OP: - BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 1); - break; - - case Y_BLTZAL_OP: - R[31] = PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 0); - break; - - case Y_BLTZALL_OP: - R[31] = PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0, - PC + IDISP (inst), - 1); - break; - - case Y_BNE_OP: - BRANCH_INST (R[RS (inst)] != R[RT (inst)], - PC + IDISP (inst), - 0); - break; - - case Y_BNEL_OP: - BRANCH_INST (R[RS (inst)] != R[RT (inst)], - PC + IDISP (inst), - 1); - break; - - case Y_BREAK_OP: - if (RD (inst) == 1) - /* Debugger breakpoint */ - RAISE_EXCEPTION (ExcCode_Bp, return true) - else - RAISE_EXCEPTION (ExcCode_Bp, break); - - case Y_CACHE_OP: - break; /* Memory details not implemented */ - - case Y_CFC0_OP: - R[RT (inst)] = CCR[0][RD (inst)]; - break; - - case Y_CFC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_CLO_OP: - { - reg_word val = R[RS (inst)]; - int i; - for (i = 31; 0 <= i; i -= 1) - if (((val >> i) & 0x1) == 0) break; - - R[RD (inst) ] = 31 - i; - break; - } - - case Y_CLZ_OP: - { - reg_word val = R[RS (inst)]; - int i; - for (i = 31; 0 <= i; i -= 1) - if (((val >> i) & 0x1) == 1) break; - - R[RD (inst) ] = 31 - i; - break; - } - - case Y_COP2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_CTC0_OP: - CCR[0][RD (inst)] = R[RT (inst)]; - break; - - case Y_CTC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_DIV_OP: - /* The behavior of this instruction is undefined on divide by - zero or overflow. */ - if (R[RT (inst)] != 0 - && !(R[RS (inst)] == (reg_word)0x80000000 - && R[RT (inst)] == (reg_word)0xffffffff)) - { - LO = (reg_word) R[RS (inst)] / (reg_word) R[RT (inst)]; - HI = (reg_word) R[RS (inst)] % (reg_word) R[RT (inst)]; - } - break; - - case Y_DIVU_OP: - /* The behavior of this instruction is undefined on divide by - zero or overflow. */ - if (R[RT (inst)] != 0 - && !(R[RS (inst)] == (reg_word)0x80000000 - && R[RT (inst)] == (reg_word)0xffffffff)) - { - LO = (u_reg_word) R[RS (inst)] / (u_reg_word) R[RT (inst)]; - HI = (u_reg_word) R[RS (inst)] % (u_reg_word) R[RT (inst)]; - } - break; - - case Y_ERET_OP: - { - CP0_Status &= ~CP0_Status_EXL; /* Clear EXL bit */ - JUMP_INST (CP0_EPC); /* Jump to EPC */ - } - break; - - case Y_J_OP: - JUMP_INST (((PC & 0xf0000000) | TARGET (inst) << 2)); - break; - - case Y_JAL_OP: - if (delayed_branches) - R[31] = PC + 2 * BYTES_PER_WORD; - else - R[31] = PC + BYTES_PER_WORD; - JUMP_INST (((PC & 0xf0000000) | (TARGET (inst) << 2))); - break; - - case Y_JALR_OP: - { - mem_addr tmp = R[RS (inst)]; - - if (delayed_branches) - R[RD (inst)] = PC + 2 * BYTES_PER_WORD; - else - R[RD (inst)] = PC + BYTES_PER_WORD; - JUMP_INST (tmp); - } - break; - - case Y_JR_OP: - { - mem_addr tmp = R[RS (inst)]; - - JUMP_INST (tmp); - } - break; - - case Y_LB_OP: - LOAD_INST (&R[RT (inst)], - read_mem_byte (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LBU_OP: - LOAD_INST (&R[RT (inst)], - read_mem_byte (R[BASE (inst)] + IOFFSET (inst)), - 0xff); - break; - - case Y_LH_OP: - LOAD_INST (&R[RT (inst)], - read_mem_half (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LHU_OP: - LOAD_INST (&R[RT (inst)], - read_mem_half (R[BASE (inst)] + IOFFSET (inst)), - 0xffff); - break; - - case Y_LL_OP: - /* Uniprocess, so this instruction is just a load */ - LOAD_INST (&R[RT (inst)], - read_mem_word (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LUI_OP: - R[RT (inst)] = (IMM (inst) << 16) & 0xffff0000; - break; - - case Y_LW_OP: - LOAD_INST (&R[RT (inst)], - read_mem_word (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LDC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_LWC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_LWL_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - reg_word word; /* Can't be register */ - int byte = addr & 0x3; - reg_word reg_val = R[RT (inst)]; - - word = read_mem_word (addr & 0xfffffffc); - if (!exception_occurred) -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - word = word; - break; - - case 1: - word = ((word & 0xffffff) << 8) | (reg_val & 0xff); - break; - - case 2: - word = ((word & 0xffff) << 16) | (reg_val & 0xffff); - break; - - case 3: - word = ((word & 0xff) << 24) | (reg_val & 0xffffff); - break; - } -#else - switch (byte) - { - case 0: - word = ((word & 0xff) << 24) | (reg_val & 0xffffff); - break; - - case 1: - word = ((word & 0xffff) << 16) | (reg_val & 0xffff); - break; - - case 2: - word = ((word & 0xffffff) << 8) | (reg_val & 0xff); - break; - - case 3: - break; - } -#endif - LOAD_INST_BASE (&R[RT (inst)], word); - break; - } - - case Y_LWR_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - reg_word word; /* Can't be register */ - int byte = addr & 0x3; - reg_word reg_val = R[RT (inst)]; - - word = read_mem_word (addr & 0xfffffffc); - if (!exception_occurred) -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - word = (reg_val & 0xffffff00) | ((unsigned)(word & 0xff000000) >> 24); - break; - - case 1: - word = (reg_val & 0xffff0000) | ((unsigned)(word & 0xffff0000) >> 16); - break; - - case 2: - word = (reg_val & 0xff000000) | ((unsigned)(word & 0xffffff00) >> 8); - break; - - case 3: - word = word; - break; - } -#else - switch (byte) - { - case 0: - break; - - case 1: - word = (reg_val & 0xff000000) | ((word & 0xffffff00) >> 8); - break; - - case 2: - word = (reg_val & 0xffff0000) | ((word & 0xffff0000) >> 16); - break; - - case 3: - word = (reg_val & 0xffffff00) | ((word & 0xff000000) >> 24); - break; - } -#endif - LOAD_INST_BASE (&R[RT (inst)], word); - break; - } - - case Y_MADD_OP: - case Y_MADDU_OP: - { - reg_word lo = LO, hi = HI; - reg_word tmp; - if (OPCODE (inst) == Y_MADD_OP) - { - signed_multiply(R[RS (inst)], R[RT (inst)]); - } - else /* Y_MADDU_OP */ - { - unsigned_multiply(R[RS (inst)], R[RT (inst)]); - } - tmp = lo + LO; - if ((unsigned)tmp < (unsigned)LO || (unsigned)tmp < (unsigned)lo) - { - /* Addition of low-order word overflows */ - hi += 1; - } - LO = tmp; - HI = hi + HI; - break; - } - - case Y_MFC0_OP: - R[RT (inst)] = CPR[0][FS (inst)]; - break; - - case Y_MFC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_MFHI_OP: - R[RD (inst)] = HI; - break; - - case Y_MFLO_OP: - R[RD (inst)] = LO; - break; - - case Y_MOVN_OP: - if (R[RT (inst)] != 0) - R[RD (inst)] = R[RS (inst)]; - break; - - case Y_MOVZ_OP: - if (R[RT (inst)] == 0) - R[RD (inst)] = R[RS (inst)]; - break; - - case Y_MSUB_OP: - case Y_MSUBU_OP: - { - reg_word lo = LO, hi = HI; - reg_word tmp; - - if (OPCODE (inst) == Y_MSUB_OP) - { - signed_multiply(R[RS (inst)], R[RT (inst)]); - } - else /* Y_MSUBU_OP */ - { - unsigned_multiply(R[RS (inst)], R[RT (inst)]); - } - - tmp = lo - LO; - if ((unsigned)LO > (unsigned)lo) - { - /* Subtraction of low-order word borrows */ - hi -= 1; - } - LO = tmp; - HI = hi - HI; - break; - } - - case Y_MTC0_OP: - CPR[0][FS (inst)] = R[RT (inst)]; - switch (FS (inst)) - { - case CP0_Compare_Reg: - CP0_Cause &= ~CP0_Cause_IP7; /* Writing clears HW interrupt 5 */ - break; - - case CP0_Status_Reg: - CP0_Status &= CP0_Status_Mask; - CP0_Status |= ((CP0_Status_CU & 0x30000000) | CP0_Status_UM); - break; - - case CP0_Cause_Reg: - CPR[0][FS (inst)] &= CP0_Cause_Mask; - break; - - case CP0_Config_Reg: - CPR[0][FS (inst)] &= CP0_Config_Mask; - break; - - default: - break; - } - break; - - case Y_MTC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_MTHI_OP: - HI = R[RS (inst)]; - break; - - case Y_MTLO_OP: - LO = R[RS (inst)]; - break; - - case Y_MUL_OP: - signed_multiply(R[RS (inst)], R[RT (inst)]); - R[RD (inst)] = LO; - break; - - case Y_MULT_OP: - signed_multiply(R[RS (inst)], R[RT (inst)]); - break; - - case Y_MULTU_OP: - unsigned_multiply (R[RS (inst)], R[RT (inst)]); - break; - - case Y_NOR_OP: - R[RD (inst)] = ~ (R[RS (inst)] | R[RT (inst)]); - break; - - case Y_OR_OP: - R[RD (inst)] = R[RS (inst)] | R[RT (inst)]; - break; - - case Y_ORI_OP: - R[RT (inst)] = R[RS (inst)] | (0xffff & IMM (inst)); - break; - - case Y_PREF_OP: - break; /* Memory details not implemented */ - - case Y_RFE_OP: -#ifdef MIPS1 - /* This is MIPS-I, not compatible with MIPS32 or the - definition of the bits in the CP0 Status register in that - architecture. */ - CP0_Status = (CP0_Status & 0xfffffff0) | ((CP0_Status & 0x3c) >> 2); -#else - RAISE_EXCEPTION (ExcCode_RI, {}); /* Not MIPS32 instruction */ -#endif - break; - - case Y_SB_OP: - set_mem_byte (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]); - break; - - case Y_SC_OP: - /* Uniprocessor, so instruction is just a store */ - set_mem_word (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]); - break; - - case Y_SDC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_SH_OP: - set_mem_half (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]); - break; - - case Y_SLL_OP: - { - int shamt = SHAMT (inst); - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = R[RT (inst)] << shamt; - else - R[RD (inst)] = R[RT (inst)]; - break; - } - - case Y_SLLV_OP: - { - int shamt = (R[RS (inst)] & 0x1f); - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = R[RT (inst)] << shamt; - else - R[RD (inst)] = R[RT (inst)]; - break; - } - - case Y_SLT_OP: - if (R[RS (inst)] < R[RT (inst)]) - R[RD (inst)] = 1; - else - R[RD (inst)] = 0; - break; - - case Y_SLTI_OP: - if (R[RS (inst)] < (short) IMM (inst)) - R[RT (inst)] = 1; - else - R[RT (inst)] = 0; - break; - - case Y_SLTIU_OP: - { - int x = (short) IMM (inst); - - if ((u_reg_word) R[RS (inst)] < (u_reg_word) x) - R[RT (inst)] = 1; - else - R[RT (inst)] = 0; - break; - } - - case Y_SLTU_OP: - if ((u_reg_word) R[RS (inst)] < (u_reg_word) R[RT (inst)]) - R[RD (inst)] = 1; - else - R[RD (inst)] = 0; - break; - - case Y_SRA_OP: - { - int shamt = SHAMT (inst); - reg_word val = R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = val >> shamt; - else - R[RD (inst)] = val; - break; - } - - case Y_SRAV_OP: - { - int shamt = R[RS (inst)] & 0x1f; - reg_word val = R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = val >> shamt; - else - R[RD (inst)] = val; - break; - } - - case Y_SRL_OP: - { - int shamt = SHAMT (inst); - u_reg_word val = R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = val >> shamt; - else - R[RD (inst)] = val; - break; - } - - case Y_SRLV_OP: - { - int shamt = R[RS (inst)] & 0x1f; - u_reg_word val = R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - R[RD (inst)] = val >> shamt; - else - R[RD (inst)] = val; - break; - } - - case Y_SUB_OP: - { - reg_word vs = R[RS (inst)], vt = R[RT (inst)]; - reg_word diff = vs - vt; - - if (SIGN_BIT (vs) != SIGN_BIT (vt) - && SIGN_BIT (vs) != SIGN_BIT (diff)) - RAISE_EXCEPTION (ExcCode_Ov, break); - R[RD (inst)] = diff; - break; - } - - case Y_SUBU_OP: - R[RD (inst)] = (u_reg_word)R[RS (inst)]-(u_reg_word)R[RT (inst)]; - break; - - case Y_SW_OP: - set_mem_word (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]); - break; - - case Y_SWC2_OP: - RAISE_EXCEPTION (ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_SWL_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - mem_word data; - reg_word reg = R[RT (inst)]; - int byte = addr & 0x3; - - data = read_mem_word (addr & 0xfffffffc); -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - data = reg; - break; - - case 1: - data = (data & 0xff000000) | (reg >> 8 & 0xffffff); - break; - - case 2: - data = (data & 0xffff0000) | (reg >> 16 & 0xffff); - break; - - case 3: - data = (data & 0xffffff00) | (reg >> 24 & 0xff); - break; - } -#else - switch (byte) - { - case 0: - data = (data & 0xffffff00) | (reg >> 24 & 0xff); - break; - - case 1: - data = (data & 0xffff0000) | (reg >> 16 & 0xffff); - break; - - case 2: - data = (data & 0xff000000) | (reg >> 8 & 0xffffff); - break; - - case 3: - data = reg; - break; - } -#endif - set_mem_word (addr & 0xfffffffc, data); - break; - } - - case Y_SWR_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - mem_word data; - reg_word reg = R[RT (inst)]; - int byte = addr & 0x3; - - data = read_mem_word (addr & 0xfffffffc); -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - data = ((reg << 24) & 0xff000000) | (data & 0xffffff); - break; - - case 1: - data = ((reg << 16) & 0xffff0000) | (data & 0xffff); - break; - - case 2: - data = ((reg << 8) & 0xffffff00) | (data & 0xff) ; - break; - - case 3: - data = reg; - break; - } -#else - switch (byte) - { - case 0: - data = reg; - break; - - case 1: - data = ((reg << 8) & 0xffffff00) | (data & 0xff) ; - break; - - case 2: - data = ((reg << 16) & 0xffff0000) | (data & 0xffff); - break; - - case 3: - data = ((reg << 24) & 0xff000000) | (data & 0xffffff); - break; - } -#endif - set_mem_word (addr & 0xfffffffc, data); - break; - } - - case Y_SYNC_OP: - break; /* Memory details not implemented */ - - case Y_SYSCALL_OP: - if (!do_syscall ()) - return false; - break; - - case Y_TEQ_OP: - if (R[RS (inst)] == R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TEQI_OP: - if (R[RS (inst)] == IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TGE_OP: - if (R[RS (inst)] >= R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TGEI_OP: - if (R[RS (inst)] >= IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TGEIU_OP: - if ((u_reg_word)R[RS (inst)] >= (u_reg_word)IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TGEU_OP: - if ((u_reg_word)R[RS (inst)] >= (u_reg_word)R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TLBP_OP: - RAISE_EXCEPTION(ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBR_OP: - RAISE_EXCEPTION(ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBWI_OP: - RAISE_EXCEPTION(ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBWR_OP: - RAISE_EXCEPTION(ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLT_OP: - if (R[RS (inst)] < R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TLTI_OP: - if (R[RS (inst)] < IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TLTIU_OP: - if ((u_reg_word)R[RS (inst)] < (u_reg_word)IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TLTU_OP: - if ((u_reg_word)R[RS (inst)] < (u_reg_word)R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TNE_OP: - if (R[RS (inst)] != R[RT (inst)]) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_TNEI_OP: - if (R[RS (inst)] != IMM (inst)) - RAISE_EXCEPTION(ExcCode_Tr, {}); - break; - - case Y_XOR_OP: - R[RD (inst)] = R[RS (inst)] ^ R[RT (inst)]; - break; - - case Y_XORI_OP: - R[RT (inst)] = R[RS (inst)] ^ (0xffff & IMM (inst)); - break; - - - /* FPA Operations */ - - case Y_ABS_S_OP: - SET_FPR_S (FD (inst), fabs (FPR_S (FS (inst)))); - break; - - case Y_ABS_D_OP: - SET_FPR_D (FD (inst), fabs (FPR_D (FS (inst)))); - break; - - case Y_ADD_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst)) + FPR_S (FT (inst))); - /* Should trap on inexact/overflow/underflow */ - break; - - case Y_ADD_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst)) + FPR_D (FT (inst))); - /* Should trap on inexact/overflow/underflow */ - break; - - case Y_BC1F_OP: - case Y_BC1FL_OP: - case Y_BC1T_OP: - case Y_BC1TL_OP: - { - int cc = CC (inst); - int nd = ND (inst); /* 1 => nullify */ - int tf = TF (inst); /* 0 => BC1F, 1 => BC1T */ - BRANCH_INST (FCC(cc) == tf, - PC + IDISP (inst), - nd); - break; - } - - case Y_C_F_S_OP: - case Y_C_UN_S_OP: - case Y_C_EQ_S_OP: - case Y_C_UEQ_S_OP: - case Y_C_OLT_S_OP: - case Y_C_OLE_S_OP: - case Y_C_ULT_S_OP: - case Y_C_ULE_S_OP: - case Y_C_SF_S_OP: - case Y_C_NGLE_S_OP: - case Y_C_SEQ_S_OP: - case Y_C_NGL_S_OP: - case Y_C_LT_S_OP: - case Y_C_NGE_S_OP: - case Y_C_LE_S_OP: - case Y_C_NGT_S_OP: - { - float v1 = FPR_S (FS (inst)), v2 = FPR_S (FT (inst)); - double dv1 = v1, dv2 = v2; - int cond = COND (inst); - int cc = CCFP (inst); - - if (NaN (dv1) || NaN (dv2)) - { - if (cond & COND_IN) - { - RAISE_EXCEPTION (ExcCode_FPE, break); - } - set_fpu_cc (cond, cc, 0, 0, 1); - } - else - { - set_fpu_cc (cond, cc, v1 < v2, v1 == v2, 0); - } - } - break; - - case Y_C_F_D_OP: - case Y_C_UN_D_OP: - case Y_C_EQ_D_OP: - case Y_C_UEQ_D_OP: - case Y_C_OLT_D_OP: - case Y_C_OLE_D_OP: - case Y_C_ULT_D_OP: - case Y_C_ULE_D_OP: - case Y_C_SF_D_OP: - case Y_C_NGLE_D_OP: - case Y_C_SEQ_D_OP: - case Y_C_NGL_D_OP: - case Y_C_LT_D_OP: - case Y_C_NGE_D_OP: - case Y_C_LE_D_OP: - case Y_C_NGT_D_OP: - { - double v1 = FPR_D (FS (inst)), v2 = FPR_D (FT (inst)); - int cond = COND (inst); - int cc = CCFP(inst); - - if (NaN (v1) || NaN (v2)) - { - if (cond & COND_IN) - { - RAISE_EXCEPTION (ExcCode_FPE, break); - } - set_fpu_cc (cond, cc, 0, 0, 1); - } - else - { - set_fpu_cc (cond, cc, v1 < v2, v1 == v2, 0); - } - } - break; - - case Y_CFC1_OP: - R[RT (inst)] = FCR[FS (inst)]; - break; - - case Y_CTC1_OP: - FCR[FS (inst)] = R[RT (inst)]; - - if (FIR_REG == FS (inst)) - { - /* Read only register */ - } - else if (FCSR_REG == FS (inst)) - { - if ((R[RT (inst)] & ~FCSR_MASK) != 0) - /* Trying to set unsupported mode */ - RAISE_EXCEPTION (ExcCode_FPE, {}); - } - break; - - case Y_CEIL_W_D_OP: - { - double val = FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), (int32)ceil (val)); - break; - } - - case Y_CEIL_W_S_OP: - { - double val = (double)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), (int32)ceil (val)); - break; - } - - case Y_CVT_D_S_OP: - { - double val = FPR_S (FS (inst)); - - SET_FPR_D (FD (inst), val); - break; - } - - case Y_CVT_D_W_OP: - { - double val = (double)FPR_W (FS (inst)); - - SET_FPR_D (FD (inst), val); - break; - } - - case Y_CVT_S_D_OP: - { - float val = (float)FPR_D (FS (inst)); - - SET_FPR_S (FD (inst), val); - break; - } - - case Y_CVT_S_W_OP: - { - float val = (float)FPR_W (FS (inst)); - - SET_FPR_S (FD (inst), val); - break; - } - - case Y_CVT_W_D_OP: - { - int val = (int32)FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), val); - break; - } - - case Y_CVT_W_S_OP: - { - int val = (int32)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), val); - break; - } - - case Y_DIV_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst)) / FPR_S (FT (inst))); - break; - - case Y_DIV_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst)) / FPR_D (FT (inst))); - break; - - case Y_FLOOR_W_D_OP: - { - double val = FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), (int32)floor (val)); - break; - } - - case Y_FLOOR_W_S_OP: - { - double val = (double)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), (int32)floor (val)); - break; - } - - case Y_LDC1_OP: - { - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - if ((addr & 0x3) != 0) - RAISE_EXCEPTION (ExcCode_AdEL, CP0_BadVAddr = addr); - - LOAD_INST ((reg_word *) &FPR_S(FT (inst)), - read_mem_word (addr), - 0xffffffff); - LOAD_INST ((reg_word *) &FPR_S(FT (inst) + 1), - read_mem_word (addr + sizeof(mem_word)), - 0xffffffff); - break; - } - - case Y_LWC1_OP: - LOAD_INST ((reg_word *) &FPR_S(FT (inst)), - read_mem_word (R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_MFC1_OP: - { - float val = FPR_S(FS (inst)); - reg_word *vp = (reg_word *) &val; - - R[RT (inst)] = *vp; /* Fool coercion */ - break; - } - - case Y_MOV_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - - case Y_MOV_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - - case Y_MOVF_OP: - { - int cc = CC (inst); - if (FCC(cc) == 0) - R[RD (inst)] = R[RS (inst)]; - break; - } - - case Y_MOVF_D_OP: - { - int cc = CC (inst); - if (FCC(cc) == 0) - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - } - - case Y_MOVF_S_OP: - { - int cc = CC (inst); - if (FCC(cc) == 0) - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - - } - - case Y_MOVN_D_OP: - { - if (R[RT (inst)] != 0) - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - } - - case Y_MOVN_S_OP: - { - if (R[RT (inst)] != 0) - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - } - - case Y_MOVT_OP: - { - int cc = CC (inst); - if (FCC(cc) != 0) - R[RD (inst)] = R[RS (inst)]; - break; - } - - case Y_MOVT_D_OP: - { - int cc = CC (inst); - if (FCC(cc) != 0) - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - } - - case Y_MOVT_S_OP: - { - int cc = CC (inst); - if (FCC(cc) != 0) - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - - } - - case Y_MOVZ_D_OP: - { - if (R[RT (inst)] == 0) - SET_FPR_D (FD (inst), FPR_D (FS (inst))); - break; - } - - case Y_MOVZ_S_OP: - { - if (R[RT (inst)] == 0) - SET_FPR_S (FD (inst), FPR_S (FS (inst))); - break; - - } - - case Y_MTC1_OP: - { - reg_word word = R[RT (inst)]; - float *wp = (float *) &word; - - SET_FPR_S(FS (inst), *wp); /* fool coercion */ - break; - } - - case Y_MUL_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst)) * FPR_S (FT (inst))); - break; - - case Y_MUL_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst)) * FPR_D (FT (inst))); - break; - - case Y_NEG_S_OP: - SET_FPR_S (FD (inst), -FPR_S (FS (inst))); - break; - - case Y_NEG_D_OP: - SET_FPR_D (FD (inst), -FPR_D (FS (inst))); - break; - - case Y_ROUND_W_D_OP: - { - double val = FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), (int32)(val + 0.5)); /* Casting truncates */ - break; - } - - case Y_ROUND_W_S_OP: - { - double val = (double)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), (int32)(val + 0.5)); /* Casting truncates */ - break; - } - - case Y_SDC1_OP: - { - double val = FPR_D (RT (inst)); - reg_word *vp = (reg_word*)&val; - mem_addr addr = R[BASE (inst)] + IOFFSET (inst); - if ((addr & 0x3) != 0) - RAISE_EXCEPTION (ExcCode_AdEL, CP0_BadVAddr = addr); - - set_mem_word (addr, *vp); - set_mem_word (addr + sizeof(mem_word), *(vp + 1)); - break; - } - - case Y_SQRT_D_OP: - SET_FPR_D (FD (inst), sqrt (FPR_D (FS (inst)))); - break; - - case Y_SQRT_S_OP: - SET_FPR_S (FD (inst), sqrt (FPR_S (FS (inst)))); - break; - - case Y_SUB_S_OP: - SET_FPR_S (FD (inst), FPR_S (FS (inst)) - FPR_S (FT (inst))); - break; - - case Y_SUB_D_OP: - SET_FPR_D (FD (inst), FPR_D (FS (inst)) - FPR_D (FT (inst))); - break; - - case Y_SWC1_OP: - { - float val = FPR_S(RT (inst)); - reg_word *vp = (reg_word *) &val; - - set_mem_word (R[BASE (inst)] + IOFFSET (inst), *vp); - break; - } - - case Y_TRUNC_W_D_OP: - { - double val = FPR_D (FS (inst)); - - SET_FPR_W (FD (inst), (int32)val); /* Casting truncates */ - break; - } - - case Y_TRUNC_W_S_OP: - { - double val = (double)FPR_S (FS (inst)); - - SET_FPR_W (FD (inst), (int32)val); /* Casting truncates */ - break; - } - - default: - fatal_error ("Unknown instruction type: %d\n", OPCODE (inst)); - break; - } - - /* After instruction executes: */ - PC += BYTES_PER_WORD; - - if (exception_occurred) - { - handle_exception (); - } - } /* End: for (step = 0; ... */ - } /* End: for ( ; steps_to_run > 0 ... */ - - /* Executed enought steps, return, but are able to continue. */ - return true; -} - - -#ifdef _WIN32 -void CALLBACK -timer_completion_routine(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue) -{ - lpArgToCompletionRoutine = lpArgToCompletionRoutine; - dwTimerLowValue = dwTimerLowValue; - dwTimerHighValue = dwTimerHighValue; - bump_CP0_timer (); -} -#endif - - -/* Increment CP0 Count register and test if it matches the Compare - register. If so, cause an interrupt. */ - -static void -bump_CP0_timer () -{ - CP0_Count += 1; - if (CP0_Count == CP0_Compare) - { - RAISE_INTERRUPT (7); - } -} - - -static void -start_CP0_timer () -{ -#ifdef _WIN32 - HANDLE timer = CreateWaitableTimer(NULL, TRUE, TEXT("SPIMTimer")); - if (NULL == timer) - { - error ("CreateWaitableTimer failed"); - } - else - { - LARGE_INTEGER interval; - interval.QuadPart = -10000 * TIMER_TICK_MS; /* Unit is 100 nsec */ - - if (!SetWaitableTimer (timer, &interval, 1, timer_completion_routine, 0, FALSE)) - { - error ("SetWaitableTimer failed"); - } - } -#else - /* Should use ITIMER_VIRTUAL delivering SIGVTALRM, but that does not seem - to work under Cygwin, so we'll adopt the lowest common denominator and - use real time. - - We ignore the resulting signal, however, and read the timer with getitimer, - since signals interrupt I/O calls, such as read, and make user - interaction with SPIM work very poorly. Since speed isn't an important - aspect of SPIM, polling isn't a big deal. */ - if (SIG_ERR == signal (SIGALRM, SIG_IGN)) - { - perror ("signal failed"); - } - else - { - struct itimerval time; - if (-1 == getitimer (ITIMER_REAL, &time)) - { - perror ("getitmer failed"); - } - if (time.it_value.tv_usec == 0 && time.it_value.tv_sec == 0) - { - /* Timer is expired or has not been started. - Start a non-periodic timer for TIMER_TICK_MS microseconds. */ - time.it_interval.tv_sec = 0; - time.it_interval.tv_usec = 0; - time.it_value.tv_sec = 0; - time.it_value.tv_usec = TIMER_TICK_MS * 1000; - if (-1 == setitimer (ITIMER_REAL, &time, NULL)) - { - perror ("setitmer failed"); - } - } - } -#endif -} - - -/* Multiply two 32-bit numbers, V1 and V2, to produce a 64 bit result in - the HI/LO registers. The algorithm is high-school math: - - A B - x C D - ------ - AD || BD - AC || CB || 0 - - where A and B are the high and low short words of V1, C and D are the short - words of V2, AD is the product of A and D, and X || Y is (X << 16) + Y. - Since the algorithm is programmed in C, we need to be careful not to - overflow. */ - -static void -unsigned_multiply (reg_word v1, reg_word v2) -{ - u_reg_word a, b, c, d; - u_reg_word bd, ad, cb, ac; - u_reg_word mid, mid2, carry_mid = 0; - - a = (v1 >> 16) & 0xffff; - b = v1 & 0xffff; - c = (v2 >> 16) & 0xffff; - d = v2 & 0xffff; - - bd = b * d; - ad = a * d; - cb = c * b; - ac = a * c; - - mid = ad + cb; - if (mid < ad || mid < cb) - /* Arithmetic overflow or carry-out */ - carry_mid = 1; - - mid2 = mid + ((bd >> 16) & 0xffff); - if (mid2 < mid || mid2 < ((bd >> 16) & 0xffff)) - /* Arithmetic overflow or carry-out */ - carry_mid += 1; - - LO = (bd & 0xffff) | ((mid2 & 0xffff) << 16); - HI = ac + (carry_mid << 16) + ((mid2 >> 16) & 0xffff); -} - - -static void -signed_multiply (reg_word v1, reg_word v2) -{ - int neg_sign = 0; - - if (v1 < 0) - { - v1 = - v1; - neg_sign = 1; - } - if (v2 < 0) - { - v2 = - v2; - neg_sign = ! neg_sign; - } - - unsigned_multiply (v1, v2); - if (neg_sign) - { - LO = ~ LO; - HI = ~ HI; - LO += 1; - if (LO == 0) - HI += 1; - } -} - -static void -set_fpu_cc (int cond, int cc, int less, int equal, int unordered) -{ - int result = 0; - - if (cond & COND_LT) result |= less; - if (cond & COND_EQ) result |= equal; - if (cond & COND_UN) result |= unordered; - - SET_FCC(cc, result); -} - - -void -raise_exception (int excode) -{ - if (ExcCode_Int != excode - || ((CP0_Status & CP0_Status_IE) /* Allow interrupt if IE and !EXL */ - && !(CP0_Status & CP0_Status_EXL))) - { - /* Ignore interrupt exception when interrupts disabled. */ - exception_occurred = 1; - if (running_in_delay_slot) - { - /* In delay slot */ - if ((CP0_Status & CP0_Status_EXL) == 0) - { - /* Branch's addr */ - CP0_EPC = ROUND_DOWN (PC - BYTES_PER_WORD, BYTES_PER_WORD); - /* Set BD bit to record that instruction is in delay slot */ - CP0_Cause |= CP0_Cause_BD; - } - } - else - { - /* Not in delay slot */ - if ((CP0_Status & CP0_Status_EXL) == 0) - { - /* Faulting instruction's address */ - CP0_EPC = ROUND_DOWN (PC, BYTES_PER_WORD); - } - } - /* ToDo: set CE field of Cause register to coprocessor causing exception */ - - /* Record cause of exception */ - CP0_Cause = (CP0_Cause & ~CP0_Cause_ExcCode) | (excode << 2); - - /* Turn on EXL bit to prevent subsequent interrupts from affecting EPC */ - CP0_Status |= CP0_Status_EXL; - -#ifdef MIPS1 - CP0_Status = (CP0_Status & 0xffffffc0) | ((CP0_Status & 0xf) << 2); -#endif - } -} diff --git a/spim-qtbase/CPU/run.h b/spim-qtbase/CPU/run.h deleted file mode 100755 index 934615a..0000000 --- a/spim-qtbase/CPU/run.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM instructions. - - Copyright (c) 1990-2021, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -bool run_spim (mem_addr initial_PC, int steps, bool display); diff --git a/spim-qtbase/CPU/scanner.h b/spim-qtbase/CPU/scanner.h deleted file mode 100755 index 3f97644..0000000 --- a/spim-qtbase/CPU/scanner.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to lexical scanner. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions (besides yylex): */ - -void initialize_scanner (FILE *in_file); -void push_scanner (FILE *in_file); -void pop_scanner (); -char* erroneous_line (); -void scanner_start_line (); -int register_name_to_number (char *name); -char *source_line (); -int yylex (); - -/* Exported Variables: */ - -/* This flag tells the scanner to treat the next sequence of letters - etc as an identifier and not look it up as an opcode. It permits us - to use opcodes as symbols in most places. However, because of the - LALR(1) lookahead, it does not work for labels. */ - -extern int only_id; - -typedef intptr_union yylval_t; -#define YYSTYPE yylval_t -extern YYSTYPE yylval; /* Value of token from YYLEX */ - -extern int line_no; /* Line number in input file*/ diff --git a/spim-qtbase/CPU/scanner.l b/spim-qtbase/CPU/scanner.l deleted file mode 100755 index 6af2dbb..0000000 --- a/spim-qtbase/CPU/scanner.l +++ /dev/null @@ -1,733 +0,0 @@ -%{ -/* SPIM S20 MIPS simulator. - Lexical scanner. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "sym-tbl.h" -#include "parser.h" -#include "scanner.h" -#include "parser_yacc.h" - -#ifdef _WIN32 -#include -#else -#include -#endif - -#define YY_NO_UNISTD_H - -/* Exported Variables: */ - -int only_id; -int line_no; /* Line number in input file*/ - - -/* Local Variables: */ - -/* Track which line we are reading and where it began in the buffer. */ -static int current_line_no = 0; - -static char *current_line = NULL; - - -static double scan_float; /* Where FP values are kept */ - -static int line_returned = 0; /* Returned current line yet? */ - -static int eof_returned = 0; /* Return EOF token yet? */ - - -/* Local functions: */ - -static int check_keyword (char *id, int allow_pseudo_ops); -static char *copy_str (char *str, int chop); -static char scan_escape (char **str); - - -#undef yywrap - -%} - -%% - -[ \t] { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - } - - -[\n] { - line_no += 1; - return (Y_NL); - } - -[\r] { /* Ignore carrage returns */ } - -[;] { - return (Y_NL); - } - - -[\001] { /* Marker character inserted to allow scanner to - return Y_EOF before returning hard EOF. */ - return (Y_EOF); - } - -"#".* { - /* Ignore comments */ - } - - -(-[0-9]+)|([0-9]+) { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.i = atoi (yytext); - return (Y_INT); - } - - -((0x)|(-0x))[0-9A-Fa-f]+ { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - if (*yytext == '-') - { - sscanf(yytext+3, "%x", (unsigned int*)&(yylval.i)); - yylval.i = -yylval.i; - } - else - { - sscanf(yytext+2, "%x", (unsigned int*)&(yylval.i)); - } - return (Y_INT); - } - - -(\+|\-)?[0-9]+[\.\,\'][0-9]+(e)?(\+|\-)?[0-9]* { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - scan_float = atof (yytext); - yylval.p = (double*) &scan_float; - return (Y_FP); - } - - -[a-zA-Z_\.][a-zA-Z0-9_\.]* { - int token = check_keyword (yytext, - !bare_machine - && accept_pseudo_insts); - label *l; - - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (!only_id && token != 0) - { - /* Keyword */ - yylval.i = token; - current_line = yytext; - return (token); - } - - if (only_id && token != 0) - yyerror ("Cannot use opcodes as labels"); - - if ((l = label_is_defined (yytext)) != NULL - && l->const_flag) - { - /* Defined label */ - yylval.i = (int) l->addr; - return (Y_INT); - } - else - { - /* Not-yet defined label */ - yylval.p = (char*) str_copy (yytext); - return (Y_ID); - } - } - - -\$[a-zA-Z0-9_\.$]+ { - int reg_no = register_name_to_number (yytext + 1); - - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (reg_no != -1 - && *(yytext + 1) == 'f' - && *(yytext + 2) != 'p') - { - /* Floating point register ($f0) */ - yylval.i = reg_no; - return (Y_FP_REG); - } - - if (0 <= reg_no && reg_no < R_LENGTH) - { - /* Register ($r0) */ - yylval.i = reg_no; - return (Y_REG); - } - else - { - /* Otherwise, an integer or identifier */ - label *l = label_is_defined (yytext); - - if (l != NULL && l->const_flag) - { - yylval.i = (int) l->addr; - return (Y_INT); - } - else - { - yylval.p = (char*) str_copy (yytext); - return (Y_ID); - } - } - } - - -[\*\/:()+-]|">"|"=" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - return (*yytext); - } - - -"," { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - /* Skip commas */ - } - -"?" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.p = (char*) str_copy (yytext); - /* For top level */ - return (Y_ID); - } - - -\"(([^""])|(\\\"))*\" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.p = (char*) copy_str (yytext + 1, 1); - return (Y_STR); - } - -\'(([^''])|(\\[^'']))\' { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (*(yytext + 1) == '\\') - { - char *escape = yytext + 2; - yylval.i = (int) scan_escape (&escape); - } - else - { - yylval.i = (int) *(yytext + 1); - } - - return (Y_INT); - } - -. { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yyerror ("Unknown character"); - } - - -%% - - - -void -initialize_scanner (FILE *in_file) -{ - if (yyin != in_file) - { - push_scanner (in_file); - } - yyin = in_file; - -#ifdef FLEX_SCANNER - yyrestart(in_file); -#define YY_FLEX_VERSION (YY_FLEX_MAJOR_VERSION * 1000 + YY_FLEX_MINOR_VERSION * 100 + YY_FLEX_SUBMINOR_VERSION) -#if YY_FLEX_VERSION >= 2533 - /* flex 2.5.33 flipped the polarity of this flag (sigh) */ - yy_init = 0; -#else - yy_init = 1; -#endif -#endif - - line_no = 1; - current_line = NULL; - line_returned = 0; - eof_returned = 0; -} - -void -push_scanner (FILE *in_file) -{ - YY_BUFFER_STATE buf = yy_create_buffer (in_file, YY_BUF_SIZE); - yypush_buffer_state (buf); -} - -void -pop_scanner () -{ - yypop_buffer_state (); -} - -void -scanner_start_line () -{ - current_line = NULL; - line_returned = 0; -} - - -/* This is a work-around for a bug in flex v 2.5.31 (but not earlier or - later versions such as 2.5.4) that left this symbol undefined. */ - -#ifndef yytext_ptr -#define yytext_ptr yytext -#endif - - -/* Use yywrap to insert a marker character, which causes the - scanner to return Y_EOF, before return a hard EOF. This - wouldn't be necessary, except that bison does not allow - the parser to use EOF (= 0) as a non-terminal */ - -int yywrap() -{ - if (eof_returned) - return (1); - else - { - unput ('\001'); - eof_returned = 1; -#ifdef FLEX_SCANNER - yy_did_buffer_switch_on_eof = 1; -#endif - return (0); - } -} - - -/* A backslash has just been read, return the character designated by *STR. */ - -static char -scan_escape (char **str) -{ - char first = **str; - *str += 1; - switch (first) - { - case 'a': return '\a'; - case 'b': return '\b'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case '\\': return '\\'; - case '"': return '"'; - case '\'': return '\''; - - case 'x': - case 'X': - { - char c1 = **str, c2 = *(*str + 1); - int b = 0; - - if ('0' <= c1 && c1 <= '9') b = c1 - '0'; - else if ('A' <= c1 && c1 <= 'F') b = c1 - 'A' + 10; - else if ('a' <= c1 && c1 <= 'f') b = c1 - 'a' + 10; - else yyerror ("Bad character in \\X construct in string"); - - b <<= 4; - if ('0' <= c2 && c2 <= '9') b += c2 - '0'; - else if ('A' <= c2 && c2 <= 'F') b += c2 - 'A' + 10; - else if ('a' <= c2 && c2 <= 'f') b += c2 - 'a' + 10; - else yyerror ("Bad character in \\X construct in string"); - - *str += 2; - return (char) b; - } - - default: - { - char message[] = "Bad character \\X"; - message[strlen (message) - 1] = first; - yyerror (message); - return '\0'; - } - } -} - - -/* Return a freshly-allocated copy of STRING with the last CHOP - characters removed. */ - -static char * -copy_str (char *str, int chop) -{ - int new_len = strlen (str) - chop; - char *new_str = (char *) xmalloc (new_len + 1), *n; - - for (n = new_str; *str != '\0' && new_len > 0; new_len -= 1) - if (*str == '\\') - switch (*(str + 1)) - { - case 'n': - { - *n ++ = '\n'; - str += 2; - new_len -= 1; - continue; - } - case 't': - { - *n ++ = '\t'; - str += 2; - new_len -= 1; - continue; - } - case '"': - { - *n ++ = '"'; - str += 2; - new_len -= 1; - continue; - } - case '0': /* \nnn */ - case '1': - case '2': - case '3': - { - char c2 = *(str + 2), c3 = *(str + 3); - int b = (*(str + 1) - '0') << 3; - - if ('0' <= c2 && c2 <= '7') - b += (c2 - '0') << 3; - else - yyerror ("Bad character in \\ooo construct in string"); - - if ('0' <= c3 && c3 <= '7') - b += c3 - '0'; - else - yyerror ("Bad character in \\ooo construct in string"); - - *n ++ = (char) b; - str += 4; - new_len -= 3; - continue; - } - case 'X': - { - char c2 = *(str + 2), c3 = *(str + 3); - int b = 0; - - if ('0' <= c2 && c2 <= '9') - b = c2 - '0'; - else if ('A' <= c2 && c2 <= 'F') - b = c2 - 'A' + 10; - else - yyerror ("Bad character in \\X construct in string"); - - b <<= 4; - if ('0' <= c3 && c3 <= '9') - b += c3 - '0'; - else if ('A' <= c3 && c3 <= 'F') - b += c3 - 'A' + 10; - else - yyerror ("Bad character in \\X construct in string"); - - *n ++ = (char) b; - str += 4; - new_len -= 3; - continue; - } - default: - { - *n ++ = *str ++; - continue; - } - } - else - *n ++ = *str ++; - - *n = '\0'; - return (new_str); -} - - -/* On a parse error, write out the current line and print a caret (^) - below the point at which the error occured. Also, reset the input - stream to the begining of the next line. */ - -char* -erroneous_line () -{ - int prefix_length = yytext - current_line; - int i, c; - str_stream ss; - - ss_init (&ss); - - if (current_line == NULL) return ss_to_string (&ss); - - /* Print part of line that has been consumed. */ - ss_printf (&ss, " "); - if (0 <= prefix_length) - { - /* yytext and current_line point to same line */ - c = *(current_line + prefix_length); - *(current_line + prefix_length) = '\0'; - ss_printf (&ss, "%s", current_line); - *(current_line + prefix_length) = (char)c; - ss_printf (&ss, "%s", yytext); - } - else - { - /* yytext and current_line point to different lines */ - ss_printf (&ss, "%s", current_line); - prefix_length = strlen(current_line); - } - - /* Flush the rest of the line (not consumed) from lex input. */ - if (*yytext != '\n') - { -#ifdef __cplusplus - while ((c = yyinput ()) != '\n' && c != EOF && c != 1) -#else - while ((c = input ()) != '\n' && c != EOF && c != 1) -#endif - { - ss_printf (&ss, "%c", c); - } - if (c == '\n') unput ('\n'); - current_line = NULL; - } - - /* Print marker to point at which consumption stopped. */ - ss_printf (&ss, "\n "); - for (i = 0; i < prefix_length; i ++) ss_printf (&ss, " "); - ss_printf (&ss, "^\n"); - - return ss_to_string (&ss); -} - - -static name_val_val keyword_tbl [] = { -#undef OP -#define OP(NAME, OPCODE, TYPE, R_OPCODE) {NAME, OPCODE, TYPE}, -#include "op.h" -}; - - -static int -check_keyword (char *id, int allow_pseudo_ops) -{ - name_val_val *entry = - map_string_to_name_val_val (keyword_tbl, - sizeof(keyword_tbl) / sizeof (name_val_val), - id); - if (entry == NULL) - return (0); - else if (!allow_pseudo_ops && entry->value2 == PSEUDO_OP) - return (0); - else - return (entry->value1); -} - - -static name_val_val register_tbl [] = { - {"a0", 4, 0}, - {"a1", 5, 0}, - {"a2", 6, 0}, - {"a3", 7, 0}, - {"at", 1, 0}, - {"fp", 30, 0}, - {"gp", 28, 0}, - {"k0", 26, 0}, - {"k1", 27, 0}, - {"kt0", 26, 0}, - {"kt1", 27, 0}, - {"ra", 31, 0}, - {"s0", 16, 0}, - {"s1", 17, 0}, - {"s2", 18, 0}, - {"s3", 19, 0}, - {"s4", 20, 0}, - {"s5", 21, 0}, - {"s6", 22, 0}, - {"s7", 23, 0}, - {"s8", 30, 0}, - {"sp", 29, 0}, - {"t0", 8, 0}, - {"t1", 9, 0}, - {"t2", 10, 0}, - {"t3", 11, 0}, - {"t4", 12, 0}, - {"t5", 13, 0}, - {"t6", 14, 0}, - {"t7", 15, 0}, - {"t8", 24, 0}, - {"t9", 25, 0}, - {"v0", 2, 0}, - {"v1", 3, 0}, - {"zero", 0, 0} -}; - -int -register_name_to_number (char *name) -{ - int c1 = *name, c2 = *(name + 1); - - if ('0' <= c1 && c1 <= '9' - && (c2 == '\0' || (('0' <= c2 && c2 <= '9') && *(name + 2) == '\0'))) - return (atoi (name)); - else if (c1 == 'f' && c2 >= '0' && c2 <= '9') - return atoi (name + 1); - else - { - name_val_val *entry = - map_string_to_name_val_val (register_tbl, - sizeof (register_tbl) / sizeof (name_val_val), - name); - if (entry == NULL) - return (-1); - else - return (entry->value1); - } -} - - -/* Exactly once, return the current source line, as a printable string - with a line number. Subsequent calls receive NULL instead of the - line. */ - -char * -source_line () -{ - if (line_returned) - return (NULL); - else if (current_line == NULL) /* Error on line */ - return (NULL); - else - { - char *eol1, c1; - char *null1 = NULL; - char *r; - - /* Find end of line: */ - for (eol1 = current_line; *eol1 != '\0' && *eol1 != '\n'; ) eol1 += 1; - -#ifdef FLEX_SCANNER - /* Ran into null byte, inserted by yylex. In necessary, look further - for newline. (This only works for scanners produced by flex. Other - versions of lex need similar code, or source code lines will end - early. */ - if (*eol1 == '\0' && yy_hold_char != '\n') - { - null1 = eol1; - *eol1 = yy_hold_char; - for ( ; *eol1 != '\0' && *eol1 != '\n'; ) - eol1 += 1; - } -#endif - - /* Save end-of-line character and null terminate string so it can - be printed. */ - c1 = *eol1; - *eol1 = '\0'; - - r = (char *) xmalloc (eol1 - current_line + 10); - sprintf (r, "%d: %s", current_line_no, current_line); - - /* Restore end-of-line character and, if necessary, yylex's null byte. */ - *eol1 = c1; - if (null1 != NULL) - { - *null1 = '\0'; - } - line_returned = 1; - return ((char *) r); - } -} diff --git a/spim-qtbase/CPU/spim-syscall.h b/spim-qtbase/CPU/spim-syscall.h deleted file mode 100644 index f350f07..0000000 --- a/spim-qtbase/CPU/spim-syscall.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPIM S20 MIPS simulator. - System calls implemented by simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#define PRINT_INT_SYSCALL 1 -#define PRINT_FLOAT_SYSCALL 2 -#define PRINT_DOUBLE_SYSCALL 3 -#define PRINT_STRING_SYSCALL 4 -#define READ_INT_SYSCALL 5 -#define READ_FLOAT_SYSCALL 6 -#define READ_DOUBLE_SYSCALL 7 -#define READ_STRING_SYSCALL 8 -#define SBRK_SYSCALL 9 -#define EXIT_SYSCALL 10 -#define PRINT_CHARACTER_SYSCALL 11 -#define READ_CHARACTER_SYSCALL 12 - -#define OPEN_SYSCALL 13 -#define READ_SYSCALL 14 -#define WRITE_SYSCALL 15 -#define CLOSE_SYSCALL 16 - -#define EXIT2_SYSCALL 17 diff --git a/spim-qtbase/CPU/spim-utils.cpp b/spim-qtbase/CPU/spim-utils.cpp deleted file mode 100755 index 14ef37e..0000000 --- a/spim-qtbase/CPU/spim-utils.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/* SPIM S20 MIPS simulator. - Misc. routines for SPIM. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include -#include -#include - -#include "spim.h" -#include "version.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "data.h" -#include "reg.h" -#include "mem.h" -#include "scanner.h" -#include "parser.h" -#include "parser_yacc.h" -#include "run.h" -#include "sym-tbl.h" - - -/* Internal functions: */ - -static mem_addr copy_int_to_stack (int n); -static mem_addr copy_str_to_stack (char *s); -static void delete_all_breakpoints (); - - -int exception_occurred; - -int initial_text_size = TEXT_SIZE; - -int initial_data_size = DATA_SIZE; - -mem_addr initial_data_limit = DATA_LIMIT; - -int initial_stack_size = STACK_SIZE; - -mem_addr initial_stack_limit = STACK_LIMIT; - -int initial_k_text_size = K_TEXT_SIZE; - -int initial_k_data_size = K_DATA_SIZE; - -mem_addr initial_k_data_limit = K_DATA_LIMIT; - - - -/* Initialize or reinitialize the state of the machine. */ - -void -initialize_world (char* exception_file_names, bool print_message) -{ - /* Allocate the floating point registers */ - if (FGR == NULL) - FPR = (double *) xmalloc (FPR_LENGTH * sizeof (double)); - /* Allocate the memory */ - make_memory (initial_text_size, - initial_data_size, initial_data_limit, - initial_stack_size, initial_stack_limit, - initial_k_text_size, - initial_k_data_size, initial_k_data_limit); - initialize_registers (); - initialize_inst_tables (); - initialize_symbol_table (); - k_text_begins_at_point (K_TEXT_BOT); - k_data_begins_at_point (K_DATA_BOT); - data_begins_at_point (DATA_BOT); - text_begins_at_point (TEXT_BOT); - - if (exception_file_names != NULL) - { - bool old_bare = bare_machine; - bool old_accept = accept_pseudo_insts; - char *filename; - char *files; - - /* Save machine state */ - bare_machine = false; /* Exception handler uses extended machine */ - accept_pseudo_insts = true; - - /* strtok modifies the string, so we must back up the string prior to use. */ - if ((files = strdup (exception_file_names)) == NULL) - fatal_error ("Insufficient memory to complete.\n"); - - for (filename = strtok (files, ";"); filename != NULL; filename = strtok (NULL, ";")) - { - if (!read_assembly_file (filename)) - fatal_error ("Cannot read exception handler: %s\n", filename); - - if (print_message) - write_output (message_out, "Loaded: %s\n", filename); - } - - free (files); - - /* Restore machine state */ - bare_machine = old_bare; - accept_pseudo_insts = old_accept; - - if (!bare_machine) - { - (void)make_label_global ("main"); /* In case .globl main forgotten */ - (void)record_label ("main", 0, 0); - } - } - initialize_scanner (stdin); - delete_all_breakpoints (); -} - - -void -write_startup_message () -{ - write_output (message_out, "SPIM %s\n", SPIM_VERSION); - write_output (message_out, "Copyright 1990-2021 by James Larus.\n"); - write_output (message_out, "All Rights Reserved.\n"); - write_output (message_out, "SPIM is distributed under a BSD license.\n"); - write_output (message_out, "See the file README for a full copyright notice.\n"); -} - - - -void -initialize_registers () -{ - memclr (FPR, FPR_LENGTH * sizeof (double)); - FGR = (float *) FPR; - FWR = (int *) FPR; - - memclr (R, R_LENGTH * sizeof (reg_word)); - R[REG_SP] = STACK_TOP - BYTES_PER_WORD - 4096; /* Initialize $sp */ - HI = LO = 0; - PC = 0; - - CP0_BadVAddr = 0; - CP0_Count = 0; - CP0_Compare = 0; - CP0_Status = (CP0_Status_CU & 0x30000000) | CP0_Status_IM | CP0_Status_UM; - CP0_Cause = 0; - CP0_EPC = 0; -#ifdef SPIM_BIGENDIAN - CP0_Config = CP0_Config_BE; -#else - CP0_Config = 0; -#endif - - FIR = FIR_W | FIR_D | FIR_S; /* Word, double, & single implemented */ - FCSR = 0x0; -} - - -/* Read file NAME, which should contain assembly code. Return true if - successful and false otherwise. */ - -bool -read_assembly_file (char *name) -{ - FILE *file = fopen (name, "rt"); - - if (file == NULL) - { - error ("Cannot open file: `%s'\n", name); - return false; - } - else - { - initialize_scanner (file); - initialize_parser (name); - - while (!yyparse ()) ; - - fclose (file); - flush_local_labels (!parse_error_occurred); - end_of_assembly_file (); - return true; - } -} - - -mem_addr -starting_address () -{ - return (find_symbol_address (DEFAULT_RUN_LOCATION)); -} - - -#define MAX_ARGS 10000 - -/* Initialize the SPIM stack from a string containing the command line. */ - -void -initialize_stack(const char *command_line) -{ - int argc = 0; - char *argv[MAX_ARGS]; - char *a; - char *args = str_copy((char*)command_line); /* Destructively modify string */ - char *orig_args = args; - - while (*args != '\0') - { - /* Skip leading blanks */ - while (*args == ' ' || *args == '\t') args++; - - /* First non-blank char */ - a = args; - - /* Last non-blank, non-null char */ - while (*args != ' ' && *args != '\t' && *args != '\0') args++; - - /* Terminate word */ - if (a != args) - { - if (*args != '\0') - *args++ = '\0'; /* Null terminate */ - - argv[argc++] = a; - - if (MAX_ARGS == argc) - { - break; /* If too many, ignore rest of list */ - } - } - } - - initialize_run_stack (argc, argv); - free (orig_args); -} - - -/* Initialize the SPIM stack with ARGC, ARGV, and ENVP data. */ - -#ifdef _MSC_VER -#define environ _environ -#endif - -void -initialize_run_stack (int argc, char **argv) -{ - char **p; - extern char **environ; - int i, j = 0, env_j; - mem_addr addrs[10000]; - - - R[REG_SP] = STACK_TOP - 1; /* Initialize $sp */ - - /* Put strings on stack: */ - /* env: */ - for (p = environ; *p != NULL; p++) - addrs[j++] = copy_str_to_stack (*p); - env_j = j; - - /* argv; */ - for (i = 0; i < argc; i++) - addrs[j++] = copy_str_to_stack (argv[i]); - - /* Align stack pointer for word-size data */ - R[REG_SP] = R[REG_SP] & ~3; /* Round down to nearest word */ - R[REG_SP] -= BYTES_PER_WORD; /* First free word on stack */ - R[REG_SP] = R[REG_SP] & ~7; /* Double-word align stack-pointer*/ - - /* Build vectors on stack: */ - /* env: */ - (void)copy_int_to_stack (0); /* Null-terminate vector */ - for (i = env_j - 1; i >= 0; i--) - R[REG_A2] = copy_int_to_stack (addrs[i]); - - /* argv: */ - (void)copy_int_to_stack (0); /* Null-terminate vector */ - for (i = j - 1; i >= env_j; i--) - R[REG_A1] = copy_int_to_stack (addrs[i]); - - /* argc: */ - R[REG_A0] = argc; - set_mem_word (R[REG_SP], argc); /* Leave argc on stack */ -} - - -static mem_addr -copy_str_to_stack (char *s) -{ - int i = (int)strlen (s); - while (i >= 0) - { - set_mem_byte (R[REG_SP], s[i]); - R[REG_SP] -= 1; - i -= 1; - } - return ((mem_addr) R[REG_SP] + 1); /* Leaves stack pointer byte-aligned!! */ -} - - -static mem_addr -copy_int_to_stack (int n) -{ - set_mem_word (R[REG_SP], n); - R[REG_SP] -= BYTES_PER_WORD; - return ((mem_addr) R[REG_SP] + BYTES_PER_WORD); -} - - -/* Run the program, starting at PC, for STEPS instructions. Display each - instruction before executing if DISPLAY is true. If CONT_BKPT is - true, then step through a breakpoint. CONTINUABLE is true if - execution can continue. Return true if breakpoint is encountered. */ - -bool -run_program (mem_addr pc, int steps, bool display, bool cont_bkpt, bool* continuable) -{ - if (cont_bkpt && inst_is_breakpoint (pc)) - { - mem_addr addr = PC == 0 ? pc : PC; - - delete_breakpoint (addr); - exception_occurred = 0; - *continuable = run_spim (addr, 1, display); - add_breakpoint (addr); - steps -= 1; - pc = PC; - } - - exception_occurred = 0; - *continuable = run_spim (pc, steps, display); - if (exception_occurred && CP0_ExCode == ExcCode_Bp) - { - /* Turn off EXL bit, so subsequent interrupts set EPC since the break is - handled by SPIM code, not MIPS code. */ - CP0_Status &= ~CP0_Status_EXL; - return true; - } - else - return false; -} - - -/* Record of where a breakpoint was placed and the instruction previously - in memory. */ - -typedef struct bkptrec -{ - mem_addr addr; - instruction *inst; - struct bkptrec *next; -} bkpt; - - -static bkpt *bkpts = NULL; - - -/* Set a breakpoint at memory location ADDR. */ - -void -add_breakpoint (mem_addr addr) -{ - bkpt *rec = (bkpt *) xmalloc (sizeof (bkpt)); - - rec->next = bkpts; - rec->addr = addr; - - if ((rec->inst = set_breakpoint (addr)) != NULL) - bkpts = rec; - else - { - if (exception_occurred) - error ("Cannot put a breakpoint at address 0x%08x\n", addr); - else - error ("No instruction to breakpoint at address 0x%08x\n", addr); - free (rec); - } -} - - -/* Delete all breakpoints at memory location ADDR. */ - -void -delete_breakpoint (mem_addr addr) -{ - bkpt *p, *b; - int deleted_one = 0; - - for (p = NULL, b = bkpts; b != NULL; ) - if (b->addr == addr) - { - bkpt *n; - - set_mem_inst (addr, b->inst); - if (p == NULL) - bkpts = b->next; - else - p->next = b->next; - n = b->next; - free (b); - b = n; - deleted_one = 1; - } - else - p = b, b = b->next; - if (!deleted_one) - error ("No breakpoint to delete at 0x%08x\n", addr); -} - - -static void -delete_all_breakpoints () -{ - bkpt *b, *n; - - for (b = bkpts, n = NULL; b != NULL; b = n) - { - n = b->next; - free (b); - } - bkpts = NULL; -} - - -/* List all breakpoints. */ - -void -list_breakpoints () -{ - bkpt *b; - - if (bkpts) - for (b = bkpts; b != NULL; b = b->next) - write_output (message_out, "Breakpoint at 0x%08x\n", b->addr); - else - write_output (message_out, "No breakpoints set\n"); -} - - - -/* Utility routines */ - - -/* Return the entry in the linear TABLE of length LENGTH with key STRING. - TABLE must be sorted on the key field. - Return NULL if no such entry exists. */ - -name_val_val * -map_string_to_name_val_val (name_val_val tbl[], int tbl_len, char *id) -{ - int low = 0; - int hi = tbl_len - 1; - - while (low <= hi) - { - int mid = (low + hi) / 2; - char *idp = id, *np = tbl[mid].name; - - while (*idp == *np && *idp != '\0') {idp ++; np ++;} - - if (*np == '\0' && *idp == '\0') /* End of both strings */ - return (& tbl[mid]); - else if (*idp > *np) - low = mid + 1; - else - hi = mid - 1; - } - - return NULL; -} - - -/* Return the entry in the linear TABLE of length LENGTH with VALUE1 field NUM. - TABLE must be sorted on the VALUE1 field. - Return NULL if no such entry exists. */ - -name_val_val * -map_int_to_name_val_val (name_val_val tbl[], int tbl_len, int num) -{ - int low = 0; - int hi = tbl_len - 1; - - while (low <= hi) - { - int mid = (low + hi) / 2; - - if (tbl[mid].value1 == num) - return (&tbl[mid]); - else if (num > tbl[mid].value1) - low = mid + 1; - else - hi = mid - 1; - } - - return NULL; -} - - -#ifdef NEED_VSPRINTF -char * -vsprintf (str, fmt, args) - char *str,*fmt; - va_list *args; -{ - FILE _strbuf; - - _strbuf._flag = _IOWRT+_IOSTRG; - _strbuf._ptr = str; - _strbuf._cnt = 32767; - _doprnt(fmt, args, &_strbuf); - putc('\0', &_strbuf); - return(str); -} -#endif - - -#ifdef NEED_STRTOL -unsigned long -strtol (const char* str, const char** eptr, int base) -{ - long result; - - if (base != 0 && base != 16) - fatal_error ("SPIM's strtol only works for base 16 (not base %d)\n", base); - if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) - { - str += 2; - sscanf (str, "%lx", &result); - } - else if (base == 16) - { - sscanf (str, "%lx", &result); - } - else - { - sscanf (str, "%ld", &result); - } - return (result); -} -#endif - - -#ifdef NEED_STRTOUL -unsigned long -strtoul (const char* str, char** eptr, int base) -{ - unsigned long result; - - if (base != 0 && base != 16) - fatal_error ("SPIM's strtoul only works for base 16 (not base %d)\n", base); - if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) - { - str += 2; - sscanf (str, "%lx", &result); - } - else if (base == 16) - { - sscanf (str, "%lx", &result); - } - else - { - sscanf (str, "%ld", &result); - } - return (result); -} -#endif - - -char * -str_copy (char *str) -{ - return (strcpy ((char*)xmalloc ((int)strlen (str) + 1), str)); -} - - -void * -xmalloc (int size) -{ - void *x = (void *) malloc (size); - - if (x == 0) - fatal_error ("Out of memory at request for %d bytes.\n"); - return (x); -} - - -/* Allocate a zero'ed block of storage. */ - -void * -zmalloc (int size) -{ - void *z = (void *) malloc (size); - - if (z == 0) - fatal_error ("Out of memory at request for %d bytes.\n"); - - memclr (z, size); - return (z); -} diff --git a/spim-qtbase/CPU/spim-utils.h b/spim-qtbase/CPU/spim-utils.h deleted file mode 100755 index 33273c5..0000000 --- a/spim-qtbase/CPU/spim-utils.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to misc. routines for SPIM. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Triple containing a string and two integers. Used in tables - mapping from a name to values. */ - -typedef struct -{ - char *name; - int value1; - int value2; -} name_val_val; - - - -/* Exported functions: */ - -void add_breakpoint (mem_addr addr); -void delete_breakpoint (mem_addr addr); -void format_data_segs (str_stream *ss); -void format_insts (str_stream *ss, mem_addr from, mem_addr to); -void format_mem (str_stream *ss, mem_addr from, mem_addr to); -void format_registers (str_stream *ss, int print_gpr_hex, int print_fpr_hex); -void initialize_registers (); -void initialize_stack (const char *command_line); -void initialize_run_stack (int argc, char **argv); -void initialize_world (char *exception_file_names, bool print_message); -void list_breakpoints (); -name_val_val *map_int_to_name_val_val (name_val_val tbl[], int tbl_len, int num); -name_val_val *map_string_to_name_val_val (name_val_val tbl[], int tbl_len, char *id); -bool read_assembly_file (char *name); -bool run_program (mem_addr pc, int steps, bool display, bool cont_bkpt, bool* continuable); -mem_addr starting_address (); -char *str_copy (char *str); -void write_startup_message (); -void *xmalloc (int); -void *zmalloc (int); diff --git a/spim-qtbase/CPU/spim.h b/spim-qtbase/CPU/spim.h deleted file mode 100755 index 39aba75..0000000 --- a/spim-qtbase/CPU/spim.h +++ /dev/null @@ -1,260 +0,0 @@ -/* SPIM S20 MIPS simulator. - Definitions for the SPIM S20. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef NULL -#define NULL 0 -#endif - -/* This declaration must match the endianness of the machine SPIM is running on. You CANNOT - set SPIM to simulate a different endianness than the machine that executes it. Almost - every processor (notably the x86) is little endian today. If your machine is big endian, - define -DSPIM_BIGENDIAN in the Makefile. */ - -#ifndef SPIM_BIGENDIAN -#define SPIM_LITTLENDIAN -#endif - - -/* Type declarations for portability. They work for DEC's Alpha (64 bits) - and 32 bit machines */ - -typedef int int32; -typedef unsigned int uint32; -typedef union {int i; void* p;} intptr_union; - - -#define streq(s1, s2) !strcmp(s1, s2) - - -/* Round V to next greatest B boundary */ -#define ROUND_UP(V, B) (((int) V + (B-1)) & ~(B-1)) -#define ROUND_DOWN(V, B) (((int) V) & ~(B-1)) - -/* Sign-extend an int16 to an int32 */ -#define SIGN_EX(X) (((X) & 0x8000) ? ((X) | 0xffff0000) : (X)) - - -#ifdef MIN /* Some systems define these in system includes */ -#undef MIN -#endif -#ifdef MAX -#undef MAX -#endif -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) - - -/* Useful and pervasive declarations: */ - -#ifdef NEED_MEM_FUNCTIONS -#define memcpy(T, F, S) bcopy((void*)F, (void*)T, S) -#define memclr(B, S) bzero(B, S) -#define memcmp(S1, S2, N) bcmp(S1, S2, N) -#else -#include -#define memclr(B, S) memset((void*)B, 0, S) -#endif - -#include -#include -#define QSORT_FUNC int(*)(const void *, const void *) - - - -#define K 1024 - - -/* Type of a memory address. Must be a 32-bit quantity to match MIPS. */ - -typedef uint32 /*@alt int @*/ mem_addr; - - -#define BYTES_PER_WORD 4 /* On the MIPS processor */ - - -/* Sizes of memory segments. */ - -/* Initial size of text segment. */ - -#ifndef TEXT_SIZE -#define TEXT_SIZE (256*K) /* 1/4 MB */ -#endif - -/* Initial size of k_text segment. */ - -#ifndef K_TEXT_SIZE -#define K_TEXT_SIZE (64*K) /* 64 KB */ -#endif - -/* The data segment must be larger than 64K since we immediate grab - 64K for the small data segment pointed to by $gp. The data segment is - expanded by an sbrk system call. */ - -/* Initial size of data segment. */ - -#ifndef DATA_SIZE -#define DATA_SIZE (256*K) /* 1/4 MB */ -#endif - -/* Maximum size of data segment. */ - -#ifndef DATA_LIMIT -#define DATA_LIMIT (K*K) /* 1 MB */ -#endif - -/* Initial size of k_data segment. */ - -#ifndef K_DATA_SIZE -#define K_DATA_SIZE (64*K) /* 64 KB */ -#endif - -/* Maximum size of k_data segment. */ - -#ifndef K_DATA_LIMIT -#define K_DATA_LIMIT (K*K) /* 1 MB */ -#endif - -/* The stack grows down automatically. */ - -/* Initial size of stack segment. */ - -#ifndef STACK_SIZE -#define STACK_SIZE (64*K) /* 64 KB */ -#endif - -/* Maximum size of stack segment. */ - -#ifndef STACK_LIMIT -#define STACK_LIMIT (256*K) /* 1/4 MB */ -#endif - - -/* Name of the function to invoke at start up */ - -#define DEFAULT_RUN_LOCATION "__start" - - -/* Name of the symbol marking the end of the exception handler */ - -#define END_OF_TRAP_HANDLER_SYMBOL "__eoth" - - -/* Default number of instructions to execute. */ - -#define DEFAULT_RUN_STEPS 2147483647 - - -/* Address to branch to when exception occurs */ -#ifdef MIPS1 -/* MIPS R2000 */ -#define EXCEPTION_ADDR 0x80000080 -#else -/* MIPS32 */ -#define EXCEPTION_ADDR 0x80000180 -#endif - -/* Maximum size of object stored in the small data segment pointed to by $gp */ - -#define SMALL_DATA_SEG_MAX_SIZE 8 - -#ifndef DIRECT_MAPPED -#define DIRECT_MAPPED 0 -#define TWO_WAY_SET 1 -#endif - - -/* Interval (in instructions) at which memory-mapped IO registers are - checked and updated. (This is to reduce overhead from making system calls - to check for IO. It can be set as low as 1.) */ - -#define IO_INTERVAL 100 - - -/* Number of IO_INTERVALs that a character remains in receiver buffer, - even if another character is available. */ - -#define RECV_INTERVAL 100 - - -/* Number of IO_INTERVALs that it takes to write a character. */ - -#define TRANS_LATENCY 100 - - -/* Iterval (milliseconds) for the hardware timer in CP0. */ - -#define TIMER_TICK_MS 10 /* 100 times per second */ - - - -/* A port is either a Unix file descriptor (an int) or a FILE* pointer. */ - -#include - -typedef union {int i; FILE* f;} port; - - -/* Exported functions (from spim.c or xspim.c): */ - -int console_input_available (); -void error (char *fmt, ...); -void fatal_error (char *fmt, ...); -char get_console_char (); -void put_console_char (char c); -void read_input (char *str, int n); -void run_error (char *fmt, ...); -void write_output (port, char *fmt, ...); - - -/* Exported variables: */ - -extern bool bare_machine; /* => simulate bare machine */ -extern bool accept_pseudo_insts; /* => parse pseudo instructions */ -extern bool delayed_branches; /* => simulate delayed branches */ -extern bool delayed_loads; /* => simulate delayed loads */ -extern bool quiet; /* => no warning messages */ -extern char *exception_file_name; /* File containing exception handler */ -extern bool force_break; /* => stop interpreter loop */ -extern bool parser_error_occurred; /* => parse resulted in error */ -extern int spim_return_value; /* Value returned when spim exits */ -/* Actual type of structure pointed to depends on X/terminal interface */ -extern port message_out, console_out, console_in; -extern bool mapped_io; /* => activate memory-mapped IO */ -extern int initial_text_size; -extern int initial_data_size; -extern mem_addr initial_data_limit; -extern int initial_stack_size; -extern mem_addr initial_stack_limit; -extern int initial_k_text_size; -extern int initial_k_data_size; -extern mem_addr initial_k_data_limit; diff --git a/spim-qtbase/CPU/string-stream.cpp b/spim-qtbase/CPU/string-stream.cpp deleted file mode 100755 index a083247..0000000 --- a/spim-qtbase/CPU/string-stream.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* SPIM S20 MIPS simulator. - Append-only output stream convertable to a string. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include -#include - -#include "spim.h" -#include "string-stream.h" - - -#ifndef SS_BUF_LENGTH -/* Initialize length of buffer */ -#define SS_BUF_LENGTH 256 -#endif - - -void -ss_init (str_stream* ss) -{ - ss->buf = (char *) malloc (SS_BUF_LENGTH); - ss->max_length = SS_BUF_LENGTH; - ss->empty_pos = 0; - ss->initialized = 1; -} - - -void -ss_clear (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - ss->empty_pos = 0; -} - - -void -ss_erase (str_stream* ss, int n) -{ - if (0 == ss->initialized) ss_init (ss); - - ss->empty_pos -= n; - if (ss->empty_pos <0) ss->empty_pos = 0; -} - - -int -ss_length (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - return ss->empty_pos; -} - - -char* -ss_to_string (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - if (ss->empty_pos == ss->max_length) - { - /* Not enough room to store output: increase buffer size and try again */ - ss->max_length = ss->max_length + 1; - ss->buf = (char *) realloc (ss->buf, (size_t)ss->max_length); - if (NULL == ss->buf) - fatal_error ("realloc failed\n"); - } - ss->buf[ss->empty_pos] = '\0'; /* Null terminate string */ - ss->empty_pos += 1; - return ss->buf; -} - - -void -ss_printf (str_stream* ss, char* fmt, ...) -{ - int free_space; - int n; - va_list args; - - va_start (args, fmt); - - if (0 == ss->initialized) ss_init (ss); - - free_space = ss->max_length - ss->empty_pos; -#ifdef _WIN32 - /* Returns -1 when buffer is too small */ - while ((n = _vsnprintf (ss->buf + ss->empty_pos, free_space, fmt, args)) < 0) -#else - /* Returns necessary space when buffer is too small */ - while ((n = vsnprintf (ss->buf + ss->empty_pos, free_space, fmt, args)) >= free_space) -#endif - { - /* Not enough room to store output: double buffer size and try again */ - ss->max_length = 2 * ss->max_length; - ss->buf = (char *) realloc (ss->buf, (size_t)ss->max_length); - free_space = ss->max_length - ss->empty_pos; - if (NULL == ss->buf) - fatal_error ("realloc failed\n"); - - va_end (args); /* Restart argument pointer */ - va_start (args, fmt); - } - ss->empty_pos += n; - - /* Null terminate string (for debugging) if there is enough room*/ - if (ss->empty_pos < ss->max_length) - ss->buf[ss->empty_pos] = '\0'; - - va_end (args); -} diff --git a/spim-qtbase/CPU/string-stream.h b/spim-qtbase/CPU/string-stream.h deleted file mode 100755 index 1766b67..0000000 --- a/spim-qtbase/CPU/string-stream.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPIM S20 MIPS simulator. - Append-only output stream convertable to a string. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -typedef struct str_stm -{ - char* buf; /* Buffer containing output */ - int max_length; /* Length of buffer */ - int empty_pos; /* Index of empty char in stream*/ - int initialized; /* Stream initialized? */ -} str_stream; - - -void ss_init (str_stream* ss); -void ss_clear (str_stream* ss); -void ss_erase (str_stream* ss, int n); -int ss_length (str_stream* ss); -char* ss_to_string (str_stream* ss); -void ss_printf (str_stream* ss, char* fmt, ...); diff --git a/spim-qtbase/CPU/sym-tbl.cpp b/spim-qtbase/CPU/sym-tbl.cpp deleted file mode 100755 index b2490b5..0000000 --- a/spim-qtbase/CPU/sym-tbl.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to maintain symbol table to resolve symbolic labels. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "data.h" -#include "parser.h" -#include "sym-tbl.h" -#include "parser_yacc.h" - - -/* Local functions: */ - -static void get_hash (char *name, int *slot_no, label **entry); -static void resolve_a_label_sub (label *sym, instruction *inst, mem_addr pc); - - - -/* Keep track of the memory location that a label represents. If we - see a reference to a label that is not yet defined, then record the - reference so that we can patch up the instruction when the label is - defined. - - At the end of a file, we flush the hash table of all non-global - labels so they can't be seen in other files. */ - - -static label *local_labels = NULL; /* Labels local to current file. */ - - -#define HASHBITS 30 - -#define LABEL_HASH_TABLE_SIZE 8191 - - -/* Map from name of a label to a label structure. */ - -static label *label_hash_table [LABEL_HASH_TABLE_SIZE]; - - -/* Initialize the symbol table by removing and freeing old entries. */ - -void -initialize_symbol_table () -{ - int i; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - { - label *x, *n; - - for (x = label_hash_table [i]; x != NULL; x = n) - { - free (x->name); - n = x->next; - free (x); - } - label_hash_table [i] = NULL; - } - - local_labels = NULL; -} - - - -/* Lookup for a label with the given NAME. Set the SLOT_NO to be the hash - table bucket that contains (or would contain) the label's record. If the - record is already in the table, set ENTRY to point to it. Otherwise, - set ENTRY to be NULL. */ - -static void -get_hash (char *name, int *slot_no, label **entry) -{ - int hi; - int i; - label *lab; - int len; - - /* Compute length of name in len. */ - for (len = 0; name[len]; len++) ; - - /* Compute hash code */ - hi = len; - for (i = 0; i < len; i++) - hi = ((hi * 613) + (unsigned)(name[i])); - - hi &= (1 << HASHBITS) - 1; - hi %= LABEL_HASH_TABLE_SIZE; - - *slot_no = hi; - /* Search table for entry */ - for (lab = label_hash_table [hi]; lab; lab = lab->next) - if (streq (lab->name, name)) - { - *entry = lab; /* <-- return if found */ - return; - } - *entry = NULL; -} - - -/* Lookup label with NAME. Either return its symbol table entry or NULL - if it is not in the table. */ - -label * -label_is_defined (char *name) -{ - int hi; - label *entry; - - get_hash (name, &hi, &entry); - - return (entry); -} - - -/* Return a label with a given NAME. If an label with that name has - previously been looked-up, the same node is returned this time. */ - -label * -lookup_label (char *name) -{ - int hi; - label *entry, *lab; - - get_hash (name, &hi, &entry); - - if (entry != NULL) - return (entry); - - /* Not found, create one, add to chain */ - lab = (label *) xmalloc (sizeof (label)); - lab->name = str_copy (name); - lab->addr = 0; - lab->global_flag = 0; - lab->const_flag = 0; - lab->gp_flag = 0; - lab->uses = NULL; - - lab->next = label_hash_table [hi]; - label_hash_table [hi] = lab; - return lab; /* <-- return if created */ -} - - -/* Record that the label named NAME refers to ADDRESS. If RESOLVE_USES is - true, resolve all references to it. Return the label structure. */ - -label * -record_label (char *name, mem_addr address, int resolve_uses) -{ - label *l = lookup_label (name); - - if (!l->gp_flag) - { - if (l->addr != 0) - { - yyerror ("Label is defined for the second time"); - return (l); - } - l->addr = address; - } - - if (resolve_uses) - { - resolve_label_uses (l); - } - - if (!l->global_flag) - { - l->next_local = local_labels; - local_labels = l; - } - return (l); -} - - -/* Make the label named NAME global. Return its symbol. */ - -label * -make_label_global (char *name) -{ - label *l = lookup_label (name); - - l->global_flag = 1; - return (l); -} - - -/* Record that an INSTRUCTION uses the as-yet undefined SYMBOL. */ - -void -record_inst_uses_symbol (instruction *inst, label *sym) -{ - label_use *u = (label_use *) xmalloc (sizeof (label_use)); - - if (data_dir) /* Want to free up original instruction */ - { - u->inst = copy_inst (inst); - u->addr = current_data_pc (); - } - else - { - u->inst = inst; - u->addr = current_text_pc (); - } - u->next = sym->uses; - sym->uses = u; -} - - -/* Record that a memory LOCATION uses the as-yet undefined SYMBOL. */ - -void -record_data_uses_symbol (mem_addr location, label *sym) -{ - label_use *u = (label_use *) xmalloc (sizeof (label_use)); - - u->inst = NULL; - u->addr = location; - u->next = sym->uses; - sym->uses = u; -} - - -/* Given a newly-defined LABEL, resolve the previously encountered - instructions and data locations that refer to the label. */ - -void -resolve_label_uses (label *sym) -{ - label_use *use; - label_use *next_use; - - for (use = sym->uses; use != NULL; use = next_use) - { - resolve_a_label_sub (sym, use->inst, use->addr); - if (use->inst != NULL && use->addr >= DATA_BOT && use->addr < stack_bot) - { - set_mem_word (use->addr, inst_encode (use->inst)); - free_inst (use->inst); - } - next_use = use->next; - free (use); - } - sym->uses = NULL; -} - - -/* Resolve the newly-defined label in INSTRUCTION. */ - -void -resolve_a_label (label *sym, instruction *inst) -{ - resolve_a_label_sub (sym, - inst, - (data_dir ? current_data_pc () : current_text_pc ())); -} - - -static void -resolve_a_label_sub (label *sym, instruction *inst, mem_addr pc) -{ - if (inst == NULL) - { - /* Memory data: */ - set_mem_word (pc, sym->addr); - } - else - { - /* Instruction: */ - if (EXPR (inst)->pc_relative) - EXPR (inst)->offset = 0 - pc; /* Instruction may have moved */ - - if (EXPR (inst)->symbol == NULL - || SYMBOL_IS_DEFINED (EXPR (inst)->symbol)) - { - int32 value; - int32 field_mask; - - if (opcode_is_branch (OPCODE (inst))) - { - int val; - - /* Drop low two bits since instructions are on word boundaries. */ - val = SIGN_EX (eval_imm_expr (EXPR (inst))); /* 16->32 bits */ - val = (val >> 2) & 0xffff; /* right shift, 32->16 bits */ - - if (delayed_branches) - val -= 1; - - value = val; - field_mask = 0xffff; - } - else if (opcode_is_jump (OPCODE (inst))) - { - value = eval_imm_expr (EXPR (inst)); - if ((value & 0xf0000000) != (pc & 0xf0000000)) - { - error ("Target of jump differs in high-order 4 bits from instruction pc 0x%x\n", pc); - } - /* Drop high four bits, since they come from the PC and the - low two bits since instructions are on word boundaries. */ - value = (value & 0x0fffffff) >> 2; - field_mask = 0xffffffff; /* Already checked that value fits in instruction */ - } - else if (opcode_is_load_store (OPCODE (inst))) - { - /* Label's location is an address */ - value = eval_imm_expr (EXPR (inst)); - field_mask = 0xffff; - - if (value & 0x8000) - { - /* LW/SW sign extends offset. Compensate by adding 1 to high 16 bits. */ - instruction* prev_inst; - instruction* prev_prev_inst; - prev_inst = read_mem_inst (pc - BYTES_PER_WORD); - prev_prev_inst = read_mem_inst (pc - 2 * BYTES_PER_WORD); - - if (prev_inst != NULL - && OPCODE (prev_inst) == Y_LUI_OP - && EXPR (inst)->symbol == EXPR (prev_inst)->symbol - && IMM (prev_inst) == 0) - { - /* Check that previous instruction was LUI and it has no immediate, - otherwise it will have compensated for sign-extension */ - EXPR (prev_inst)->offset += 0x10000; - } - /* There is an ADDU instruction before the LUI if the - LW/SW instruction uses an index register: skip over the ADDU. */ - else if (prev_prev_inst != NULL - && OPCODE (prev_prev_inst) == Y_LUI_OP - && EXPR (inst)->symbol == EXPR (prev_prev_inst)->symbol - && IMM (prev_prev_inst) == 0) - { - EXPR (prev_prev_inst)->offset += 0x10000; - } - } - } - else - { - /* Label's location is a value */ - value = eval_imm_expr (EXPR (inst)); - field_mask = 0xffff; - } - - if ((value & ~field_mask) != (int32)0 - && (value & ~field_mask) != (int32)0xffff0000) - { - error ("Immediate value is too large for field: "); - print_inst (pc); - } - if (opcode_is_jump (OPCODE (inst))) - SET_TARGET (inst, value); /* Don't mask so it is sign-extended */ - else - SET_IMM (inst, value); /* Ditto */ - SET_ENCODING (inst, inst_encode (inst)); - } - else - error ("Resolving undefined symbol: %s\n", - (EXPR (inst)->symbol == NULL) ? "" : EXPR (inst)->symbol->name); - } -} - - -/* Remove all local (non-global) label from the table. */ - -void -flush_local_labels (int issue_undef_warnings) -{ - label *l; - - for (l = local_labels; l != NULL; l = l->next_local) - { - int hi; - label *entry, *lab, *p; - - get_hash (l->name, &hi, &entry); - - for (lab = label_hash_table [hi], p = NULL; - lab; - p = lab, lab = lab->next) - if (lab == entry) - { - if (p == NULL) - label_hash_table [hi] = lab->next; - else - p->next = lab->next; - if (issue_undef_warnings && entry->addr == 0 && !entry->const_flag) - error ("Warning: local symbol %s was not defined\n", - entry->name); - /* Can't free label since IMM_EXPR's still reference it */ - break; - } - } - local_labels = NULL; -} - - -/* Return the address of SYMBOL or 0 if it is undefined. */ - -mem_addr -find_symbol_address (char *symbol) -{ - label *l = lookup_label (symbol); - - if (l == NULL || l->addr == 0) - return 0; - else - return (l->addr); -} - - -/* Print all symbols in the table. */ - -void -print_symbols () -{ - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table [i]; l != NULL; l = l->next) - write_output (message_out, "%s%s at 0x%08x\n", - l->global_flag ? "g\t" : "\t", l->name, l->addr); -} - - -/* Print all undefined symbols in the table. */ - -void -print_undefined_symbols () -{ - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table [i]; l != NULL; l = l->next) - if (l->addr == 0) - write_output (message_out, "%s\n", l->name); -} - - -/* Return a string containing the names of all undefined symbols in the - table, seperated by a newline character. Return NULL if no symbols - are undefined. */ - -char * -undefined_symbol_string () -{ - int buffer_length = 128; - int string_length = 0; - char *buffer = (char*)malloc(buffer_length); - - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table[i]; l != NULL; l = l->next) - if (l->addr == 0) - { - int name_length = (int)strlen(l->name); - int after_length = string_length + name_length + 2; - if (buffer_length < after_length) - { - buffer_length = MAX (2 * buffer_length, 2 * after_length); - buffer = (char*)realloc (buffer, buffer_length); - } - memcpy (buffer + string_length, l->name, name_length); - string_length += name_length; - buffer[string_length] = '\n'; - string_length += 1; - buffer[string_length] = '\0'; /* After end of string */ - } - - if (string_length != 0) - return (buffer); - else - { - free (buffer); - return (NULL); - }; -} diff --git a/spim-qtbase/CPU/sym-tbl.h b/spim-qtbase/CPU/sym-tbl.h deleted file mode 100755 index 94760f3..0000000 --- a/spim-qtbase/CPU/sym-tbl.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPIM S20 MIPS simulator. - Data structures for symbolic addresses. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -typedef struct lab_use -{ - instruction *inst; /* NULL => Data, not code */ - mem_addr addr; - struct lab_use *next; -} label_use; - - -/* Symbol table information on a label. */ - -typedef struct lab -{ - char *name; /* Name of label */ - long addr; /* Address of label or 0 if not yet defined */ - unsigned global_flag : 1; /* Non-zero => declared global */ - unsigned gp_flag : 1; /* Non-zero => referenced off gp */ - unsigned const_flag : 1; /* Non-zero => constant value (in addr) */ - struct lab *next; /* Hash table link */ - struct lab *next_local; /* Link in list of local labels */ - label_use *uses; /* List of instructions that reference */ -} label; /* label that has not yet been defined */ - - -#define SYMBOL_IS_DEFINED(SYM) ((SYM)->addr != 0) - - - -/* Exported functions: */ - -mem_addr find_symbol_address (char *symbol); -void flush_local_labels (int issue_undef_warnings); -void initialize_symbol_table (); -label *label_is_defined (char *name); -label *lookup_label (char *name); -label *make_label_global (char *name); -void print_symbols (); -void print_undefined_symbols (); -label *record_label (char *name, mem_addr address, int resolve_uses); -void record_data_uses_symbol (mem_addr location, label *sym); -void record_inst_uses_symbol (instruction *inst, label *sym); -char *undefined_symbol_string (); -void resolve_a_label (label *sym, instruction *inst); -void resolve_label_uses (label *sym); diff --git a/spim-qtbase/CPU/syscall.cpp b/spim-qtbase/CPU/syscall.cpp deleted file mode 100755 index 0c36b7d..0000000 --- a/spim-qtbase/CPU/syscall.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM syscalls, both in simulator and bare mode. - Execute MIPS syscalls in bare mode, when running on MIPS systems. - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef _WIN32 -#include -#endif -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#endif - -#include "spim.h" -#include "string-stream.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "syscall.h" - - -#ifdef _WIN32 -/* Windows has an handler that is invoked when an invalid argument is passed to a system - call. https://msdn.microsoft.com/en-us/library/a9yf33zb(v=vs.110).aspx - - All good, except that the handler tries to invoke Watson and then kill spim with an exception. - - Override the handler to just report an error. -*/ - -#include -#include -#include - -void myInvalidParameterHandler(const wchar_t* expression, - const wchar_t* function, - const wchar_t* file, - unsigned int line, - uintptr_t pReserved) -{ - if (function != NULL) - { - run_error ("Bad parameter to system call: %s\n", function); - } - else - { - run_error ("Bad parameter to system call\n"); - } -} - -static _invalid_parameter_handler oldHandler; - -void windowsParameterHandlingControl(int flag ) -{ - static _invalid_parameter_handler oldHandler; - static _invalid_parameter_handler newHandler = myInvalidParameterHandler; - - if (flag == 0) - { - oldHandler = _set_invalid_parameter_handler(newHandler); - _CrtSetReportMode(_CRT_ASSERT, 0); // Disable the message box for assertions. - } - else - { - newHandler = _set_invalid_parameter_handler(oldHandler); - _CrtSetReportMode(_CRT_ASSERT, 1); // Enable the message box for assertions. - } -} -#endif - - -/* Decides which syscall to execute or simulate. Returns zero upon - exit syscall and non-zero to continue execution. */ - -int -do_syscall () -{ -#ifdef _WIN32 - windowsParameterHandlingControl(0); -#endif - - /* Syscalls for the source-language version of SPIM. These are easier to - use than the real syscall and are portable to non-MIPS operating - systems. */ - - switch (R[REG_V0]) - { - case PRINT_INT_SYSCALL: - write_output (console_out, "%d", R[REG_A0]); - break; - - case PRINT_FLOAT_SYSCALL: - { - float val = FPR_S (REG_FA0); - - write_output (console_out, "%.8f", val); - break; - } - - case PRINT_DOUBLE_SYSCALL: - write_output (console_out, "%.18g", FPR[REG_FA0 / 2]); - break; - - case PRINT_STRING_SYSCALL: - write_output (console_out, "%s", mem_reference (R[REG_A0])); - break; - - case READ_INT_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - R[REG_RES] = atol (str); - break; - } - - case READ_FLOAT_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - FPR_S (REG_FRES) = (float) atof (str); - break; - } - - case READ_DOUBLE_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - FPR [REG_FRES] = atof (str); - break; - } - - case READ_STRING_SYSCALL: - { - read_input ( (char *) mem_reference (R[REG_A0]), R[REG_A1]); - data_modified = true; - break; - } - - case SBRK_SYSCALL: - { - mem_addr x = data_top; - expand_data (R[REG_A0]); - R[REG_RES] = x; - data_modified = true; - break; - } - - case PRINT_CHARACTER_SYSCALL: - write_output (console_out, "%c", R[REG_A0]); - break; - - case READ_CHARACTER_SYSCALL: - { - static char str [2]; - - read_input (str, 2); - if (*str == '\0') *str = '\n'; /* makes xspim = spim */ - R[REG_RES] = (long) str[0]; - break; - } - - case EXIT_SYSCALL: - spim_return_value = 0; - return (0); - - case EXIT2_SYSCALL: - spim_return_value = R[REG_A0]; /* value passed to spim's exit() call */ - return (0); - - case OPEN_SYSCALL: - { -#ifdef _WIN32 - R[REG_RES] = _open((char*)mem_reference (R[REG_A0]), R[REG_A1], R[REG_A2]); -#else - R[REG_RES] = open((char*)mem_reference (R[REG_A0]), R[REG_A1], R[REG_A2]); -#endif - break; - } - - case READ_SYSCALL: - { - /* Test if address is valid */ - (void)mem_reference (R[REG_A1] + R[REG_A2] - 1); -#ifdef _WIN32 - R[REG_RES] = _read(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); -#else - R[REG_RES] = read(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); -#endif - data_modified = true; - break; - } - - case WRITE_SYSCALL: - { - /* Test if address is valid */ - (void)mem_reference (R[REG_A1] + R[REG_A2] - 1); -#ifdef _WIN32 - R[REG_RES] = _write(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); -#else - R[REG_RES] = write(R[REG_A0], mem_reference (R[REG_A1]), R[REG_A2]); -#endif - break; - } - - case CLOSE_SYSCALL: - { -#ifdef _WIN32 - R[REG_RES] = _close(R[REG_A0]); -#else - R[REG_RES] = close(R[REG_A0]); -#endif - break; - } - - default: - run_error ("Unknown system call: %d\n", R[REG_V0]); - break; - } - -#ifdef _WIN32 - windowsParameterHandlingControl(1); -#endif - return (1); -} - - -void -handle_exception () -{ - if (!quiet && CP0_ExCode != ExcCode_Int) - error ("Exception occurred at PC=0x%08x\n", CP0_EPC); - - exception_occurred = 0; - PC = EXCEPTION_ADDR; - - switch (CP0_ExCode) - { - case ExcCode_Int: - break; - - case ExcCode_AdEL: - if (!quiet) - error (" Unaligned address in inst/data fetch: 0x%08x\n", CP0_BadVAddr); - break; - - case ExcCode_AdES: - if (!quiet) - error (" Unaligned address in store: 0x%08x\n", CP0_BadVAddr); - break; - - case ExcCode_IBE: - if (!quiet) - error (" Bad address in text read: 0x%08x\n", CP0_BadVAddr); - break; - - case ExcCode_DBE: - if (!quiet) - error (" Bad address in data/stack read: 0x%08x\n", CP0_BadVAddr); - break; - - case ExcCode_Sys: - if (!quiet) - error (" Error in syscall\n"); - break; - - case ExcCode_Bp: - exception_occurred = 0; - return; - - case ExcCode_RI: - if (!quiet) - error (" Reserved instruction execution\n"); - break; - - case ExcCode_CpU: - if (!quiet) - error (" Coprocessor unuable\n"); - break; - - case ExcCode_Ov: - if (!quiet) - error (" Arithmetic overflow\n"); - break; - - case ExcCode_Tr: - if (!quiet) - error (" Trap\n"); - break; - - case ExcCode_FPE: - if (!quiet) - error (" Floating point\n"); - break; - - default: - if (!quiet) - error ("Unknown exception: %d\n", CP0_ExCode); - break; - } -} diff --git a/spim-qtbase/CPU/syscall.h b/spim-qtbase/CPU/syscall.h deleted file mode 100755 index f8c0b46..0000000 --- a/spim-qtbase/CPU/syscall.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM syscalls, both in simulator and bare mode. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions. */ - -int do_syscall (); -void handle_exception (); - -#define PRINT_INT_SYSCALL 1 -#define PRINT_FLOAT_SYSCALL 2 -#define PRINT_DOUBLE_SYSCALL 3 -#define PRINT_STRING_SYSCALL 4 - -#define READ_INT_SYSCALL 5 -#define READ_FLOAT_SYSCALL 6 -#define READ_DOUBLE_SYSCALL 7 -#define READ_STRING_SYSCALL 8 - -#define SBRK_SYSCALL 9 - -#define EXIT_SYSCALL 10 - -#define PRINT_CHARACTER_SYSCALL 11 -#define READ_CHARACTER_SYSCALL 12 - -#define OPEN_SYSCALL 13 -#define READ_SYSCALL 14 -#define WRITE_SYSCALL 15 -#define CLOSE_SYSCALL 16 - -#define EXIT2_SYSCALL 17 - diff --git a/spim-qtbase/CPU/version.h b/spim-qtbase/CPU/version.h deleted file mode 100644 index 867d070..0000000 --- a/spim-qtbase/CPU/version.h +++ /dev/null @@ -1 +0,0 @@ -#define SPIM_VERSION "Version 9.1.23 of December 4, 2021" diff --git a/spim-qtbase/QtSpim/NewIcon.icns b/spim-qtbase/QtSpim/NewIcon.icns deleted file mode 100644 index f1d7d699e39ed305449d05df6385f244094b6159..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96341 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 E*{7&ZyZ`_I diff --git a/spim-qtbase/QtSpim/QtSpim.pro b/spim-qtbase/QtSpim/QtSpim.pro deleted file mode 100644 index 3dc565d..0000000 --- a/spim-qtbase/QtSpim/QtSpim.pro +++ /dev/null @@ -1,256 +0,0 @@ -# SPIM S20 MIPS simulator. -# Qt interface for SPIM simulator. -# -# Copyright (c) 1990-2020, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -#------------------------------------------------- -# -# Project created by QtCreator 2010-07-11T10:46:07 -# -#------------------------------------------------- - -cache() - -QT += core widgets printsupport - -TARGET = QtSpim -TEMPLATE = app - - -YACCSOURCES = ../CPU/parser.y -LEXSOURCES = ../CPU/scanner.l - -SOURCES += main.cpp\ - spimview.cpp\ - menu.cpp\ - regwin.cpp\ - textwin.cpp\ - datawin.cpp\ - state.cpp\ - console.cpp\ - ../CPU/data.cpp\ - ../CPU/display-utils.cpp\ - ../CPU/inst.cpp\ - ../CPU/mem.cpp\ - ../CPU/run.cpp\ - ../CPU/spim-utils.cpp\ - ../CPU/string-stream.cpp\ - ../CPU/sym-tbl.cpp\ - ../CPU/syscall.cpp\ - spim_support.cpp - - -HEADERS += spimview.h\ - regtextedit.h\ - texttextedit.h\ - datatextedit.h\ - spim_settings.h\ - settablecheckbox.h\ - console.h - - -FORMS += spimview.ui\ - savelogfile.ui\ - printwindows.ui\ - runparams.ui\ - settings.ui\ - changevalue.ui \ - breakpoint.ui - - -INCLUDEPATH = ../CPU ../QtSpim - - -RESOURCES = windows_images.qrc exception.qrc - -win32:RC_FILE = qtspim.rc - - -QMAKE_YACC = bison -QMAKE_YACCFLAGS = --defines=parser_yacc.h --output=parser_yacc.cpp -QMAKE_YACCFLAGS_MANGLE = -p yy -QMAKE_YACC_HEADER = parser_yacc.h -QMAKE_YACC_SOURCE = parser_yacc.cpp - -QMAKE_LEX = flex -QMAKE_LEXFLAGS_MANGLE = -Pyy -QMAKE_LEXFLAGS = -I -8 --outfile=lex.scanner.c - - -# Help file -# -HELP_PROJ = help/qtspim.qhp -buildcompressedhelp.name = Build compressed help -buildcompressedhelp.input = HELP_PROJ -buildcompressedhelp.output = help/${QMAKE_FILE_BASE}.qch -buildcompressedhelp.commands= qhelpgenerator ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} -buildcompressedhelp.CONFIG = no_link recursive - -# qcollectiongenerator must be run in the directory containing the project file, otherwise it -# puts partial paths in the .qhc file, which make it impossible to install the help files in -# other directories. -# -HELP_COL_PROJ = help/qtspim.qhcp -buildhelpcollection.name = Build help collection -buildhelpcollection.input = HELP_COL_PROJ -buildhelpcollection.output = help/${QMAKE_FILE_BASE}.qhc -linux|macx:buildhelpcollection.commands= bash -c '\"pushd ${QMAKE_FILE_PATH}; qcollectiongenerator ${QMAKE_FILE_BASE}.qhcp; popd; $(COPY) ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.qhc ${QMAKE_FILE_OUT};\"' -win32:buildhelpcollection.commands= sh -c '\"pushd ${QMAKE_FILE_PATH} ; qcollectiongenerator ${QMAKE_FILE_BASE}.qhcp ; popd ; $(COPY) ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.qhc ${QMAKE_FILE_OUT}\"' -buildhelpcollection.CONFIG = no_link recursive - -QMAKE_EXTRA_COMPILERS += buildcompressedhelp buildhelpcollection -POST_TARGETDEPS += help/qtspim.qch help/qtspim.qhc - - -# Microsoft Visual C compiler flags -# -win32-msvc2008 { - # Compile all files as C++ - # - QMAKE_CFLAGS_DEBUG += -TP - QMAKE_CFLAGS_RELEASE += -TP - - # Disable security warnings - # - DEFINES += _CRT_SECURE_NO_WARNINGS -} -win32-msvc2010 { - # Compile all files as C++ - # - QMAKE_CFLAGS_DEBUG += -TP - QMAKE_CFLAGS_RELEASE += -TP - - # Disable security warnings - # - DEFINES += _CRT_SECURE_NO_WARNINGS -} -win32-msvc2012 { - # Compile all files as C++ - # - QMAKE_CFLAGS_DEBUG += -TP - QMAKE_CFLAGS_RELEASE += -TP - - # Disable security warnings - # - DEFINES += _CRT_SECURE_NO_WARNINGS -} - - -# gcc flags -# -win32-g++ { - # Compile all files as C++ - # Surpress gcc warning about deprecated conversion from string constant to char* - # - QMAKE_CFLAGS_DEBUG += -Wno-write-strings - QMAKE_CFLAGS_RELEASE += -Wno-write-strings - QMAKE_CXXFLAGS_DEBUG += -Wno-write-strings - QMAKE_CXXFLAGS_RELEASE += -Wno-write-strings - - # Surpress error when deleting non-existent file. - # - QMAKE_DEL_FILE = rm -f - QMAKE_MOVE = mv - QMAKE_COPY = cp -} - -linux-g++-32 { - # Compile all files as C++ - # Surpress gcc warning about deprecated conversion from string constant to char* - # - QMAKE_CFLAGS_DEBUG += -Wno-write-strings - QMAKE_CFLAGS_RELEASE += -Wno-write-strings - QMAKE_CXXFLAGS_DEBUG += -Wno-write-strings - QMAKE_CXXFLAGS_RELEASE += -Wno-write-strings - - # Libraries will be installed in standard location - QMAKE_RPATHDIR = /usr/lib/qtspim/lib - - # Surpress error when deleting non-existent file. - # - QMAKE_DEL_FILE = rm -f -} - -linux-g++ { - QMAKE_CFLAGS_DEBUG += -Wno-write-strings - QMAKE_CFLAGS_RELEASE += -Wno-write-strings - QMAKE_CXXFLAGS_DEBUG += -Wno-write-strings - QMAKE_CXXFLAGS_RELEASE += -Wno-write-strings - - # Libraries will be installed in standard location - QMAKE_RPATHDIR = /usr/lib/qtspim/lib - - # Surpress error when deleting non-existent file. - # - QMAKE_DEL_FILE = rm -f - - # This seems really stupid, but the only place that MOVE is invoked is to move parser_yacc.h on - # to itself, which fails with gnuutils, since they raises an error if you try to mv (or cp) a - # file onto itself. Pretty pointless, and no way to turn it off... - QMAKE_MOVE = touch - - # Do not add -lGL, since this requires installation of OpenCL libraries, - # which are already installed with QtCreator. - QMAKE_LIBS_OPENGL = -} - -macx-g++ { - # Compile all files as C++ - # Surpress gcc warning about deprecated conversion from string constant to char* - # - QMAKE_CFLAGS_DEBUG += -Wno-write-strings -Wno-deprecated-register - QMAKE_CFLAGS_RELEASE += -Wno-write-strings -Wno-deprecated-register - QMAKE_CXXFLAGS_DEBUG += -Wno-write-strings -Wno-deprecated-register - QMAKE_CXXFLAGS_RELEASE += -Wno-write-strings -Wno-deprecated-register - - # Surpress error when deleting non-existent file. - # - QMAKE_DEL_FILE = rm -f - QMAKE_INFO_PLIST = macinfo.plist - - ICON = NewIcon.icns -} - -macx-clang { - # Compile all files as C++ - # Surpress gcc warning about deprecated conversion from string constant to char* - # - QMAKE_CFLAGS_DEBUG += -Wno-write-strings -Wno-deprecated-register - QMAKE_CFLAGS_RELEASE += -Wno-write-strings -Wno-deprecated-register - QMAKE_CXXFLAGS_DEBUG += -Wno-write-strings -Wno-deprecated-register - QMAKE_CXXFLAGS_RELEASE += -Wno-write-strings -Wno-deprecated-register - - # Surpress error when deleting non-existent file. - # - QMAKE_DEL_FILE = rm -f - QMAKE_INFO_PLIST = macinfo.plist - - ICON = NewIcon.icns -} diff --git a/spim-qtbase/QtSpim/README b/spim-qtbase/QtSpim/README deleted file mode 100644 index 36fd24c..0000000 --- a/spim-qtbase/QtSpim/README +++ /dev/null @@ -1,56 +0,0 @@ - SPIM S20 MIPS simulator. - Qt interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Notes for building QtSpim on various systems. - -All: - Install the bison parser generator and flex lexer generator, either using Cygwin on Windows or native on Linux. - - -Windows: - The Open Source version of Qt Creator for Windows, which uses mingw works fine, as does - the version (which you need to build yourself) that uses Microsoft Visual Studio's C++ - compiler. - -Linux: - The version of Qt Creator that comes with Ubuntu is an old version, which has some problems with QtSpim. - Download a recent version from http://qt.nokia.com/downloads/. - -Mac: - Download the Mac Qt SDK at http://qt.nokia.com/downloads/sdk-mac-os-cpp. - - -Notes: - If you are porting to a new system, and see a large number of compiler errors in - QtCreator, changes are good that you need to change QtSpim.pro to define the compiler - flag that says "treat all files, including .c files, as C++ code. This flag is "-X C++" - for gcc and "-TP" for the Microsoft compiler. \ No newline at end of file diff --git a/spim-qtbase/QtSpim/breakpoint.ui b/spim-qtbase/QtSpim/breakpoint.ui deleted file mode 100644 index 3c8d57e..0000000 --- a/spim-qtbase/QtSpim/breakpoint.ui +++ /dev/null @@ -1,115 +0,0 @@ - - - BreakpointDialog - - - - 0 - 0 - 282 - 100 - - - - Breakpoint - - - - - 10 - 10 - 261 - 80 - - - - - - - Execution stopped at a breakpoint - - - - - - - - - Continue - - - true - - - - - - - Single Step - - - - - - - Abort - - - - - - - - - - - - continuePushButton - clicked() - BreakpointDialog - close() - - - 52 - 70 - - - 141 - 49 - - - - - singleStepPushButton - clicked() - BreakpointDialog - close() - - - 140 - 70 - - - 141 - 49 - - - - - abortPushButton - clicked() - BreakpointDialog - close() - - - 227 - 70 - - - 141 - 49 - - - - - diff --git a/spim-qtbase/QtSpim/changevalue.ui b/spim-qtbase/QtSpim/changevalue.ui deleted file mode 100644 index f8bf69b..0000000 --- a/spim-qtbase/QtSpim/changevalue.ui +++ /dev/null @@ -1,102 +0,0 @@ - - - ChangeValueDialog - - - - 0 - 0 - 239 - 160 - - - - Change Value - - - - - 10 - 10 - 221 - 141 - - - - - - - Change value to: - - - - - - - - - - - - Hexadecimal - - - - - - - Decimal - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - buttonBox - accepted() - ChangeValueDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ChangeValueDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/spim-qtbase/QtSpim/console.cpp b/spim-qtbase/QtSpim/console.cpp deleted file mode 100644 index 6edc896..0000000 --- a/spim-qtbase/QtSpim/console.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spimview.h" - -Console::Console(QWidget *parent) - : QPlainTextEdit(parent) -{ - setWindowTitle("Console"); - resize(800, 600); - - setUndoRedoEnabled(false); - appendPlainText(QString("")); - - QFont courier("Courier"); - setFont(courier); -} - - -void Console::WriteOutput(QString out) -{ - activateWindow(); - moveCursor(QTextCursor::End); - insertPlainText(out); - ensureCursorVisible(); -} - - -QString Console::ReadChar() -{ - if (l->isRunning()) // Not re-enterent - { - return QString("\n"); - } - else - { - activateWindow(); - while (1) - { - if (InputAvailable()) - { - QString firstChar = inputBuffer.left(1); - inputBuffer.remove(0, 1); - return firstChar; - } - // This is a bit tricky and I hope it works on all platforms. If there aren't any - // characters in the buffer, start a new event loop to wait for keystrokes and block on - // it. Cannot use semaphores or busy-wait since both actions are on the same thread. - // - l->exec(); - } - } -} - - -bool Console::InputAvailable() -{ - return inputBuffer.length() > 0; -} - - -void Console::Clear() -{ - setPlainText(""); - inputBuffer = QString(""); - l = new QEventLoop(); -} - - -void Console::keyPressEvent(QKeyEvent* /*e*/) -{ - // Ignore -} - -void Console::keyReleaseEvent(QKeyEvent* e) -{ - QString key = e->text(); - - if (key != "") - { - inputBuffer.append(key); - if (!mapped_io) - { - WriteOutput(key); // Do not echo input when using mem mapped IO - } - - // Release the call on ReadChar (if any) that is blocked waiting for input. - // - l->exit(); - } -} - -void Console::mouseMoveEvent(QMouseEvent* /*e*/) -{ - // Ignore -} - -void Console::mousePressEvent(QMouseEvent* /*e*/) -{ - // Ignore -} - - -void Console::closeEvent(QCloseEvent* event) -{ - Window->ui->action_Win_Console->setChecked(false); - event->accept(); -} - - -void Console::hideEvent(QHideEvent* event) -{ - Window->ui->action_Win_Console->setChecked(false); - event->accept(); -} - - -void Console::showEvent(QShowEvent* event) -{ - if (Window != NULL) - { - Window->ui->action_Win_Console->setChecked(true); - } - event->accept(); -} diff --git a/spim-qtbase/QtSpim/console.h b/spim-qtbase/QtSpim/console.h deleted file mode 100644 index ff8a80f..0000000 --- a/spim-qtbase/QtSpim/console.h +++ /dev/null @@ -1,64 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include -#include -#include - -class Console : public QPlainTextEdit -{ -Q_OBJECT - -public: - Console(QWidget* parent); - - virtual void keyPressEvent(QKeyEvent* e); - virtual void keyReleaseEvent(QKeyEvent* e); - virtual void mouseMoveEvent(QMouseEvent* e); - virtual void mousePressEvent(QMouseEvent* e); - - void Clear(); - bool InputAvailable(); - QString ReadChar(); - void WriteOutput(QString out); - -protected: - virtual void closeEvent(QCloseEvent* event); - virtual void hideEvent(QHideEvent* event); - virtual void showEvent(QShowEvent* event); - -private: - QString inputBuffer; - QEventLoop* l; -}; diff --git a/spim-qtbase/QtSpim/datatextedit.h b/spim-qtbase/QtSpim/datatextedit.h deleted file mode 100644 index 4d51eba..0000000 --- a/spim-qtbase/QtSpim/datatextedit.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include - -class dataTextEdit : public QPlainTextEdit -{ - Q_OBJECT - -public: - dataTextEdit(); - void contextMenuEvent(QContextMenuEvent* event); - QAction* action_Context_ChangeValue; - -protected: - virtual void closeEvent(QCloseEvent* event); - virtual void hideEvent(QHideEvent* event); - virtual void showEvent(QShowEvent* event); - -private: - QPoint contextGlobalPos; - -public slots: - void changeValue(); - int addrFromPos(QTextCursor* cursor); -}; diff --git a/spim-qtbase/QtSpim/datawin.cpp b/spim-qtbase/QtSpim/datawin.cpp deleted file mode 100644 index be84bbd..0000000 --- a/spim-qtbase/QtSpim/datawin.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spimview.h" -#include "ui_spimview.h" - -#include -#include -#include -#include -#define QT_USE_FAST_CONCATENATION -#include -#include - - -#define WORD_WIDTH_10 10 -#define WORD_WIDTH_16 8 -#define WORD_WIDTH_DEFAULT 32 - - -// -// Data segment window -// - -void SpimView::DisplayDataSegments(bool force) -{ - if (force || data_modified) - { - dataTextEdit* te = ui->DataSegDockWidget->findChild("DataSegmentTextEdit"); - QString windowContents = windowFormattingStart(st_textWinFont, st_textWinFontColor, st_textWinBackgroundColor); - int scrollPosition = te->verticalScrollBar()->value(); - - windowContents += formatUserDataSeg() % formatUserStack() % formatKernelDataSeg() % windowFormattingEnd(); - - te->clear(); - te->appendHtml(windowContents); - - te->verticalScrollBar()->setSliderPosition(scrollPosition); - } - data_modified = false; -} - - -QString SpimView::formatUserDataSeg() -{ - if (st_showUserDataSegment) - { - return formatSegLabel("User data segment", DATA_BOT, data_top) - % formatMemoryContents(DATA_BOT, data_top); - } - else - { - return QString(""); - } -} - - -QString SpimView::formatUserStack() -{ - if (st_showUserStackSegment) - { - return formatSegLabel("
User Stack", ROUND_DOWN(R[29], BYTES_PER_WORD), STACK_TOP) - % formatMemoryContents(ROUND_DOWN(R[29], BYTES_PER_WORD), STACK_TOP); - } - else - { - return QString(""); - } -} - - -QString SpimView::formatKernelDataSeg() -{ - if (st_showKernelDataSegment) - { - return formatSegLabel("
Kernel data segment", K_DATA_BOT, k_data_top) - % formatMemoryContents(K_DATA_BOT, k_data_top); - } - else - { - return QString(""); - } -} - - -#define BYTES_PER_LINE (4*BYTES_PER_WORD) - - -QString SpimView::formatMemoryContents(mem_addr from, mem_addr to) -{ - mem_addr i = ROUND_UP(from, BYTES_PER_WORD); - QString windowContents = formatPartialQuadWord(i, to); - i = ROUND_UP(i, BYTES_PER_LINE); // Next quadword - - for ( ; i < to; ) - { - mem_word val; - - /* Count consecutive zero words */ - int j; - for (j = 0; (i + (uint32) j * BYTES_PER_WORD) < to; j += 1) - { - val = read_mem_word(i + (uint32) j * BYTES_PER_WORD); - if (val != 0) - { - break; - } - } - - if (j >= 4) - { - /* Block of 4 or more zero memory words: */ - windowContents += QString("[") % formatAddress(i) - % QString("]..[") % formatAddress(i + (uint32) j * BYTES_PER_WORD - 1) - % QString("]") % nnbsp(2) % QString("00000000
"); - - i = i + (uint32) j * BYTES_PER_WORD; - windowContents += formatPartialQuadWord(i, to); - i = ROUND_UP(i, BYTES_PER_LINE); // Next quadword - } - else - { - /* Fewer than 4 zero words, print them on a single line: */ - windowContents += QString("[") % formatAddress(i) % "]" % nnbsp(2); - mem_addr j = i; - do - { - val = read_mem_word(i); - windowContents += nnbsp(2) % formatWord(val, st_dataSegmentDisplayBase); - i += BYTES_PER_WORD; - } - while ((i % BYTES_PER_LINE) != 0 && i < to); - - windowContents += nnbsp(2) % formatAsChars(j, i) % QString("
"); - } - } - return windowContents; -} - - -QString SpimView::formatPartialQuadWord(mem_addr from, mem_addr to) -{ - QString windowContents = QString(""); - - if ((from % BYTES_PER_LINE) != 0 && from < to) - { - windowContents += QString("[") % formatAddress(from) % QString("]") % nnbsp(2); - - mem_addr a; - for (a = from; (a % BYTES_PER_LINE) != 0 && from < to; a += BYTES_PER_WORD) - { - mem_word val = read_mem_word(a); - windowContents += nnbsp(2) % formatWord(val, st_dataSegmentDisplayBase); - } - - windowContents += formatAsChars(from, a) % QString("
"); - } - - return windowContents; -} - - -QString SpimView::formatAsChars(mem_addr from, mem_addr to) -{ - QString windowContents = nnbsp(2); - - if (to - from != BYTES_PER_LINE) - { - int missing = (BYTES_PER_LINE - (to - from)) / BYTES_PER_WORD; - windowContents += nnbsp(2); - switch (st_dataSegmentDisplayBase) - { - case 10: windowContents += nnbsp(missing * (WORD_WIDTH_10 + 2)); break; - case 16: windowContents += nnbsp(missing * (WORD_WIDTH_16 + 2)); break; - default: windowContents += nnbsp(missing * (WORD_WIDTH_DEFAULT + 2)); break; - } - } - - for (mem_addr a = from; a < to; a += 1) - { - mem_word val = read_mem_byte(a); - windowContents += formatChar(val) % " "; - } - - return windowContents; -} - - -// -// Utility functions -// - -QString formatAddress(mem_addr addr) -{ - return QString::number(addr, 16).rightJustified(8, '0'); -} - - -QString formatWord(mem_word word, int base) -{ - int width = 0; - switch (base) - { - case 10: width = WORD_WIDTH_10; break; - case 16: width = WORD_WIDTH_16; break; - default: width = WORD_WIDTH_DEFAULT; break; - } - QString str = QString::number(word, base); - str.remove(0, str.length() - width); // Negative hex number proceeded by 0xffffffff - - if (str[0] == '-') // decimal starting with a negative sign - return str.rightJustified(width, ' ').replace(QRegExp(" "), " "); // Don't zero pad - else - return str.rightJustified(width, '0'); -} - - -QString formatChar(int chr) -{ - if (chr == ' ') - { - return QString(" "); - } - else if (chr == '<') - { - return QString("<"); - } - else if (chr == '>') - { - return QString(">"); - } - else if (chr == '&') - { - return QString("&"); - } - else if (chr > ' ' && chr <= '~') // Printable ascii chars - { - return QString(QChar(chr)); - } - else - { - return QString(QChar('.')); - } -} - - -QString formatSegLabel(QString segName, mem_addr low, mem_addr high) -{ - return QString("
") % segName - % QString(" [") % formatAddress(low) % QString("]..[") % formatAddress(high) - % QString("]
"); -} - - -// -// Change memory value -// - -dataTextEdit::dataTextEdit() -{ - action_Context_ChangeValue = new QAction(this); - action_Context_ChangeValue->setObjectName("action_ChangeValue"); - action_Context_ChangeValue->setText("Change Memory Contents"); -} - - -void dataTextEdit::contextMenuEvent(QContextMenuEvent* event) -{ - QMenu *menu = createStandardContextMenu(); - menu->addSeparator(); - - menu->addAction(Window->ui->action_Data_DisplayBinary); - menu->addAction(Window->ui->action_Data_DisplayDecimal); - menu->addAction(Window->ui->action_Data_DisplayHex); - - menu->addSeparator(); - menu->addAction(action_Context_ChangeValue); - contextGlobalPos = event->globalPos(); - - menu->exec(event->globalPos()); -} - - -void dataTextEdit::changeValue() -{ - QTextCursor cursor; - mem_addr addr = addrFromPos(&cursor); - if (addr != 0) - { - int base = Window->DataDisplayBase(); - QString val = promptForNewValue("New value for " + formatAddress(addr), &base); - - bool ok; - int newMemVal = 0; - if (base == 10) { - newMemVal = val.toLong(&ok, base); // decimal is signed - } else - { - newMemVal = val.toULong(&ok, base); // hex is unsigned - } - - if (ok) - { - set_mem_word(addr, newMemVal); - } else - { - QMessageBox msgBox; - msgBox.setText(QString("Bad ") + (base == 16 ? "hex" : "decimal") + " memory value: " + val); - msgBox.exec(); - } - - Window->DisplayDataSegments(true); - } -} - - -int dataTextEdit::addrFromPos(QTextCursor* cursor) -{ - // Position of context menu is location user right-click. Find the line at this point - // and compute the address of the memory location the user clicked on. - // - QPoint mouseViewportPos = this->viewport()->mapFromGlobal(contextGlobalPos); - QTextCursor mouseCursor = this->cursorForPosition(mouseViewportPos); - *cursor = mouseCursor; - - cursor->select(QTextCursor::LineUnderCursor); - QString line = cursor->selectedText(); - - QRegExp rx("\\[([0-9a-fA-F]{8})\\]"); // Address of instruction - - rx.indexIn(line); - QString addrStr = rx.cap(1); - if (addrStr != "") - { - bool ok; - mem_addr addr = addrStr.toUInt(&ok, 16); - if (ok) - { - // [...]#### - // - int offset = mouseCursor.position() - cursor->anchor(); // Start of line to mouse location - line.truncate(offset); // Remove address - line.remove(0, 14); // Remove line after mouse position - - QRegExp rx2("^([0-9a-fA-F]+\\s*)?([0-9a-fA-F]+\\s*)?([0-9a-fA-F]+\\s*)?([0-9a-fA-F]+\\s*)?"); - rx2.indexIn(line, 0); - return addr - + (rx2.cap(1) == "" ? 0 : 0) - + (rx2.cap(2) == "" ? 0 : BYTES_PER_WORD) - + (rx2.cap(3) == "" ? 0 : BYTES_PER_WORD) - + (rx2.cap(4) == "" ? 0 : BYTES_PER_WORD); - } - } - return 0; -} - - -void dataTextEdit::closeEvent(QCloseEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - Window->ui->action_Win_DataSegment->setChecked(false); - } - event->accept(); -} - - -void dataTextEdit::hideEvent(QHideEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - Window->ui->action_Win_DataSegment->setChecked(false); - } - event->accept(); -} - - -void dataTextEdit::showEvent(QShowEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - Window->ui->action_Win_DataSegment->setChecked(true); - } - event->accept(); -} diff --git a/spim-qtbase/QtSpim/exception.qrc b/spim-qtbase/QtSpim/exception.qrc deleted file mode 100644 index 8400c1b..0000000 --- a/spim-qtbase/QtSpim/exception.qrc +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - ../CPU/exceptions.s - - diff --git a/spim-qtbase/QtSpim/help/Fig10_1.jpg b/spim-qtbase/QtSpim/help/Fig10_1.jpg deleted file mode 100644 index 2d1be721da71e003498e7fb50876e0d728fa2fb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53679 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
>l)~6kEjhwmPa37JLKF{&P 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%0D&p(x;r3aceYia?8Y7O^Qe`8E3q%W?C~O#U$+YlR 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 diff --git a/spim-qtbase/QtSpim/help/Fig1_6.jpg b/spim-qtbase/QtSpim/help/Fig1_6.jpg deleted file mode 100644 index 1c49b307516c4b29dca8fc51163097cfec5155cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22713 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 PO=j``K)ULopHu$=<)R`z diff --git a/spim-qtbase/QtSpim/help/Fig2_1.jpg b/spim-qtbase/QtSpim/help/Fig2_1.jpg deleted file mode 100644 index ef11222d75b971930c53f95a854c1e7dc8e68de1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16842 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 diff --git a/spim-qtbase/QtSpim/help/Fig6_2.jpg b/spim-qtbase/QtSpim/help/Fig6_2.jpg deleted file mode 100644 index b4a89a0a6cfc08a515d6acff12def243acb87793..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19368 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 diff --git a/spim-qtbase/QtSpim/help/Fig6_3a.jpg b/spim-qtbase/QtSpim/help/Fig6_3a.jpg deleted file mode 100644 index 33b33962aa6ff6ceeed76f1fddf84d24adf7fea7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6705 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 rgdy@o??m&%K|M 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 - - - - -Assemblers, Linkers, and the SPIM Simulator - - - - - - - - - - -

Appendix A from Patterson and Hennessey, Computer Organization - and Design: The Hardware/Software Interface, Third Edition. Copyright Morgan - Kaufmann Publishers. Used by permission.

-
- -
-

Assembly language is the symbolic representation of a computer’s binary - encoding— machine language. Assembly language - is more readable than machine language because it uses symbols instead of bits. - The symbols in assembly language name commonly occurring bit patterns, such - as opcodes and register specifiers, so people can read and remember them. In - addition, assembly language permits programmers to use labels to identify - and name particular memory words that hold instructions or data.

-

Figure 1.1 The process that produces - an executable file. An assembler translates a file of assembly language into - an object file, which is linked with other files and libraries into an executable - file.

-

A tool called an assembler translates assembly language - into binary instructions. Assemblers provide a friendlier representation than a - computer’s 0s and 1s that simplifies writing and reading programs. Symbolic names for - operations and locations are one facet of this representation. Another facet is - programming facilities that increase a program’s clarity. For - example, macros, discussed earlier, enable a programmer to - extend the assembly language by defining new operations.

-

An assembler reads a single assembly language source file and produces - an object file containing machine instructions and bookkeeping information - that helps combine several object files into a program. Figure 1.1 illustrates - how a program is built. Most programs consist of several files—also called - modules — that are written, compiled, and assembled independently. A program - may also use prewritten routines supplied in a program library . A module - typically contains references to subroutines and data defined in other - modules and in libraries. The code in a module cannot be executed when it contains - unresolved references to labels in other - object files or libraries. Another tool, called a linker, - combines a collection of object and library files into an executable - file, which a computer can run.

-

To see the advantage of assembly language, consider the following sequence - of figures, all of which contain a short subroutine that computes and prints - the sum of the squares of integers from 0 to 100. Figure 1.2 shows the machine - language that a MIPS computer executes. With considerable effort, you could - use the opcode and instruction format tables in Chapter 2 to translate the instructions - into a symbolic program similar to Figure 1.3. This form of the routine is - much easier to read because operations and operands are written with symbols, - rather than with bit patterns. However, this assembly language is still difficult - to follow because memory locations are named by their address, rather than by - a symbolic label.

-
-       00100111101111011111111111100000 10101111101111110000000000010100 10101111101001000000000000100000
-       10101111101001010000000000100100 10101111101000000000000000011000 10101111101000000000000000011100
-       10001111101011100000000000011100 10001111101110000000000000011000 00000001110011100000000000011001
-       00100101110010000000000000000001 00101001000000010000000001100101 10101111101010000000000000011100
-       00000000000000000111100000010010 00000011000011111100100000100001 00010100001000001111111111110111
-       10101111101110010000000000011000 00111100000001000001000000000000 10001111101001010000000000011000
-       00001100000100000000000011101100 00100100100001000000010000110000 10001111101111110000000000010100
-       00100111101111010000000000100000 00000011111000000000000000001000 00000000000000000001000000100001
-        
-

Figure 1.2 MIPS machine language code for a routine to compute and print - the sum of the squares of integers between 0 and 100.

-

Figure 1.4 shows assembly language that labels memory addresses with mnemonic - names. Most programmers prefer to read and write this form. Names that begin - with a period, for example .data and .globl, are assembler - directives that tell the assembler how to translate a program but - do not produce machine instructions. Names followed by a colon, such as str - or main, are labels that name the next memory location. This program is as readable - as most assembly language programs (except for a glaring lack of comments), - but it is still difficult to follow because many simple operations are required - to accomplish simple tasks and because assembly language’s lack of control flow - constructs provides few hints about the program’s operation.

-

By contrast, the C routine in Figure 1.5 is both shorter and clearer since - variables have mnemonic names and the loop is explicit rather than constructed - with branches. In fact, the C routine is the only one that we wrote. The other - forms of the program were produced by a C compiler and assembler.

-

In general, assembly language plays two roles (see Figure 1.6). The first - role is the output language of compilers. A compiler translates a program - written in a high-level language (such as C or Pascal) into an equivalent - program in machine or assembly language. The high-level language is called the - source language, and the compiler’s - output is its target language.

-
- -
-
-        addiu $29, $29, -32
-        sw $31, 20($29)
-        sw $4, 32($29)
-        sw $5, 36($29)
-        sw $0, 24($29)
-        sw $0, 28($29)
-        lw $14, 28($29)
-        lw $24, 24($29)
-        multu $14, $14
-        addiu $8, $14, 1
-        slti $1, $8, 101
-        sw $8, 28($29)
-        mflo $15
-        addu $25, $24, $15
-        bne $1, $0, -9
-        sw $25, 24($29)
-        lui $4, 4096
-        lw $5, 24($29)
-        jal 1048812
-        addiu $4, $4, 1072
-        lw $31, 20($29)
-        addiu $29, $29, 32
-        jr $31
-        move $2, $0
-        
-
- -
-

Figure 1.3 The same routine written in assembly language. However, - the code for the routine does not label registers or memory locations nor include - comments.

-

Assembly language’s other role is as a language in which to write programs. - This role used to be the dominant one. Today, however, because of larger main - memories and better compilers, most programmers write in a high-level language - and rarely, if ever, see the instructions that a computer executes. Nevertheless, - assembly language is still important to write programs in which speed or size - are critical or to exploit hardware features that have no analogues in high-level - languages.

-

Although this appendix focuses on MIPS assembly language, assembly programming - on most other machines is very similar. The additional instructions and address - modes in CISC machines, such as the VAX, can make assembly programs shorter - but do not change the process of assembling a program or provide assembly language - with the advantages of high-level languages such as type-checking and structured - control flow.

-
-        .text
-        .align 2
-        .globl main
-main:
-        subu $sp, $sp, 32
-        sw $ra, 20($sp)
-        sd $a0, 32($sp)
-        sw $0, 24($sp)
-        sw $0, 28($sp)
-loop:
-        lw $t6, 28($sp)
-        mul $t7, $t6, $t6
-        lw $t8, 24($sp)
-        addu $t9, $t8, $t7
-        sw $t9, 24($sp)
-        addu $t0, $t6, 1
-        sw $t0, 28($sp)
-        ble $t0, 100, loop
-        la $a0, str
-        lw $a1, 24($sp)
-        jal printf
-        move $v0, $0
-        lw $ra, 20($sp)
-        addu $sp, $sp, 32
-        jr $ra
-        .data
-        .align 0
-str:
-        .asciiz "The sum from 0 .. 100 is %d\n"
-        
-

Figure 1.4 The same routine written in assembly language with labels, but no - comments. The commands that start with periods are assembler - directives. .text indicates that succeeding lines contain instructions. .data - indicates that they contain data. .align n indicates that the items on the succeeding - lines should be aligned on a 2 n byte boundary. Hence, .align 2 means - the next item should be on a word boundary. .globl main declares that main is a global - symbol that should be visible to code stored in other files. Finally, .asciiz stores a - null-terminated string in memory. -

-

When to Use Assembly Language

-

The primary reason to program in assembly language, as opposed to an available - high-level language, is that the speed or size of a program is critically important. - For example, consider a computer that controls a piece of machinery, such as - a car’s brakes. A computer that is incorporated in another device, such as a - car, is called an embedded computer. This type of computer needs to respond - rapidly and predictably to events in the outside world. Because a compiler introduces - uncertainty about the time cost of operations, programmers may find it difficult - to ensure that a high-level language program responds within a definite time - inter-val—say, 1 millisecond after a sensor detects that a tire is skidding. - An assembly language programmer, on the other hand, has tight control over which - instructions execute. In addition, in embedded applications, reducing a program’s - size, so that it fits in fewer memory chips, reduces the cost of the embedded - computer.

-
-        #include<stdio.h>
-        int
-        main (int argc, char *argv[])
-        {
-          int i; int sum = 0;
-          for (i = 0; i <= 100; i = i + 1) sum = sum + i * i;
-          printf ("The sum from 0 .. 100 is %d\n", sum);
-        }
-        
-

Figure 1.5 The routine written in the C programming language.

-

Figure 1.6 Assembly language - either is written by a programmer or is the output of a compiler.

-

A hybrid approach, in which most of a program is written in a high-level language and - time-critical sections are written in assembly language, builds on the strengths of both - languages. Programs typically spend most of their time executing a small fraction of the - program’s source code. This observation is just the principle of locality that - underlies caches.

-

Program profiling measures where a program spends its time and can find the - time-critical parts of a program. In many cases, this portion of the program - can be made faster with better data structures or algorithms. Sometimes, however, - significant performance improvements only come from recoding a critical portion - of a program in assembly language.

-

This improvement is not necessarily an indication that the high-level language’s - compiler has failed. Compilers typically are better than programmers at producing - uniformly high-quality machine code across an entire program. Programmers, however, - understand a program’s algorithms and behavior at a deeper level than a compiler - and can expend considerable effort and ingenuity improving small sections of - the program. In particular, programmers often consider several procedures simultaneously - while writing their code. Compilers typically compile each procedure in isolation - and must follow strict conventions governing the use of registers at procedure - boundaries. By retaining commonly used values in registers, even across procedure - boundaries, programmers can make a program run faster.

-

Another major advantage of assembly language is the ability to exploit specialized - instructions, for example, string copy or pattern-matching instructions. Compilers, - in most cases, cannot determine that a program loop can be replaced by a single - instruction. However, the programmer who wrote the loop can replace it easily - with a single instruction.

-

Currently, a programmer’s advantage over a compiler has become difficult - to maintain as compilation techniques improve and machines’ pipelines increase - in complexity (Chapter 6).

-

The final reason to use assembly language is that no high-level language - is available on a particular computer. Many older or specialized computers do - not have a compiler, so a programmer’s only alternative is assembly language. -

-

Drawbacks of Assembly Language

-

Assembly language has many disadvantages that strongly argue against its - widespread use. Perhaps its major disadvantage is that programs written in assembly - language are inherently machine-specific and must be totally rewritten to run - on another computer architecture. The rapid evolution of computers discussed - in Chapter 1 means that architectures become obsolete. An assembly language - program remains tightly bound to its original architecture, even after the computer - is eclipsed by new, faster, and more cost-effective machines.

-

Another disadvantage is that assembly language programs are longer than the - equivalent programs written in a high-level language. For example, the C program - in Figure 1.5 is 11 lines long, while the assembly program in Figure 1.4 - is 31 lines long. In more complex programs, the ratio of assembly to high-level - language (its expansion factor ) can be much larger than the factor of - three in this example. Unfortunately, empirical studies have shown that programmers - write roughly the same number of lines of code per day in assembly as in high-level - languages. This means that programmers are roughly x times more productive - in a high-level language, where x is the assembly language expansion factor. -

-
- -
-

To compound the problem, longer programs are more difficult to read and understand - and they contain more bugs. Assembly language exacerbates the problem because - of its complete lack of structure. Common programming idioms, such as if-then - statements and loops, must be built from branches and jumps. The resulting - programs are hard to read because the reader must reconstruct every higher-level - construct from its pieces and each instance of a statement may be slightly different. - For example, look at Figure 1.4 and answer these questions: What type of loop - is used? What are its lower and upper bounds?

-
-
-

Elaboration:

-

Compilers can produce machine language directly instead of relying on an - assembler. These compilers typically execute much faster than those that invoke an - assembler as part of compilation. However, a compiler that generates machine language - must perform many tasks that an assembler normally handles, such as resolving addresses - and encoding instructions as binary numbers. The trade-off is between compilation speed - and compiler simplicity.

-

Elaboration:

-

Despite these considerations, some embedded applications are written in a high-level - language. Many of these applications are large and complex programs that must be - extremely reliable. Assembly language programs are longer and more difficult to write - and read than high-level language programs. This greatly increases the cost of writing - an assembly language program and makes it extremely difficult to verify the correctness - of this type of program. In fact, these considerations led the Department of Defense, - which pays for many complex embedded systems, to develop Ada, a new high-level language - for writing embedded systems.

-
-
-

Assemblers

-

An assembler translates a file of assembly language statements into a file - of binary machine instructions and binary data. The translation process has - two major parts. The first step is to find memory locations with labels so the - relationship between symbolic names and addresses is known when instructions - are translated. The second step is to translate each assembly statement by combining - the numeric equivalents of opcodes, register specifiers, and labels into a legal - instruction. As shown in Figure 1.1, the assembler produces an output file, - called an object file, which contains the machine instructions, data, - and bookkeeping information.

-

An object file typically cannot be executed because it references procedures - or data in other files. A label is - external (also called - global) if the labeled object can be referenced from files - other than the one in which it is defined. A label is local if the object can be - used only within the file in which it is defined. In most assemblers, labels are local - by default and must be explicitly declared global. Subroutines and global variables - require external labels since they are referenced from many files in a - program.Local labels hide names that should not be visible to - other modules—for example, static functions in C, which can only be called by other - functions in the same file. In addition, compiler-generated names—for example, a name - for the instruction at the beginning of a loop—are local so the compiler need not - produce unique names in every file.

-

Local and Global Labels

-

Consider the program in Figure 1.4. The subroutine has an external (global) label - main. It also contains two local labels—loop and str—that are only visible with - this assembly language file. Finally, the routine also contains an unresolved reference - to an external label printf, which is the library routine that prints values. Which - labels in Figure 1.4 could be referenced from another file?

-

Only global labels are visible outside of a file, so the only label that - could be referenced from another file is main.

-

Since the assembler processes each file in a program individually and in - isolation, it only knows the addresses of local labels. The assembler depends - on another tool, the linker, to combine a collection of object files and libraries - into an executable file by resolving external labels. The assembler assists - the linker by providing lists of labels and unresolved references.

-

However, even local labels present an interesting challenge to an assembler. - Unlike names in most high-level languages, assembly labels may be used before - they are defined. In the example, in Figure 1.4, the label str is used by - the la instruction before it is defined. The possibility of a - forward reference, like this forces an - assembler to translate a program in two steps: first find all labels is used - before it is defined. and then produce instructions. In the example, when the - assembler sees the la instruction, it does not know where the word labeled str - is located or even whether str labels an instruction or datum.

-
- -
-

An assembler’s first pass reads each line of an assembly file and breaks - it into its component pieces. These pieces, which are called lexemes, - are individual words, numbers, and punctuation characters. For example, the - line

-
-        ble $t0, 100, loop
-        
-

contains six lexemes: the opcode ble, the register specifier $t0, a comma, - the number 100, a comma, and the symbol loop.

-

If a line begins with a label, the assembler records in its - symbol table the name of the label and the - address of the memory word that the instruction occupies. The assembler then - calculates how many words of memory the instruction on the current line will - occupy. By keeping track of the instructions’ sizes, the assembler can determine - where the next instruction goes. To compute the size of a variable-length instruction, - like those on the VAX, an assembler has to examine it in detail. Fixed-length - instructions, like those on MIPS, on the other hand, require only a cursory - examination. The assembler performs a similar calculation to compute the space - required for data statements. When the assembler reaches the end of an assembly - file, the symbol table records the location of each label defined in the file. -

-

The assembler uses the information in the symbol table during a second pass over the - file, which actually produces machine code. The assembler again examines each line in - the file. If the line contains an instruction, the assembler combines the binary - representations of its opcode and operands (register specifiers or memory address) into - a legal instruction. Instructions and data words that reference an external symbol - defined in another file cannot be completely assembled (they are unresolved) since the - symbol’s address is not in the symbol table. An assembler does not complain about - unresolved references since the corresponding label is likely to be defined in another - file

-

Assembly language is a programming language. Its principal difference from - high-level languages such as BASIC, Java, and C is that assembly language provides - only a few, simple types of data and control flow. Assembly language programs - do not specify the type of value held in a variable. Instead, a programmer must - apply the appropriate operations (e.g., integer or floating-point addition) - to a value. In addition, in assembly language, programs must implement all control - flow with go to s. Both factors make assembly language programming for - any machine—MIPS or 80x86—more difficult and error-prone than writing in a high-level - language.

-
-
-

Elaboration:

-

If an assembler’s speed is important, this two-step process can be done in one - pass over the assembly file with a technique known as back - patching. In its pass over the file, the assembler builds a (possibly incomplete) - binary representation of every instruction. If the instruction references a label that - has not yet been defined, the assembler records the label and instruction in a - table. When a label is defined, the assembler consults this table to find all - instructions that contain a forward reference to the label. The assembler goes back and - corrects their binary representation to incorporate the address of the - label. Backpatching speeds assembly because the assembler only reads its input - once. However, it requires an assembler to hold the entire binary representation of a - program in memory so instructions can be backpatched. This requirement can limit the - size of programs that can be assembled. The process is complicated by machines with - several types of branches that span different ranges of instructions. When the assembler - first sees an unresolved label in a branch instruction, it must either use the largest - possible branch or risk having to go back and readjust many instructions to make room - for a larger branch. -

-
-
-

Object File Format

-

Assemblers produce object files. An object file on UNIX contains six distinct - sections (see Figure 2.1):

-
    -
  • The object file header describes the size and position of the - other pieces of the file.
  • -
  • The text segment contains the machine - language code for routines in the source file. These routines may be unexecutable - because of unresolved references.
  • -
  • The data segment contains a binary - representation of the data in the source file. The data also may be incomplete - because of unresolved references to labels in other files.
  • -
  • The relocation information identifies - instructions and data words that depend on absolute - addresses. These references must change if portions of the program - are moved in memory.
  • -
  • The symbol table associates addresses with external labels in - the source file and lists unresolved references.
  • -
  • The debugging information contains a concise description of the - way in which the program was compiled, so a debugger can find which instruction - addresses correspond to lines in a source file and print the data structures - in readable form.
  • -
-

The assembler produces an object file that contains a binary representation of the - program and data and additional information to help link pieces of a program. This - relocation information is necessary because the assembler does not know which memory - locations a procedure or piece of data will occupy after it is linked with the rest of - the program. Procedures and data from a file are stored in a contiguous piece of memory, - but the assembler does not know where this memory will be located. The assembler also - passes some symbol table entries to the linker. In particular, the assembler must record - which external symbols are defined in a file and what unresolved references occur in a - file.

-
- -
-

Figure 2.1 Object file. A UNIX - assembler produces an object file with six distinct sections.

-
-
-

Elaboration:

-

For convenience, assemblers assume each file starts at the same address (for example, - location 0) with the expectation that the linker will relocate the code and data - when they are assigned locations in memory. The assembler produces relocation - information, which contains an entry describing each instruction or data word in the - file that references an absolute address. On MIPS, only the subroutine call, - load, and store instructions reference absolute addresses. Instructions that - use PC-relative addressing, such as branches, need not be relocated.

-
-
-

Additional Facilities

-

Assemblers provide a variety of convenience features that help make assembler - programs short and easier to write, but do not fundamentally change assembly - language. For example, data layout directives allow a programmer to describe - data in a more concise and natural manner than its binary representation. -

-

In Figure 1.4, the directive

-
-        .asciiz “The sum from 0 .. 100 is %d\n”
-        
-

stores characters from the string in memory. Contrast this line with the - alternative of writing each character as its ASCII value (Figure 2.21 in Chapter - 2 describes the ASCII encoding for characters):

-
-        .byte 84, 104, 101, 32, 115, 117, 109, 32
-        .byte 102, 114, 111, 109, 32, 48, 32, 46
-        .byte 46, 32, 49, 48, 48, 32, 105, 115
-        .byte 32, 37, 100, 10, 0
-        
-

The .asciiz directive is easier to read because it represents characters as letters, - not binary numbers. An assembler can translate characters to their binary representation - much faster and more accurately than a human. Data layout - directives specify data in a human-readable form that the assembler translates to - binary.

-

String Directive

-

Define the sequence of bytes produced by this directive:

-
-        .asciiz “The quick brown fox jumps over the lazy dog”
-
-        .byte 84, 104, 101, 32, 113, 117, 105, 99 .byte 107, 32, 98, 114, 111, 119,
-        110, 32 .byte 102, 111, 120, 32, 106, 117, 109, 112 .byte 115, 32, 111, 118,
-        101, 114, 32, 116 .byte 104, 101, 32, 108, 97, 122, 121, 32 .byte 100, 111,
-        103, 0
-        
-

Macros are a pattern-matching and replacement facility that provide - a simple mechanism to name a frequently used sequence of instructions. Instead - of repeatedly typing the same instructions every time they are used, a programmer - invokes the macro and the assembler replaces the macro call with the corresponding - sequence of instructions. Macros, like subroutines, permit a programmer to create - and name a new abstraction for a common operation. Unlike subroutines, however, - macros do not cause a subroutine call and return when the program runs since - a macro call is replaced by the macro’s body when the program is assembled. - After this replacement, the resulting assembly is indistinguishable from the - equivalent program written without macros.

-

Macros

-

As an example, suppose that a programmer needs to print many numbers. The - library routine printf accepts a format string and one or more values to print - as its arguments. A programmer could print the integer in register $7 with the - following instructions:

-
-        .data
-int_str: .asciiz“%d”
-        .text
-        la $a0, int_str         # Load string address into first arg
-        mov $a1, $7             # Load value into second arg
-        jal printf              # Call the printf routine
-                
-
- -
-

The .data directive tells the assembler to store the string in the program’s - data segment, and the .text directive tells the assembler to store the instructions - in its text segment.

-

However, printing many numbers in this fashion is tedious and produces a - verbose program that is difficult to understand. An alternative is to introduce - a macro, print_int, to print an integer:

-
-        int_str:.asciiz “%d”
-        .text
-        .macro print_int($arg)
-        la $a0, int_str         # Load string address into first arg
-        mov $a1, $arg           # Load macro’s parameter ($arg) into second arg
-        jal printf              # Call the printf routine
-        .end_macro
-
-        print_int($7)
-        
-

The macro has a formal parameter, $arg, - that names the argument to the macro. When the macro is expanded, the argument - from a call is substituted for the formal parameter throughout the macro’s body. - Then the assembler replaces the call with the macro’s newly expanded body. In - the first call on print_int, the argument is $7, so the macro expands to the - code

-
-        la $a0, int_str
-        mov $a1, $7
-        jal printf
-        
-

In a second call on print_int, say, print_int($t0), the argument is $t0, - so the macro expands to

-
-        la $a0, int_str
-        mov $a1, $t0
-        jal printf
-        
-

What does the call print_int($a0) expand to?

-
-        la $a0, int_str
-        mov $a1, $a0
-        jal printf
-        
-

This example illustrates a drawback of macros. A programmer who uses this - macro must be aware that print_int uses register $a0 and so cannot correctly - print the value in that register.

- Hardware-Software Interface: -

Some assemblers also implement pseudoinstructions, which are instructions - provided by an assembler but not implemented in hardware. Chapter 2 contains many - examples of how the MIPS assembler synthesizes pseudoinstructions and addressing modes - from the spartan MIPS hardware instruction set. For example, The assembler synthesizes - the blt instruction from two other instructions: slt and bne. By extending the - instruction set, the MIPS assembler makes assembly language programming easier without - complicating the hardware. Many pseudoinstructions could also be simulated with macros, - but the MIPS assembler can generate better code for these instructions because it can - use a dedicated register ($at) and is able to optimize the generated code. -

-
-
-

Elaboration

- Assemblers conditionally assemble pieces of code, which permits a - programmer to include or exclude groups of instructions when a program is - assembled. This feature is particularly useful when several versions of - a program differ by a small amount. Rather than keep these programs in separate - files—which greatly complicates fixing bugs in the common code—programmers - typically merge the versions into a single file. Code particular to one - version is conditionally assembled, so it can be excluded when other versions - of the program are assembled. -

If macros and conditional assembly are useful, why do assemblers for - UNIX systems rarely, if ever, provide them? One reason is that most programmers - on these systems write programs in higher-level languages like C. Most of - the assembly code is produced by compilers, which find it more convenient - to repeat code rather than define macros. Another reason is that other tools - on UNIX—such as cpp, the C preprocessor, or m4, a general macro processor—can - provide macros and conditional assembly for assembly language programs. -

-
- -
-

Linkers

-

Separate compilation permits a program - to be split into pieces that are stored in different files. Each file contains - a logically related collection of subroutines and data structures that form - a module in a larger program. A file can be compiled and assembled independently - of other files, so changes to one module do not require recompiling the entire - program. As we discussed above, separate compilation necessitates the additional - step of linking to combine object files from separate modules and fix their - unresolved references.

-

The tool that merges these files is the linker (see Figure 3.1). - It performs three tasks:

-
    -
  • Searches the program libraries to find library routines used by the - program
  • -
  • Determines the memory locations that code from each module will occupy - and relocates its instructions by adjusting absolute references
  • -
  • Resolves references among files
  • -
-

A linker’s first task is to ensure that a program contains no undefined labels. - The linker matches the external symbols and unresolved references from a pro-gram’s - files. An external symbol in one file resolves a reference from another file - if both refer to a label with the same name. Unmatched references mean a symbol - was used, but not defined anywhere in the program.

-

Unresolved references at this stage in the linking process do not necessarily - mean a programmer made a mistake. The program could have referenced a library - routine whose code was not in the object files passed to the linker. After matching - symbols in the program, the linker searches the system’s program libraries to - find predefined subroutines and data structures that the program references. - The basic libraries contain routines that read and write data, allocate and - deallocate memory, and perform numeric operations. Other libraries contain routines - to access a database or manipulate terminal windows. A program that references - an unresolved symbol that is not in any library is erroneous and cannot be linked. - When the program uses a library routine, the linker extracts the routine’s code - from the library and incorporates it into the program text segment. This new - routine, in turn, may depend on other library routines, so the linker continues - to fetch other library routines until no external references are unresolved - or a routine cannot be found.

-

If all external references are resolved, the linker next determines the memory - locations that each module will occupy. Since the files were assembled in isolation, the - assembler could not know where a module’s instructions or data will be placed - relative to other modules. When the linker places a module in memory, all absolute - references must be relocated to reflect its true location. Since the linker has - relocation information that identifies all relocatable references, it can efficiently - find and backpatch these references.

-

Figure 3.1 The linker searches a - collection of object files and program libraries to find nonlocal routines used in a - program, combines them into a single executable file, and resolves references between - routines in different files.

-

The linker produces an executable file that can run on a computer. Typically, - this file has the same format as an object file, except that it contains no - unresolved references or relocation information.

-

Loading

-
- -
-

A program that links without an error can be run. Before being run, the program - resides in a file on secondary storage, such as a disk. On UNIX systems, the operating - system kernel brings a program into memory and starts it running. To start a program, - the operating system performs the following steps:

-
    -
  1. Reads the executable file’s header to determine the size of the text - and data segments.
  2. -
  3. Creates a new address space for the program. This address space is large - enough to hold the text and data segments, along with a stack segment.
  4. -
  5. Copies instructions and data from the executable file into the new address - space.
  6. -
  7. Copies arguments passed to the program onto the stack.
  8. -
  9. Initializes the machine registers. In general, most registers are cleared, - but the stack pointer must be assigned the address of the first free stack - location.
  10. -
  11. Jumps to a start-up routine that copies the program’s arguments from - the stack to registers and calls the program’s main routine. If the main - routine returns, the start-up routine terminates the program with the exit - system call.
  12. -
-

Memory Usage

-

The next few sections elaborate the description of the MIPS architecture - presented earlier in the book. Earlier chapters focused primarily on hardware - and its relationship with low-level software. These sections focus primarily - on how assembly language programmers use MIPS hardware. These sections describe - a set of conventions followed on many MIPS systems. For the most part, the hardware - does not impose these conventions. Instead, they represent an agreement among - programmers to follow the same set of rules so that software written by different - people can work together and make effective use of MIPS hardware.

-

Systems based on MIPS processors typically divide memory into three parts - (see Figure 5.1). The first part, near the bottom of the address space (starting - at address 400000hex), is the text segment, which holds the program’s - instructions.

-

The second part, above the text segment, is the data segment, which - is further divided into two parts. - Static data (starting at address 10000000hex) contains objects - whose size is known to the compiler and whose lifetime—the interval during which a - program can access them—is the program’s entire execution. For example, in C, - global variables are statically allocated since they can be referenced anytime during a - program’s execution. The linker both assigns static objects to locations in the data - segment and resolves references to these objects.

-

Figure 5.1 Layout of memory.

-

Hardware-Software Interface

- Because the data segment begins far above the program at address 10000000 - hex , load and store instructions cannot directly reference data objects with - their16-bit offset fields. For example, to load the word in the data segment at address - 10010020 hex into register $v0 requires two instructions: -
-        lui $s0, 0x1001 # 0x1001 means 1001 base 16
-        lw $v0, 0x0020($s0) # 0x10010000 + 0x0020 = 0x10010020
-        
-

(The 0x before a number means that it is a hexadecimal value. For example, - 0x8000 is 8000hex or 32,768 ten .)

-

To avoid repeating the lui instruction at every load and store, MIPS systems - typically dedicate a register ($gp) as a global pointer to the static - data segment. This register contains address 10008000 hex, so load - and store instructions can use their signed 16-bit offset fields to access the - first 64 KB of the static data segment. With this global pointer, we can rewrite - the example as a single instruction:

-
-        lw $v0, 0x8020($gp)
-        
-

Of course, a global pointer register makes addressing locations 10000000 - hex – 10010000 hex faster than other heap locations. The - MIPS compiler usually stores global variables in this area because these - variables have fixed locations and fit better than other global data, such as - arrays.

-
- -
-

Immediately above static data is dynamic data. This data, as its name implies, - is allocated by the program as it executes. In C programs, the malloc library routine - finds and returns a new block of memory. Since a compiler cannot predict how much memory - a program will allocate, the operating system expands the dynamic data area to meet - demand. As the upward arrow in the figure indicates, malloc expands the dynamic area - with the sbrk system call, which causes the operating system to add more pages to the - program’s virtual address space immediately above the dynamic data segment.

-

The third part, the program stack segment, - resides at the top of the virtual address space (starting at address 7fffffff - hex ). Like dynamic data, the maximum size of a pro-gram’s stack - is not known in advance. As the program pushes values on the stack, the operating - system expands the stack segment down, toward the data segment.

-

This three-part division of memory is not the only possible one. However, - it has two important characteristics: the two dynamically expandable segments - are as far apart as possible, and they can grow to use a program’s entire address - space.

-

Procedure Call Conventions

-

Conventions governing the use of registers are necessary when procedures - in a program are compiled separately. To compile a particular procedure, a compiler - must know which registers it may use and which registers are reserved for other - procedures. Rules for using registers are called register - use or procedure call conventions. - As the name implies, these rules are, for the most part, conventions - followed by software rather than rules enforced by hardware. However, most compilers - and programmers try very hard to follow these conventions because violating - them causes insidious bugs.

-

The calling convention described in this section is the one used by the gcc - compiler. The native MIPS compiler uses a more complex convention that is slightly - faster.

-

The MIPS CPU contains 32 general-purpose registers that are numbered 0–31. - Register $0 always contains the hardwired value 0.

-
    -
  • Registers $at (1), $k0 (26), and $k1 (27) are reserved for the assembler - and operating system and should not be used by user programs or compilers. -
  • -
  • Registers $a0–$a3 (4–7) are used to pass the first four arguments to - routines (remaining arguments are passed on the stack). Registers $v0 and - $v1 (2, 3) are used to return values from functions.
  • -
  • Registers $t0–$t9 (8–15, 24, 25) are caller-saved - registers that are used to hold temporary quantities that need not be - preserved across calls.
  • -
  • Registers $s0–$s7 (16–23) are callee-saved - registers that hold long-lived values that should be preserved - across calls.
  • -
  • Register $gp (28) is a global pointer that points to the middle of a - 64K block of memory in the static data segment.
  • -
  • Register $sp (29) is the stack pointer, which points to the last location - on the stack. Register $fp (30) is the frame pointer. The jal instruction - writes register $ra (31), the return address from a procedure call. These - two registers are explained in the next section.
  • -
-
- -
-

The two-letter abbreviations and names for these registers—for example, $sp - for the stack pointer—reflect the registers’ intended uses in the procedure - call convention. In describing this convention, we will use the names instead - of register numbers. Figure 6.1 lists the registers and describes their intended - uses.

-

Procedure Calls

-

This section describes the steps that occur when one procedure (the caller - ) invokes another procedure (the callee ). Programmers who write in - a high-level language (like C or Pascal) never see the details of how one procedure - calls another because the compiler takes care of this low-level bookkeeping. - However, assembly language programmers must explicitly implement every procedure - call and return.

-

Most of the bookkeeping associated with a call is centered around a block - of memory called a procedure call frame. - This memory is used for a variety of purposes:

-
    -
  • To hold values passed to a procedure as arguments
  • -
  • To save registers that a procedure may modify, but which the procedure’s - caller does not want changed
  • -
  • To provide space for variables local to a procedure
  • -
-

In most programming languages, procedure calls and returns follow a strict - last-in, first-out (LIFO) order, so this memory can be allocated and deallocated - on a stack, which is why these blocks of memory are sometimes called stack frames. -

-

Figure 6.2 shows a typical stack frame. The frame consists of the memory - between the frame pointer ($fp), which points to the first word of the frame, - and the stack pointer ($sp), which points to the last word of the frame. The - stack grows down from higher memory addresses, so the frame pointer points above - the stack pointer. The executing procedure uses the frame pointer to quickly - access values in its stack frame. For example, an argument in the stack frame - can be loaded into register $v0 with the instruction

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Register name Number Usage
$zero 0 constant 0
$at 1 reserved for assembler
$v0 2 expression evaluation and results of a - function
$v1 3 expression evaluation and results of a - function
$a0 4 argument 1
$a1 5 argument 2
$a2 6 argument 3
$a3 7 argument 4
$t0 8 temporary (not preserved across call) -
$t1 9 temporary (not preserved across call) -
$t2 10 temporary (not preserved across call) -
$t3 11 temporary (not preserved across call) -
$t4 12 temporary (not preserved across call) -
$t5 13 temporary (not preserved across call) -
$t6 14 temporary (not preserved across call) -
$t7 15 temporary (not preserved across call) -
$s0 16 saved temporary (preserved across call) -
$s1 17 saved temporary (preserved across call) -
$s2 18 saved temporary (preserved across call) -
$s3 19 saved temporary (preserved across call) -
$s4 20 saved temporary (preserved across call) -
$s5 21 saved temporary (preserved across call) -
$s6 22 saved temporary (preserved across call) -
$s7 23 saved temporary (preserved across call) -
$t8 24 temporary (not preserved across call) -
$t9 25 temporary (not preserved across call) -
$k0 26 reserved for OS kernel
$k1 27 reserved for OS kernel
$gp 28 pointer to global area
$sp 29 stack pointer
$fp 30 frame pointer
$ra 31 return address (used by function call) -
-

Figure 6.1 MIPS registers and usage convention.

-
-        lw $v0, 0($fp)
-        
-

Figure 6.2 Layout of a stack - frame. The frame pointer ($fp) points to the first word in the currently - executing procedure’s stack frame. The stack pointer ($sp) points to the last - word of frame. The first four arguments are passed in registers, so the fifth - argument is the first one stored on the stack.

-

A stack frame may be built in many different ways; however, the caller and - callee must agree on the sequence of steps. The steps below describe the calling - convention used on most MIPS machines. This convention comes into play at three - points during a procedure call: immediately before the caller invokes the callee, - just as the callee starts executing, and immediately before the callee returns - to the caller. In the first part, the caller puts the procedure call arguments - in standard places and invokes the callee to do the following:

-
    -
  1. Pass arguments. By convention, the first four arguments are passed in - registers $a0–$a3. Any remaining arguments are pushed on the stack and appear - at the beginning of the called procedure’s stack frame.
  2. -
  3. Save caller-saved registers. The called procedure can use these registers - ($a0–$a3 and $t0–$t9) without first saving their value. If the caller expects - to use one of these registers after a call, it must save its value before - the call.
  4. -
  5. Execute a jal instruction, which jumps to the callee’s first instruction - and saves the return address in register $ra.
  6. -
-

Before a called routine starts running, it must take the following steps - to set up its stack frame:

-
    -
  1. Allocate memory for the frame by subtracting the frame’s size from the - stack pointer.
  2. -
  3. Save callee-saved registers in the frame. A callee must save the values - in these registers ($s0–$s7, $fp, and $ra) before altering them since the - caller expects to find these registers unchanged after the call. Register - $fp is saved by every procedure that allocates a new stack frame. However, - register $ra only needs to be saved if the callee itself makes a call. The - other calleesaved registers that are used also must be saved.
  4. -
  5. Establish the frame pointer by adding the stack frame’s size minus 4 - to $sp and storing the sum in register $fp.
  6. -
-

Hardware-Software Interface

-

The MIPS register use convention provides callee- and caller-saved registers because - both types of registers are advantageous in different circumstances. Callee-saved - registers are better used to hold long-lived values, such as variables from a user’s - program. These registers are only saved during a procedure call if the callee expects to - use the register. On the other hand, caller-saved registers are better used to hold - short-lived quantities that do not persist across a call, such as immediate values in an - address calculation. During a call, the callee can also use these registers for - short-lived temporaries.

-

Finally, the callee returns to the caller by executing the following steps: -

-
    -
  1. If the callee is a function that returns a value, place the returned value - in register $v0.
  2. -
  3. Restore all callee-saved registers that were saved upon procedure entry. -
  4. -
  5. Pop the stack frame by adding the frame size to $sp.
  6. -
  7. Return by jumping to the address in register $ra.
  8. -
-
-
-

Elaboration:

-

A programming language that does not permit recursive - procedures— procedures that call themselves either directly or - indirectly through a chain of calls—need not allocate frames on a stack. In a - nonrecursive language, each procedure’s frame may be statically allocated - since only one invocation of a procedure can be active at a time. Older versions - of Fortran prohibited recursion because statically allocated frames produced - faster code on some older machines. However, on load-store architectures like - MIPS, stack frames may be just as fast because a frame pointer register points - directly to -

-
- -
-

the active stack frame, which permits a single load or store instruction - to access values in the frame. In addition, recursion is a valuable programming - technique.

-

Procedure Call Example

-
-        main () {
-          printf ("The factorial of 10 is %d\n", fact (10));
-        }
-
-        int fact (int n) {
-          if (n < 1)
-            return (1);
-          else
-            return (n * fact (n - 1));
-        }
-        
-

which computes and prints 10! (the factorial of 10, 10! = 10 × 9 × . . . - × 1). fact is a recursive routine that computes n ! by multiplying - n times ( n – 1)!. The assembly code for this routine illustrates how - programs manipulate stack frames.

-

Upon entry, the routine main creates its stack frame and saves the two calleesaved - registers it will modify: $fp and $ra. The frame is larger than required for - these two registers because the calling convention requires the minimum size - of a stack frame to be 24 bytes. This minimum frame can hold four argument registers - ($a0–$a3) and the return address $ra, padded to a double-word boundary (24 bytes). - Since main also needs to save $fp, its stack frame must be two words larger - (remember: the stack pointer is kept doubleword aligned).

-
-        .text
-        .globl main
-main:
-        subu $sp,$sp,32         # Stack frame is 32 bytes long
-        sw $ra,20($sp)          # Save return address
-        sw $fp,16($sp)          # Save old frame pointer
-        addiu $fp,$sp,28        # Set up frame pointer
-        
-

The routine main then calls the factorial routine and passes it the single - argument 10. After fact returns, main calls the library routine printf and passes - it both a format string and the result returned from fact:

-
-        li $a0,10               # Put argument (10) in $a0
-        jal fact                # Call factorial function
-        la $a0,$LC              # Put format string in $a0
-        move $a1,$v0            # Move fact result to $a1
-        jal printf              # Call the print function
-        
-

Finally, after printing the factorial, main returns. But first, it must restore - the registers it saved and pop its stack frame:

-
-        lw $ra,20($sp)          # Restore return address
-        lw $fp,16($sp)          # Restore frame pointer
-        addiu $sp,$sp,32        # Pop stack frame
-        jr $ra                  # Return to caller
-        .rdata
-$LC:
-        .ascii “The factorial of 10 is %d\n\000”
-        
-

The factorial routine is similar in structure to main. First, it creates - a stack frame and saves the callee-saved registers it will use. In addition - to saving $ra and $fp, fact also saves its argument ($a0), which it will use - for the recursive call:

-
-        lw $ra,20($sp)          # Restore return address
-        lw $fp,16($sp)          # Restore frame pointer
-        addiu $sp,$sp,32        # Pop stack frame
-        jr $ra                  # Return to caller
-        .rdata
-$LC:
-        .ascii “The factorial of 10 is %d\n\000”
-        
-

The heart of the fact routine performs the computation from the C program. - It tests if the argument is greater than 0. If not, the routine returns the - value 1. If the argument is greater than 0, the routine recursively calls itself - to compute fact(n-1) and multiplies that value times n:

-
-        lw $v0,0($fp)           # Load n
-        bgtz $v0,$L2            # Branch if n > 0
-        li $v0,1                # Return 1
-        jr $L1                  # Jump to code to return
-$L2:
-        lw $v1,0($fp)           # Load n
-        subu $v0,$v1,1          # Compute n - 1
-        move $a0,$v0            # Move value to $a0
-        jal fact                # Call factorial function
-        lw $v1,0($fp)           # Load n
-        mul $v0,$v0,$v1         # Compute fact(n-1) * n
-        
-

Finally, the factorial routine restores the callee-saved registers and returns - the value in register $v0:

-
-        $L1:                    # Result is in $v0
-        lw $ra, 20($sp)         # Restore $ra
-        lw $fp, 16($sp)         # Restore $fp
-        addiu $sp, $sp, 32      # Pop stack
-        jr $ra                  # Return to caller
-        
-

Stack in Recursive Procedure

-

Figure 6.3 shows the stack at the call fact(7). main runs first, so its - frame is deepest on the stack. main calls fact(10), whose stack frame is next - on the stack. Each invocation recursively invokes fact to compute the next-lowest - factorial. The stack frames parallel the LIFO order of these calls.

-

Figure 6.3 Stack frames during the call of fact(7).

-

What does the stack look like when the call to fact(10) returns?

- -
-
-

Elaboration:

-

The difference between the MIPS compiler and the gcc compiler is that the MIPS - compiler usually does not use a frame pointer, so this register is available as another - callee-saved register, $s8. This change saves a couple of instructions in the procedure - call and return sequence. However, it complicates code generation because a procedure - must access its stack frame with $sp, whose value can change during a procedure’s - execution if values are pushed on the stack.

-
-
-

Another Procedure Call Example

-

As another example, consider the following routine that computes the tak - function, which is a widely used benchmark created by Ikuo Takeuchi. This function - does not compute anything useful, but is a heavily recursive program that illustrates - the MIPS calling convention.

-
-        int tak (int x, int y, int z) {
-          if (y < x)
-                return 1 + tak (tak (x - 1, y, z),
-                                tak (y - 1, z, x),
-                                tak (z - 1, x, y));
-          else
-                return z;
-        }
-
-        int main () {
-          tak(18, 12, 6);
-        }
-        
-

The assembly code for this program is below. The tak function first saves its return - address in its stack frame and its arguments in callee-saved registers, since the - routine may make calls that need to use registers $a0–$a2 and $ra. The function uses - callee-saved registers since they hold values that persist over the lifetime of the - function, which includes several calls that could potentially modify registers.

-
-        .text
-        .globl tak
-tak:
-        subu $sp, $sp, 40
-        sw $ra, 32($sp)
-        sw $s0, 16($sp)         # x
-        move $s0, $a0
-        sw $s1, 20($sp)         # y
-        move $s1, $a1
-        sw $s2, 24($sp)         # z
-        move $s2, $a2
-        sw $s3, 28($sp)         # temporary
-        
-

The routine then begins execution by testing if y < x. If not, it branches - to label L1, which is below.

-
-        bge $s1, $s0, L1 # if (y < x)
-        
-

If y < x, then it executes the body of the routine, which contains four recursive - calls. The first call uses almost the same arguments as its parent:

-
-        addiu $a0, $s0, -1
-        move $a1, $s1
-        move $a2, $s2
-        jal tak                 # tak (x - 1, y, z)
-        move $s3, $v0
-        
-

Note that the result from the first recursive call is saved in register $s3, - so that it can be used later. The function now prepares arguments for the second - recursive call.

-
-        addiu $a0, $s1, -1
-        move $a1, $s2
-        move $a2, $s0
-        jal tak                 # tak (y - 1, z, x)
-        
-

In the instructions below, the result from this recursive call is saved in - register $s0. But, first we need to read, for the last time, the saved value - of the first argument from this register.

-
-        addiu $a0, $s2, -1
-        move $a1, $s0
-        move $a2, $s1
-        move $s0, $v0
-        jal tak                 # tak (z - 1, x, y)
-        
-

After the three inner recursive calls, we are ready for the final recursive - call. After the call, the function’s result is in $v0 and control jumps to the - function’s epilogue.

-
-        move $a0, $s3
-        move $a1, $s0
-        move $a2, $v0
-        jal tak                 # tak (tak(...), tak(...), tak(...))
-        addiu $v0, $v0, 1
-        j L2
-        
-

This code at label L1 is the consequent of the if-then-else statement. - It just moves the value of argument z into the return register and falls into - the function epilogue.

-
-L1:
-        move $v0, $s2
-        
-

The code below is the function epilogue, which restores the saved registers - and returns the function’s result to its caller.

-
-L2:
-        lw $ra, 32($sp)
-        lw $s0, 16($sp)
-        lw $s1, 20($sp)
-        lw $s2, 24($sp)
-        lw $s3, 28($sp)
-        addiu $sp, $sp, 40
-        jr $ra
-        
-

The main routine calls the tak function with its initial arguments, then - takes the computed result (7) and prints it using SPIM’s system call for printing - integers.

-
-        .globl main
-main:
-        subu $sp, $sp, 24
-        sw $ra, 16($sp)
-        li $a0, 18
-        li $a1, 12
-        li $a2, 6
-        jal tak                 # tak(18, 12, 6)
-        move $a0, $v0
-        li $v0, 1               # print_int syscall
-        syscall
-        lw $ra, 16($sp)
-        addiu $sp, $sp, 24
-        jr $ra
-        
-

Exceptions and Interrupts

-

The MIPS exception facility, which responds both to exceptions caused by errors - during an instruction’s execution and to external interrupts caused by I/O - devices. This section describes exception and interrupt - handling in more detail. - 1 In MIPS processors, a part of the CPU called coprocessor 0 - records the information that software needs to handle exceptions and interrupts. - The MIPS simulator SPIM does not implement all of coprocessor 0’s registers, - since many are not useful in a simulator or are part of the memory system, which - SPIM does not model. However, SPIM does provide the following coprocessor 0 - registers:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Register nameRegister numberUsage
BadVAddr 8 memory address at which an offending memory reference - occurred
Count 9 timer
Compare 11 value compared against timer that causes interrupt - when they match
Status 12 interrupt mask and enable bits
Cause 13 exception type and pending interrupt bits
EPC 14 address of instruction that caused exception
Config 16 configuration of machine
-

1. This section discusses exceptions in the MIPS32 architecture, which is - what SPIM implementsin Version 7.0 and later. Earlier versions of SPIM implemented - the MIPS-I architecture, which handled exceptions slightly differently. Converting - programs from these versions to run on MIPS32 should not be difficult, as the - changes are limited to the Status and Cause register fields and the replacement - of the rfe instruction by the eret instruction.

-
- -
-

These seven registers are part of coprocessor 0’s register set. They are - accessed by the mfc0 and mtc0 instructions. After an exception, register EPC - contains the address of the instruction that was executing when the exception - occurred. If the exception was caused by an external interrupt, then the instruction - will not have started executing. All other exceptions are caused by the execution - of the instruction at EPC, except when the offending instruction is in the delay - slot of a branch or jump. In that case, EPC points to the branch or jump instruction - and the BD bit is set in the Cause register. When that bit is set, the exception - handler must look at EPC + 4 for the offending instruction. However, in either - case, an exception handler properly resumes the program by returning to the - instruction at EPC.

-

If the instruction that caused the exception made a memory access, register - BadVAddr contains the referenced memory location’s address.

-

The Count register is a timer that increments at a fixed rate (by default, - every 10 milliseconds) while SPIM is running. When the value in the Count register - equals the value in the Compare register, a hardware interrupt at priority level - 5 occurs.

-

Figure 7.1 shows the subset of the Status register fields implemented by - the MIPS simulator SPIM. The interrupt mask field contains a bit for each of - the six hardware and two software interrupt levels. A mask bit that is 1 allows - interrupts at that level to interrupt the processor. A mask bit that is 0 disables - interrupts at that level. When an interrupt arrives, it sets its interrupt pending - bit in the Cause register, even if the mask bit is disabled. When an interrupt - is pending, it will interrupt the processor when its mask bit is subsequently - enabled.

-

The user mode bit is 0 if the processor is running in kernel mode and 1 if it is - running in user mode. On SPIM, this bit is fixed at 1, since the SPIM processor does not - implement kernel mode. The exception level bit is normally 0, but is set to 1 after an - exception occurs. When this bit is 1, interrupts are disabled and the EPC is not updated - if another exception occurs. This bit prevents an exception handler from being disturbed - by an interrupt or exception, but it should be reset when the handler finishes. If the - interrupt enable bit is 1, interrupts are allowed. If it is 0, they are disabled.

-

Figure 7.1 The Status register. -

-

Figure 7.2 The Cause register. -

-

Figure 7.2 shows the subset of Cause register fields that SPIM implements. - The branch delay bit is 1 if the last exception occurred in an instruction executed - in the delay slot of a branch. The interrupt pending bits become 1 when an interrupt - is raised at a given hardware or software level. The exception code register - describes the cause of an exception through the following codes:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NumberName Cause of exception
0 Int interrupt (hardware)
4 AdEL address error exception (load or instruction fetch) -
5 AdES address error exception (store)
6 IBE bus error on instruction fetch
7 DBE bus error on data load or store
8 Sys syscall exception
9 Bp breakpoint exception
10 RI reserved instruction exception
11 CpU coprocessor unimplemented
12 Ov arithmetic overflow exception
13 Tr trap
15 FPE floating point
-

Exceptions and interrupts cause a MIPS processor to jump to a piece of code, - at address 80000180 hex (in the kernel, not user address space), - called an exception handler. This code examines the exception’s cause - and jumps to an appropriate point in the operating system. The operating system - responds to an exception either by terminating the process that caused the exception - or by performing some action. A process that causes an error, such as executing - an unimplemented instruction, is killed by the operating system. On the other - hand, other exceptions such as page faults are requests from a process to the - operating system to perform a service, such as bringing in a page from disk. - The operating system processes these requests and resumes the process. The final - type of exceptions are interrupts from external devices. These generally cause - the operating system to move data to or from an I/O device and resume the interrupted - process.

-

The code in the example below is a simple exception handler, which invokes - a routine to print a message at each exception (but not interrupts). This code - is similar to the exception handler (exceptions.s) used by the SPIM simulator. -

-

Exception Handler

-

The exception handler first saves register $at, which is used in pseudo-instructions - in the handler code, then saves $a0 and $a1, which it later uses to pass arguments. - The exception handler cannot store the old values from these registers on the - stack, as would an ordinary routine, because the cause of the exception might - have been a memory reference that used a bad value (such as 0) in the stack - pointer. Instead, the exception handler stores these registers in an exception - handler register ($k1, since it can’t access memory without using $at) and two - memory locations (save0 and save1). If the exception routine itself could be - interrupted, two locations would not be enough since the second exception would - overwrite values saved during the first exception. However, this simple exception - handler finishes running before it enables interrupts, so the problem does not - arise.

-
-        .ktext 0x80000180
-        mov $k1, $at            # Save $at register
-        sw $a0, save0           # Handler is not re-entrant and can’t use
-        sw $a1, save1           # stack to save $a0, $a1
-        # Don’t need to save $k0/$k1
-        
-

The exception handler then moves the Cause and EPC registers into CPU registers. - The Cause and EPC registers are not part of the CPU register set. Instead, they - are registers in coprocessor 0, which is the part of the CPU that handles exceptions. - The instruction mfc0 $k0, $13 moves coprocessor 0’s register 13 (the Cause register) - into CPU register $k0. Note that the exception handler need not save registers - $k0 and $k1 because user programs are not supposed to use these registers. The - exception handler uses the value from the Cause register to test if the exception - was caused by an interrupt (see the preceding table). If so, the exception is - ignored. If the exception was not an interrupt, the handler calls print_excp - to print a message.

-
-        mfc0 $k0, $13           # Move Cause into $k0
-        srl $a0, $k0, 2         # Extract ExcCode field
-        andi $a0, $a0, 0xf
-        bgtz $a0, done          # Branch if ExcCode is Int (0)
-        mov $a0, $k0            # Move Cause into $a0
-        mfc0 $a1, $14           # Move EPC into $a1
-        jal print_excp          # Print exception error messa
-        
-

Before returning, the exception handler clears the Cause register; resets - the Status register to enable interrupts and clear the EXL bit, which allows - subsequent exceptions to change the EPC register; and restores registers $a0, - $a1, and $at. It then executes the eret (exception return) instruction, which - returns to the instruction pointed to by EPC. This exception handler returns - to the instruction following the one that caused the exception, so as to not - reexecute the faulting instruction and cause the same exception again.

-
-        done: mfc0 $k0, $14     # Bump EPC
-        addiu $k0, $k0, 4       # Do not reexecute
-        # faulting instruction
-        mtc0 $k0, $14           # EPC
-        mtc0 $0, $13            # Clear Cause register
-        mfc0 $k0, $12           # Fix Status register
-        andi $k0, 0xfffd        # Clear EXL bit
-        ori $k0, 0x1            # Enable interrupts
-        mtc0 $k0, $12
-        lw $a0, save0           # Restore registers
-        lw $a1, save1
-        mov $at, $k1
-        eret                    # Return to EPC
-        .kdata
-save0:  .word 0
-save1:  .word 0
-        
-
-
-

Elaboration:

-

On real MIPS processors, the return from an exception handler is more complex. The - exception handler cannot always jump to the instruction following EPC. For example, if - the instruction that caused the exception was in a branch instruction’s delay slot - (see Chapter 6), the next instruction to execute may not be the following instruction in - memory.

-
-
-

Input and Output

-

SPIM simulates one I/O device: a memory-mapped console on which a program - can read and write characters. When a program is running, SPIM connects its - own terminal (or a separate console window in the X-window version xspim or - the Windows version PCSpim) to the processor. A MIPS program running on SPIM - can read the characters that you type. In addition, if the MIPS program writes - characters to the terminal, they appear on SPIM’s terminal or console window. - One exception to this rule is control-C: this character is not passed to the - program, but instead causes SPIM to stop and return to command mode. When the - program stops running (for example, because you typed control-C or because the - program hit a breakpoint), the terminal is reconnected to SPIM so you can type - SPIM commands.

-

To use memory-mapped I/O (see below), spim or xspim must be started with - the -mapped_io flag. PCSpim can enable memory-mapped I/O through a command line - flag or the "Settings" dialog.

-

The terminal device consists of two independent units: a receiver - and a trans mitter. The receiver reads characters typed - on the keyboard. The transmitter display characters on the console. The two - units are completely independent. This means, for example, that characters typed - at the keyboard are not automatically echoed on the display. Instead, a program - echoes a character by reading it from the receiver and writing it to the transmitter. -

-

A program controls the terminal with four memory-mapped device registers, - as shown in Figure 8.1. “Memory-mapped’’ means that each register appears - as a special memory location. The Receiver Control register is at location - ffff0000 hex . Only two of its bits are actually used. Bit 0 is called - “ready’’: if it is 1, it means that a character has arrived from the keyboard - but has not yet been read from the Receiver Data register. The ready bit is - read-only: writes to it are ignored. The ready bit changes from 0 to 1 when - a character is typed at the keyboard, and it changes from 1 to 0 when the character - is read from the Receiver Data register.

-

Figure 8.1 The terminal is controlled - by four device registers, each of which appears as a memory location at the - given address. Only a few bits of these registers are actually used. The - others always read as 0s and are ignored on writes.

-

Bit 1 of the Receiver Control register is the keyboard “interrupt enable.” This - bit may be both read and written by a program. The interrupt enable is initially 0. If - it is set to 1 by a program, the terminal requests an interrupt at hardware level 1 - whenever a character is typed and the ready bit becomes 1. However, for the interrupt to - affect the processor, interrupts must also be enabled in the Status register. All other - bits of the Receiver Control register are unused.

-

The second terminal device register is the Receiver Data register - (at address ffff0004hex). The low-order 8 bits of this register contain the - last character typed at the keyboard. All other bits contain 0s. This register - is read-only and changes only when a new character is typed at the keyboard. - Reading the Receiver Data register resets the ready bit in the Receiver Control - register to 0. The value in this register is undefined if the Receiver Control - register is 0.

-

The third terminal device register is the Transmitter Control register - (at address ffff0008 hex ). Only the low-order 2 bits of this - register are used. They behave much like the corresponding bits of the Receiver - Control register. Bit 0 is called “ready’’ and is read-only. If this bit is - 1, the transmitter is ready to accept a new character for output. If it is 0, - the transmitter is still busy writing the previous character. Bit 1 is “interrupt - enable’’ and is readable and writable. If this bit is set to 1, then the terminal - requests an interrupt at hardware level 0 whenever the transmitter is ready - for a new character and the ready bit becomes 1.

-

The final device register is the Transmitter Data register (at address - ffff000c hex ). When a value is written into this location, its low-order - 8 bits (i.e., an ASCII character as in Figure 2.21 in Chapter 2) are sent to - the console. When the Transmitter Data register is written, the ready bit in - the Transmitter Control register is reset to

-

0. This bit stays 0 until enough time has elapsed to transmit the character - to the terminal; then the ready bit becomes 1 again. The Transmitter Data register - should only be written when the ready bit of the Transmitter Control register - is 1. If the transmitter is not ready, writes to the Transmitter Data register - are ignored (the write appears to succeed but the character is not output). -

-

Real computers require time to send characters to a console or terminal. - These time lags are simulated by SPIM. For example, after the transmitter starts - to write a character, the transmitter’s ready bit becomes 0 for a while. SPIM - measures time in instructions executed, not in real clock time. This means that - the transmitter does not become ready again until the processor executes a fixed - number of instructions. If you stop the machine and look at the ready bit, it - will not change. However, if you let the machine run, the bit eventually changes - back to 1.

-

SPIM

-

SPIM is a software simulator that runs assembly language programs written - for processors that implement the MIPS32 architecture, specifically Release - 1 of this architecture with a fixed memory mapping, no caches, and only coprocessors - 0 and 1.2 SPIM’s name is just MIPS spelled backwards. SPIM can read - and immediately execute assembly language files. SPIM is a self-contained system - for running MIPS programs. It contains a debugger and provides a few operating - system–like services. SPIM is much slower than a real computer (100 or more times). - However, its low cost and wide availability cannot be matched by - real hardware! -

-

Earlier versions of SPIM (before 7.0) implemented the MIPS-I architecture - used in the original MIPS R2000 processors. This architecture is almost a proper - subset of the MIPS32 architecture, with the difference being the manner in which - exceptions are handled. MIPS32 also introduced approximately 60 new instructions, - which are supported by SPIM. Programs that ran on the earlier versions of SPIM - and did not use exceptions should run unmodified on newer versions of SPIM. - Programs that used exceptions will require minor changes.

-

An obvious question is, Why use a simulator when most people have PCs that - contain processors that run significantly faster than SPIM? One reason is that - the processor in PCs are Intel 80x86s, whose architecture is far less regular - and far more complex to understand and program than MIPS processors. The MIPS - architecture may be the epitome of a simple, clean RISC machine.

-

In addition, simulators can provide a better environment for assembly programming - than an actual machine because they can detect more errors and provide a better - interface than an actual computer.

-

Finally, simulators are a useful tool in studying computers and the programs - that run on them. Because they are implemented in software, not silicon, simulators - can be examined and easily modified to add new instructions, build new systems - such as multiprocessors, or simply to collect data.

-

Simulation of a Virtual Machine

-

The basic MIPS architecture is difficult to program directly because of delayed - branches, delayed loads, and restricted address modes. This difficulty is tolerable - since these computers were designed to be programmed in high-level languages - and present an interface designed for compilers rather than assembly language - programmers. A good part of the programming complexity results from delayed - instructions. A delayed branch requires two cycles to execute. In the - second cycle, the instruction immediately following the branch executes. This - instruction can perform useful work that normally would have been done before - the branch. It can also be a nop (no operation) that does nothing. Similarly, - delayed loads require 2 cycles to bring a value from memory, so the instruction - immediately following a load cannot use the value.

-

MIPS wisely chose to hide this complexity by having its assembler implement - a virtual machine . This virtual computer - appears to have nondelayed branches and loads and a richer instruction set than - the actual hardware. The assembler reorga nizes (rearranges) - instructions to fill the delay slots. The virtual computer also provides - pseudoinstructions, which appear as real instructions in assembly language - programs. The hardware, however, knows nothing about pseudoinstructions, so - the assembler translates them into equivalent sequences of actual machine instructions. - For example, the MIPS hardware only provides instructions to branch when a register - is equal to or not equal to 0. Other conditional branches, such as one that - branches when one register is greater than another, are synthesized by comparing - the two registers and branching when the result of the comparison is true (nonzero). -

-
- -
-

By default, SPIM simulates the richer virtual machine, since this is the - machine that most programmers will find useful. However, SPIM can also simulate - the delayed branches and loads in the actual hardware. Below, we describe the - virtual machine and only mention in passing features that do not belong to the - actual hardware. In doing so, we follow the convention of MIPS assembly language - programmers (and compilers), who routinely use the extended machine as if it - was implemented in silicon.

-

Getting Started with SPIM

-

The rest of this appendix introduces SPIM and the MIPS R2000 Assembly language. - Many details should never concern you; however, the sheer volume of information - can sometimes obscure the fact that SPIM is a simple, easy-to-use program. This - section starts with a quick tutorial on using SPIM, which should enable you - to load, debug, and run simple MIPS programs.

-

SPIM comes in different versions for different types of computer systems. - The one constant is the simplest version, called spim, which is a command-line-driven - program that runs in a console window. It operates like most programs of this - type: you type a line of text, hit the return key, and spim executes your command. - Despite its lack of a fancy interface, spim can do everything that its fancy - cousins can do.

-

QtSpim is a version of the simulator with a window interface. It runs on Microsoft - Windows, Apple OS X, and Linux.

-

There are two older cousins to spim. The version that runs in the X-windows - environment of a UNIX or Linux system is called xspim. PCspim is a windowing - version of spim that runs on Microsoft Windows.

-

Surprising Features

-

Although SPIM faithfully simulates the MIPS computer, SPIM is a simulator - and certain things are not identical to an actual computer. The most obvious - differences are that instruction timing and the memory system are not identical. - SPIM does not simulate caches or memory latency, nor does it accurately reflect - float-ing-point operation or multiply and divide instruction delays. In addition, - the floating-point instructions do not detect many error conditions, which would - cause exceptions on a real machine.

-

Another surprise (which occurs on the real machine as well) is that a pseudoinstruction - expands to several machine instructions. When you single-step or examine memory, - the instructions that you see are different from the source program. The correspondence - between the two sets of instructions is fairly simple since SPIM does not reorganize - instructions to fill delay slots.

-

Byte Order

-

Processors can number bytes within a word so the byte with the lowest number - is either the leftmost or rightmost one. The convention used by a machine is - called its byte order. MIPS processors can operate with either big-endian - or little-endian byte order. For example, in a big-endian machine, - the directive .byte 0, 1, 2, 3 would result in a memory word containing

- - - - - - - - - - -
Byte #
0 1 2 3
-

while in a little-endian machine, the word would contain

- - - - - - - - - - -
Byte #
3 2 1 0
-

SPIM operates with both byte orders. SPIM’s byte order is the same as the - byte order of the underlying machine that runs the simulator. For example, on - a Intel 80x86, SPIM is little-endian, while on a Macintosh or Sun SPARC, SPIM - is bigendian.

-

System Calls

-

SPIM provides a small set of operating-system-like services through the system - call (syscall) instruction. To request a service, a program loads the system - call code (see Figure 9.1) into register $v0 and arguments into registers - $a0–$a3 (or $f12 for floating-point values). System calls that return values - put their results in register $v0 (or $f0 for floating-point results). For example, - the following code prints “the answer = 5’’:

-
-        .data
-str:
-        .asciiz "the answer = "
-        .text
-        li $v0, 4               # system call code for print_str
-        la $a0, str             # address of string to print
-        syscall                 # print the string
-        li $v0, 1               # system call code for print_int
-        li $a0, 5               # integer to print
-        syscall                 # print it
-        
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Service System call code Arguments Result
print_int 1 $a0 = integer  
print_float 2 $f12 = float  
print_double 3 $f12 = double  
print_string 4 $a0 = string  
read_int 5   integer (in $v0)
read_float 6   float (in $f0)
read_double 7   double (in $f0)
read_string 8 $a0 = buffer, $a1 = length  
sbrk 9 $a0 = amount address (in $v0)
exit 10    
print_char 11 $a0 = char  
read_char 12   char (in $v0)
open 13 $a0 = filename (string), $a1 = flags, $a2 - = mode file descriptor (in $v0) -
read 14 $a0 = file descriptor, $a1 = buffer, $a2 - = length num chars read (in $v0)
write 15 $a0 = file descriptor, $a1 = buffer, $a2 - = length num chars written (in $v0)
close 16 $a0 = file descriptor  
exit2 17 $a0 = result  
-

Figure 9.1 System services.

-

The print_int system call is passed an integer and prints it on the console. - print_float prints a single floating-point number; print_double prints a double - precision number; and print_string is passed a pointer to a null-ter-minated - string, which it writes to the console.

-

The system calls read_int, read_float, and read_double read an entire line - of input up to and including the newline. Characters following the number are - ignored. read_string has the same semantics as the UNIX library routine fgets. - It reads up to n – 1 characters into a buffer and terminates the string - with a null byte. If fewer than n – 1 characters are on the current line, - read_string reads up to and including the newline and again null-terminates - the string.

-

Warning: Programs that use these syscalls to read from the terminal should not - use memory-mapped I/O.

-

sbrk returns a pointer to a block of memory containing n additional - bytes. exit stops the program SPIM is running. exit2 terminates the SPIM program, - and the argument to exit2 becomes the value returned when the SPIM simulator - itself terminates.

-

print_char and read_char write and read a single character. open, read, write, - and close are the standard UNIX library calls.

-

MIPS R2000 Assembly Language

-

A MIPS processor consists of an integer processing unit (the CPU) and a collection - of coprocessors that perform ancillary tasks or operate on other types of data - such as floating-point numbers (see Figure 10.1). SPIM simulates two coprocessors. - Coprocessor 0 handles exceptions and interrupts. Coprocessor 1 is the float-ing-point - unit. SPIM simulates most aspects of this unit.

-

Addressing Modes

-

MIPS is a load-store architecture, which means that only load and store instructions - access memory. Computation instructions operate only on values in registers. - The bare machine provides only one memory-addressing mode: c(rx), which uses - the sum of the immediate c and register rx as the address. The virtual machine - provides the following addressing modes for load and store instructions:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FormatAddress computation
(register) contents of register
imm immediate
imm (register) immediate + contents of register
label address of label
label ± imm address of label + or – immediate
label ± imm (register) address of label + or – (immediate + contents of register) -
-

Most load and store instructions operate only on aligned data. A quantity - is aligned if its memory address is a multiple of its size in bytes. Therefore, - a half

-

Figure 10.1 MIPS R2000 CPU and - FPU.

-

word object must be stored at even addresses and a full word object must - be stored at addresses that are a multiple of four. However, MIPS provides some - instructions to manipulate unaligned data (lwl, lwr, swl, and swr).

-
-
-

Elaboration:

-

The MIPS assembler (and SPIM) synthesizes the more complex addressing modes by - producing one or more instructions before the load or store to compute a complex - address. For example, suppose that the label table referred to memory location - 0x10000004 and a program contained the instruction

-
-                ld $a0, table + 4($a1)
-        
-

The assembler would translate this instruction into the instructions

-
-        lui $at, 4096
-        addu $at, $at, $a1
-        lw $a0, 8($at)
-        
-

The first instruction loads the upper bits of the label’s address into register - $at, which is the register that the assembler reserves for its own use. The - second instruction adds the contents of register $a1 to the label’s partial - address. Finally, the load instruction uses the hardware address mode to add - the sum of the lower bits of the label’s address and the offset from the original - instruction to the value in register $at.

-
-
-

Assembler Syntax

-

Comments in assembler files begin with a sharp sign (#). Everything from the sharp - sign to the end of the line is ignored.

-

Identifiers are a sequence of alphanumeric characters, underbars (_), and dots (.) - that do not begin with a number. Instruction opcodes are reserved words - that cannot be used as identifiers. Labels are declared by putting them at the - beginning of a line followed by a colon, for example:

-
-        lui $at, 4096
-        addu $at, $at, $a1
-        lw $a0, 8($at)
-        
-

Numbers are base 10 by default. If they are preceded by 0x, they are - interpreted as hexadecimal. Hence, 256 and 0x100 denote the same value.

-

Strings are enclosed in doublequotes ("). Special characters in strings follow - the C convention:

-
    -
  • newline \n
  • -
  • tab \t
  • -
  • quote \"
  • -
-

SPIM supports a subset of the MIPS assembler directives:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
.align n Align the next datum on a 2 n byte boundary. For example, - .align 2 aligns the next value on a word boundary. .align 0 turns off automatic - alignment of .half, .word, .float, and .double directives until the next .data or - .kdata directive.
.ascii str Store the string str in memory, but do not null-terminate it.
.asciiz str Store the string str in memory and null-terminated it.
.byte b1,..., bn Store the n values in successive bytes of memory.
.data Subsequent items are stored in the data segment. If the optional - argument addr is present, subsequent items are stored starting at - address addr.
.double d1, ..., dn Store the n floating-point double precision numbers in successive memory - locations.
.extern sym size Declare that the datum stored at sym is size bytes and is a global - label. This directive enables assembler to store the datum in a portion of data - segment that is efficiently accessed via register $gp.
.float f1,..., fn Store the n floating-point single precision numbers in successive memory - locations.
.globl sym Declare that label sym is global and can be referenced from other - files.
.half h1, ..., hn Store the n 16-bit quantities in successive memory halfwords. -
.kdata Subsequent data items are stored in the kernel segment. If the optional - argument addr is present, subsequent items are stored starting at - address addr.
.ktext Subsequent items are put in the kernel text segment. In SPIM, these items may - only be instructions or words (see the .word directive below). If the optional - argument addr is present, subsequent items are stored starting at - address addr.
.set noat and .set at The first directive prevents SPIM from complaining about subsequent instructions - that use register $at. The second directive reenables the warning. Since - pseudoinstructions expand into code that uses register $at, programmers must be - very careful about leaving values in this register. -
.space n Allocate n bytes of space in the current segment - (which must be the data segment in SPIM).
.text <addr> Subsequent items are put in the user text segment. In SPIM, these items may only - be instructions or words (see the .word directive below). If the optional - argument addr is present, subsequent items are stored starting at - address addr.
.word w1,..., wn Store the n 32-bit quantities in successive memory words. -
-

SPIM does not distinguish various parts of the data segment (.data, .rdata, and - .sdata).

-

Encoding MIPS Instructions

-

Figure 10.2 explains how a MIPS instruction is encoded in a binary number. - Each column contains instruction encodings for a field (a contiguous group of - bits) from an instruction. The numbers at the left margin are values for a field. - For example, the j opcode has a value of 2 in the opcode field. The text at - the top of a column names a field and specifies which bits it occupies in an - instruction. For example, the op field is contained in bits 26–31 of an instruction. - This field encodes most instructions. However, some groups of instructions use - additional fields to distinguish related instructions. For example, the different - floating-point instructions are specified by bits 0–5. The arrows from the first - column show which opcodes use these additional fields.

-

Instruction Format

-

The rest of this appendix describes both the instructions implemented by - actual MIPS hardware and the pseudoinstructions provided by the MIPS assembler. - The two types of instructions are easily distinguished. Actual instructions - depict the fields in their binary representation. For example, in

-

Addition (with overflow)

- - - - - - - - - - - - - - - - - - - - - - - -
add rd, rs, rt
0 rs rt rd 0 0x20 value
6 5 5 5 5 6 width (bits)
-

The add instruction consists of six fields. Each field’s size in bits is - the small number below the field. This instruction begins with 6 bits of 0s. - Register specifiers begin with an r, so the next field is a 5-bit register - specifier called rs. This is the same register that is the second argument in - the symbolic assembly at the left of this line. Another common field is imm - 16 , which is a 16-bit immediate number.

-

Figure 10.2 MIPS opcode - map. The values of each field are shown to its left. The first column shows - the values in base 10 and the second shows base 16 for the op field (bits 31 - to 26) in the third column. This op field completely specifies the MIPS operation - except for 6 op values: 0, 1, 16, 17, 18, and 19. These operations are determined - by other fields, identified by pointers. The last field (funct) uses “ - f ” to mean “s” if rs = 16 and op = 17 or “d” if rs = 17 and op = - 17. The second field (rs) uses “ z ” to mean “0”, “1”, “2”, or - “3” if op = 16, 17, 18, or 19, respectively. If rs = 16, the operation is specified - elsewhere: if z = 0, the operations are specified in the fourth - field (bits 4 to 0); if z = 1, then the operations are in the last - field with f = s. If rs = 17 and z = 1, then the operations - are in the last field with f = d.

-

Pseudoinstructions follow roughly the same conventions, but omit instruction - encoding information. For example:

-

Multiply (without overflow)

- - - - -
mul rdest, rsrc1, src2 pseudoinstruction
-

In pseudoinstructions, rdest and rsrc1 are registers and src2 is either a - register or an immediate value. In general, the assembler and SPIM translate - a more general form of an instruction (e.g., add $v1, $a0, 0x55) to a specialized - form (e.g., addi $v1, $a0, 0x55).

-

Arithmetic and Logical Instructions

-

Absolute value

- - - - -
abs rdest, rsrc pseudoinstruction
-

Put the absolute value of register rsrc in register rdest.

-

Addition (with overflow)

- - - - - - - - - - - - - - - - - - - - - - -
add rd, rs, rt
0 rs rt rd 0 0x20 value
6 5 5 5 5 6 width (bits)
-

Addition (without overflow)

- - - - - - - - - - - - - - - - - - - - - - -
addu rd, rs, rt
0 rs rt rd 0 0x21 value
6 5 5 5 5 6 width (bits)
-

Put the sum of registers rs and rt into register rd.

-

Addition immediate (with overflow)

- - - - - - - - - - - - - - - - - - -
addi rt, rs, imm
8 rs rt imm value
6 5 5 16 width (bits)
-

Addition immediate (without overflow)

- - - - - - - - - - - - - - - - - - -
addiu rt, rs, imm
9 rs rt imm value
6 5 5 16 width (bits)
-

Put the sum of register rs and the sign-extended immediate into register rt.

-

AND

- - - - - - - - - - - - - - - - - - - - - - -
and rd, rs, rt
0 rs rt rd 0 0x24 value
6 5 5 5 5 6 width (bits)
-

Put the logical AND of registers rs and rt into register rd.

-

AND immediate

- - - - - - - - - - - - - - - - - - -
andi rt, rs, imm
0xc rs rt imm value
6 5 5 16 width (bits)
-

Put the logical AND of register rs and the zero-extended immediate into register rt.

-

Count leading ones

- - - - - - - - - - - - - - - - - - - - - - -
clo rd, rs
0x1c rs 0 rd 0 0x21 value
6 5 5 5 5 6 width (bits)
-

Count leading zeros

- - - - - - - - - - - - - - - - - - - - - - -
clz rd, rs
0x1c rs 0 rd 0 0x20 value
6 5 5 5 5 6 width (bits)
-

Count the number of leading ones (zeros) in the word in register rs and put - the result into register rd. If a word is all ones (zeros), the result is 32. -

-

Divide (with overflow)

- - - - - - - - - - - - - - - - - - - - - - -
div rs, rt
0 rs rt 0 0 0x1a value
6 5 5 5 5 6 width (bits)
-

Divide (without overflow)

- - - - - - - - - - - - - - - - - - - - - - -
divu rs, rt
0 rs rt 0 0 0x1b value
6 5 5 5 5 6 width (bits)
-

Divide register rs by register rt. Leave the quotient in register lo and - the remainder in register hi. Note that if an operand is negative, the remainder - is unspecified by the MIPS architecture and depends on the convention of the - machine on which SPIM is run.

-

Divide (with overflow)

- - - - -
div rdest, rsrc1, src2 pseudoinstruction
-

Divide (without overflow)

- - - - -
divu rdest, rsrc1, src2 pseudoinstruction
-

Put the quotient of register rsrc1 and src2 into register rdest.

-

Multiply

- - - - - - - - - - - - - - - - - - - - - - -
mult rs, rt
0 rs rt 0 0 0x18 value
6 5 5 5 5 6 width (bits)
-

Unsigned multiply

- - - - - - - - - - - - - - - - - - - - - - -
multu rs, rt
0 rs rt 0 0 0x19 value
6 5 5 5 5 6 width (bits)
-

Multiply registers rs and rt. Leave the low-order word of the product in - register lo and the high-order word in register hi.

-

Multiply (without overflow)

- - - - - - - - - - - - - - - - - - - - - - -
mul rd, rs, rt
0x1c rs rt 4d 0 2 value
6 5 5 5 5 6 width (bits)
-

Put the low-order 32 bits of the product of rs and rt into register rd. -

-

Multiply (with overflow)

- - - - -
mulo rdest, rsrc1, src2 pseudoinstruction
-

Unsigned multiply (with overflow)

- - - - -
mulou rdest, rsrc1, src2 pseudoinstruction
-

Put the low-order 32 bits of the product of register rsrc1 and src2 into register rdest.

-

Multiply add

- - - - - - - - - - - - - - - - - - - - - - -
madd rs, rt
0x1c rs rt 0 0 0 value
6 5 5 5 5 6 width (bits)
-

Unsigned multiply add

- - - - - - - - - - - - - - - - - - - - - - -
maddu rs, rt
0x1c rs rt 0 0 1 value
6 5 5 5 5 6 width (bits)
-

Multiply registers rs and rt and add the resulting 64-bit product to the - 64-bit value in the concatenated registers lo and hi.

-

Multiply subtract

- - - - - - - - - - - - - - - - - - - - - - -
msub rs, rt
0x1c rs rt 0 0 4 value
6 5 5 5 5 6 width (bits)
-

Unsigned multiply subtract

- - - - - - - - - - - - - - - - - - - - - - -
msubu rs, rt
0x1c rs rt 0 0 5 value
6 5 5 5 5 6 width (bits)
-

Multiply registers rs and rt and subtract the resulting 64-bit product from - the 64-bit value in the concatenated registers lo and hi.

-

Negate value (with overflow)

- - - - -
neg rdest, rsrc pseudoinstruction
-

Negate value (without overflow)

- - - - -
negu rdest, rsrc pseudoinstruction
-

Put the negative of register rsrc into register rdest.

-

NOR

- - - - - - - - - - - - - - - - - - - - - - -
nor rd, rs, rt
0 rs rt rd 0 0x27 value
6 5 5 5 5 6 width (bits)
-

Put the logical NOR of registers rs and rt into register rd.

-

NOT

- - - - -
not rdest, rsrc pseudoinstruction
-

Put the bitwise logical negation of register rsrc into register rdest.

-

OR

- - - - - - - - - - - - - - - - - - - - - - -
or rd, rs, rt
0 rs rt rd 0 0x25 value
6 5 5 5 5 6 width (bits)
-

Put the logical OR of registers rs and rt into register rd.

-

OR immediate

- - - - - - - - - - - - - - - - - - -
ori rt, rs, imm
0xd rs rt imm value
6 5 5 16 width (bits)
-

Put the logical OR of register rsand the zero-extended immediate into register rt.

-

Remainder

- - - - -
rem rdest, rsrc1, rsrc2 pseudoinstruction
-

Unsigned remainder

- - - - -
remu rdest, rsrc1, rsrc2 pseudoinstruction
-

Put the remainder of register rsrc1 divided by register rsrc2 into register - rdest. Note that if an operand is negative, the remainder is unspecified by - the MIPS architecture and depends on the convention of the machine on which - SPIM is run.

-

Shift left logical

- - - - - - - - - - - - - - - - - - - - - - -
sll rd, rt, shamt
0 0 rt rd shamt 0 value
6 5 5 5 5 6 width (bits)
-

Shift left logical variable

- - - - - - - - - - - - - - - - - - - - - - -
sllv rd, rt, rs
0 rs rt rd 0 4 value
6 5 5 5 5 6 width (bits)
-

Shift right arithmetic

- - - - - - - - - - - - - - - - - - - - - - -
sra rd, rt, shamt
0 0 rt rd shamt 3 value
6 5 5 5 5 6 width (bits)
-

Shift right arithmetic variable

- - - - - - - - - - - - - - - - - - - - - - -
srav rd, rt, rs
0 rs rt rd 0 7 value
6 5 5 5 5 6 width (bits)
-

Shift right logical

- - - - - - - - - - - - - - - - - - - - - - -
srl rd, rt, shamt
0 0 rt rd shamt 2 value
6 5 5 5 5 6 width (bits)
-

Shift right logical variable

- - - - - - - - - - - - - - - - - - - - - - -
srlv rd, rt, rs
0 rs rt rd 0 6 value
6 5 5 5 5 6 width (bits)
-

Shift register rt left (right) by the distance indicated by immediate shamt - or the register rs and put the result in register rd. Note that argument rs - is ignored for sll, sra, and srl.

-

Rotate left

- - - - -
rol rdest, rsrc1, rsrc2 pseudoinstruction
-

Rotate right

- - - - -
ror rdest, rsrc1, rsrc2 pseudoinstruction
-

Rotate register rsrc1 left (right) by the distance indicated by rsrc2 and put the result in register rdest.

-

Subtract (with overflow)

- - - - - - - - - - - - - - - - - - - - - - -
sub rd, rs, rt
0 rs rt rd 0 0x22 value
6 5 5 5 5 6 width (bits)
-

Subtract (without overflow)

- - - - - - - - - - - - - - - - - - - - - - -
sub rd, rs, rt
0 rs rt rd 0 0x23 value
6 5 5 5 5 6 width (bits)
-

Put the difference of registers rs and rt into register rd.

-

Exclusive OR

- - - - - - - - - - - - - - - - - - - - - - -
xor rd, rs, rt
0 rs rt rd 0 0x26 value
6 5 5 5 5 6 width (bits)
-

Put the logical XOR of registers rs and rt into register rd.

-

Exclusive OR immediate

- - - - - - - - - - - - - - - - - - -
xori rt, rs, imm
0xe rs rt imm value
6 5 5 16 width (bits)
-

Put the logical XOR of register rs and the zero-extended immediate into register - rt.

-

Constant-Manipulating Instructions

-

Load upper immediate

- - - - - - - - - - - - - - - - - - -
lui rt, imm
0xf 0rt imm value
6 5 5 16 width (bits)
-

Load the lower halfword of the immediate imm into the upper halfword of register - rt. The lower bits of the register are set to 0.

-

Load immediate

- - - - -
li rdest, imm pseudoinstruction
-

Move the immediate imm into register rdest.

-

Comparison Instructions

-

Set less than

- - - - - - - - - - - - - - - - - - - - - - -
slt rd, rs, rt
0 rs rt rd 0 0x2a value
6 5 5 5 5 6 width (bits)
-

Set less than unsigned

- - - - - - - - - - - - - - - - - - - - - - -
sltu rd, rs, rt
0 rs rt rd 0 0x2b value
6 5 5 5 5 6 width (bits)
-

Set register rd to 1 if register rs is less than rt, and to 0 otherwise.

-

Set less than immediate

- - - - - - - - - - - - - - - - - - -
slti rt, rs, imm
0xa rs rt imm value
6 5 5 16 width (bits)
-

Set less than unsigned immediate

- - - - - - - - - - - - - - - - - - -
sltiu rt, rs, imm
0xb rs rt imm value
6 5 5 16 width (bits)
-

Set register rt to 1 if register rs is less than the sign-extended immediate, - and to 0 otherwise.

-

Set equal

- - - - -
seq rdest, rsrc1, rsrc2 pseudoinstruction
-

Set register rdest to 1 if register rsrc1 equals rsrc2, and to 0 otherwise.

-

Set greater than equal

- - - - -
sge rdest, rsrc1, rsrc2 pseudoinstruction
-

Set greater than equal unsigned

- - - - -
sgeu rdest, rsrc1, rsrc2 pseudoinstruction
-

Set register rdest to 1 if register rsrc1 is greater than or equal to rsrc2, - and to 0 otherwise.

-

Set greater than

- - - - -
sgt rdest, rsrc1, rsrc2 pseudoinstruction
-

Set greater than unsigned

- - - - -
sgtu rdest, rsrc1, rsrc2 pseudoinstruction
-

Set register rdest to 1 if register rsrc1 is greater than rsrc2, and to 0 otherwise.

-

Set less than equal

- - - - -
sle rdest, rsrc1, rsrc2 pseudoinstruction
-

Set less than equal unsigned

- - - - -
sleu rdest, rsrc1, rsrc2 pseudoinstruction
-

Set register rdest to 1 if register rsrc1 is less than or equal to rsrc2, and to 0 otherwise.

-

Set not equal

- - - - -
sne rdest, rsrc1, rsrc2 pseudoinstruction
-

Set register rdestto 1 if register rsrc1is not equal to rsrc2, and to 0 otherwise.

-

Branch Instructions

-

Branch instructions use a signed 16-bit instruction offset field; hence - they can jump 2 15 - instructions (not bytes) forward or - 215 instructions backwards. The jump instruction contains a 26-bit address - field. In actual MIPS processors, branch instructions are delayed branches, - which do not transfer control until the instruction following the branch (its - "delay slot") has executed (see Chapter 6). Delayed branches affect the offset - calculation, since it must be computed relative to the address of the delay - slot instruction (PC + 4), which is when the branch occurs. SPIM does not simulate - this delay slot, unless the -bare or -delayed_branch flags are specified. -

-

In assembly code, offsets are pnot usually specified as numbers. Instead, - an instructions branch to a label, and the assembler computes the distance between - the branch and the target class="instformat" instructions.

-

In MIPS32, all actual (not pseudo) conditional branch instructions have a - "likely" variant (for example, beq’s likely variant is beql), which does - not execute the instruction in the branch’s delay slot if the branch is not - taken. Do not use these instructions; they may be removed in subsequent versions - of the architecture. SPIM implements these instructions, but they are not described - further.

-

Branch instruction

- - - - -
b label pseudoinstruction
-

Unconditionally branch to the instruction at the label.

-

Branch coprocessor false

- - - - - - - - - - - - - - - - - - - - -
bc1f cc, label
0x11 8 cc 0 offset value
6 5 3 2 16 width (bits)
-

Branch coprocessor true

- - - - - - - - - - - - - - - - - - - - -
bc1t cc, label
0x11 8 cc 1 offset value
6 5 3 2 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - the floating point coprocessor’s condition flag numbered cc is false (true). - If cc is omitted from the instruction, condition code flag 0 is assumed.

-

Branch on equal

- - - - - - - - - - - - - - - - - - -
beq rs, rt, label
4 rs rt offset value
6 5 5 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - register rs equals rt.

-

Branch on greater than equal zero

- - - - - - - - - - - - - - - - - - -
bgez rs, label
1 rs 1 offset value
6 5 5 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - register rs is greater than or equal to 0.

-

Branch on greater than equal zero and link

- - - - - - - - - - - - - - - - - - -
bgez rs, label
1 rs 11 offset value
6 5 5 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - register rs is greater than or equal to 0. Save the address of the next instruction - in register 31.

-

Branch on greater than zero

- - - - - - - - - - - - - - - - - - -
bgtz rs, label
7 rs 0 offset value
6 5 5 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - register rs is greater than 0.

-

Branch on less than equal zero

- - - - - - - - - - - - - - - - - - -
blez rs, label
6 rs 0 offset value
6 5 5 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - register rs is less than or equal to 0.

-

Branch on less than and link

- - - - - - - - - - - - - - - - - - -
bltzal rs, label
1 rs 0x10 offset value
6 5 5 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - register rs is less than 0. Save the address of the next instruction in register - 31.

-

Branch on less than zero

- - - - - - - - - - - - - - - - - - -
bltz rs, label
1 rs 0 offset value
6 5 5 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - register rs is less than 0.

-

Branch on not equal

- - - - - - - - - - - - - - - - - - -
bne rs, rt, label
5 rs rt offset value
6 5 5 16 width (bits)
-

Conditionally branch the number of instructions specified by the offset if - register rs is not equal to rt.

-

Branch on equal zero

- - - - -
beqz rsrc, label pseudoinstruction
-

Conditionally branch to the instruction at the label if rsrc equals 0.

-

Branch on greater than equal

- - - - -
bge rsrc1, rsrc2, label pseudoinstruction
-

Branch on greater than equal unsigned

- - - - -
bgeu rsrc1, rsrc2, label pseudoinstruction
-

Conditionally branch to the instruction at the label if register rsrc1 is - greater than or equal to rsrc2.

-

Branch on greater than

- - - - -
bgt rsrc1, src2, label pseudoinstruction
-

Branch on greater than unsigned

- - - - -
bgtu rsrc1, src2, label pseudoinstruction
-

Conditionally branch to the instruction at the label if register rsrc1 is - greater than src2.

-

Branch on less than equal

- - - - -
ble rsrc1, src2, label pseudoinstruction
-

Branch on less than equal unsigned

- - - - -
bleu rsrc1, src2, label pseudoinstruction
-

Conditionally branch to the instruction at the label if register rsrc1is - less than or equal to src2.

-

Branch on less than

- - - - -
blt rsrc1, rsrc2, label pseudoinstruction
-

Branch on less than unsigned

- - - - -
bltu rsrc1, rsrc2, label pseudoinstruction
-

Conditionally branch to the instruction at the label if register rsrc1is - less than rsrc2.

-

Branch on not equal zero

- - - - -
bnez rsrc, label pseudoinstruction
-

Conditionally branch to the instruction at the label if register rsrcis not - equal to 0.

-

Jump Instructions

-

Jump

- - - - - - - - - - - - - - -
j target
2 target value
6 26 width (bits)
-

Unconditionally jump to the instruction at target.

-

Jump and link

- - - - - - - - - - - - - - -
jal target
3 target value
6 26 width (bits)
-

Unconditionally jump to the instruction at target. Save the address of the - next instruction in register $ra.

-

Jump and link register

- - - - - - - - - - - - - - - - - - - - - - -
jalr rs, rd
0 rs 0 rd 0 9 value
6 5 5 5 5 6 width (bits)
-

Unconditionally jump to the instruction whose address is in register rs. - Save the address of the next instruction in register rd (which defaults to 31).

-

Jump register

- - - - - - - - - - - - - - - - - - - - - - -
jr rs
0 rs 0 0 0 8 value
6 5 5 5 5 6 width (bits)
-

Unconditionally jump to the instruction whose address is in register rs.

-

Trap Instructions

-

Trap if equal

- - - - - - - - - - - - - - - - - - - - -
teq rs, rt
0 rs rt 0 0x34 value
6 5 5 10 6 width (bits)
-

If register rs is equal to register rt, raise a Trap exception.

-

Trap if equal immediate

- - - - - - - - - - - - - - - - - - -
teqi rs, imm
1 rs 0xc imm value
6 5 5 16 width (bits)
-

If register rs is equal to the sign extended value imm, raise a Trap exception.

-

Trap if not equal

- - - - - - - - - - - - - - - - - - - - -
tne rs, rt
0 rs rt 0 0x36 value
6 5 5 10 6 width (bits)
-

If register rs is not equal to register rt, raise a Trap exception.

-

Trap if not equal immediate

- - - - - - - - - - - - - - - - - - -
tneqi rs, imm
1 rs 0xe imm value
6 5 5 16 width (bits)
-

If register rs is not equal to the sign extended value imm, - raise a Trap exception.

-

Trap if greater equal

- - - - - - - - - - - - - - - - - - - - -
tge rs, rt
0 rs rt 0 0x30 value
6 5 5 10 6 width (bits)
-

Unsigned trap if greater equal

- - - - - - - - - - - - - - - - - - - - -
tgeu rs, rt
0 rs rt 0 0x31 value
6 5 5 10 6 width (bits)
-

If register rs is greater than or equal to register rt, raise a Trap exception.

-

Trap if greater equal immediate

- - - - - - - - - - - - - - - - - - -
tgei rs, imm
1 rs 8 imm value
6 5 5 16 width (bits)
-

Unsigned trap if greater equal immediate

- - - - - - - - - - - - - - - - - - -
tgeiu rs, imm
1 rs 9 imm value
6 5 5 16 width (bits)
-

If register rs is greater than or equal to the sign extended value imm, raise - a Trap exception.

-

Trap if less than

- - - - - - - - - - - - - - - - - - - - -
tlt rs, rt
0 rs rt 0 0x32 value
6 5 5 10 6 width (bits)
-

Unsigned trap if less than

- - - - - - - - - - - - - - - - - - - - -
tltu rs, rt
0 rs rt 0 0x33 value
6 5 5 10 6 width (bits)
-

If register rs is less than register rt, raise a Trap exception.

-

Trap if less than immediate

- - - - - - - - - - - - - - - - - - -
tlti rs, imm
1 rs 0xa imm value
6 5 5 16 width (bits)
-

Unsigned trap if less than immediate

- - - - - - - - - - - - - - - - - - -
tltiu rs, imm
1 rs 0xb imm value
6 5 5 16 width (bits)
-

If register rs is less than the sign extended value imm, raise a Trap exception.

-

Load Instructions

-

Load address

- - - - -
la rdest, address pseudoinstruction
-

Load computed address —not the contents of the location—into register - rdest.

-

Load byte

- - - - - - - - - - - - - - - - - - -
lb rt, address
0x20 rs rt offset value
6 5 5 16 width (bits)
-

Load unsigned byte

- - - - - - - - - - - - - - - - - - -
lbu rt, address
0x24 rs rt offset value
6 5 5 16 width (bits)
-

Load the byte at address into register rt. The byte is sign-extended - by lb, but not by lbu.

-

Load halfword

- - - - - - - - - - - - - - - - - - -
lh rt, address
0x21 rs rt offset value
6 5 5 16 width (bits)
-

Load unsigned halfword

- - - - - - - - - - - - - - - - - - -
lhu rt, address
0x25 rs rt offset value
6 5 5 16 width (bits)
-

Load the 16-bit quantity (halfword) at address into register rt. The - halfword is sign-extended by lh, but not by lhu.

-

Load word

- - - - - - - - - - - - - - - - - - -
lw rt, address
0x23 rs rt offset value
6 5 5 16 width (bits)
-

Load the 32-bit quantity (word) at address into register rt.

-

Load word coprocessor 1

- - - - - - - - - - - - - - - - - - -
lwc1 ft, address
0x31 rs ft offset value
6 5 5 16 width (bits)
-

Load the word at address into register ft in the floating-point unit.

-

Load word left

- - - - - - - - - - - - - - - - - - -
lwl rt, address
0x22 rs rt offset value
6 5 5 16 width (bits)
-

Load word right

- - - - - - - - - - - - - - - - - - -
lwr rt, address
0x26 rs rt offset value
6 5 5 16 width (bits)
-

Load the left (right) bytes from the word at the possibly unaligned address - into register rt.

-

Load doubleword

- - - - -
ld rdest, address pseudoinstruction
-

Load the 64-bit quantity at address into registers rdest and rdest + 1.

-

Unaligned load halfword

- - - - -
ulh rdest, address pseudoinstruction
-

Unaligned load halfword unsigned

- - - - -
ulhu rdest, address pseudoinstruction
-

Load the 16-bit quantity (halfword) at the possibly unaligned address - into register rdest. The halfword is sign-extended by ulh, but not ulhu.

-

Unaligned load word

- - - - -
ulw rdest, address pseudoinstruction
-

Load the 32-bit quantity (word) at the possibly unaligned address - into register rdest.

-

Load linked

- - - - - - - - - - - - - - - - - - -
ll rt, address
0x30 rs rt offset value
6 5 5 16 width (bits)
-

Load the 32-bit quantity (word) at address into register rt and start - an atomic read-modify-write operation. This operation is completed by a store - conditional (sc) instruction, which will fail if another processor writes into - the block containing the loaded word. Since SPIM does not simulate multiple - processors, the store conditional operation always succeeds.

-

Store Instructions

-

Store byte

- - - - - - - - - - - - - - - - - - -
sb rt, address
0x28 rs rt offset value
6 5 5 16 width (bits)
-

Store the low byte from register rt at address.

-

Store halfword

- - - - - - - - - - - - - - - - - - -
sh rt, address
0x29 rs rt offset value
6 5 5 16 width (bits)
-

Store the low halfword from register rt at address.

-

Store word

- - - - - - - - - - - - - - - - - - -
sw rt, address
0x2b rs rt offset value
6 5 5 16 width (bits)
-

Store the word from register rt at address.

-

Store word coprocessor 1

- - - - - - - - - - - - - - - - - - -
swc1 ft, address
0x31 rs ft offset value
6 5 5 16 width (bits)
-

Store the floating-point value in register ft of floating-point coprocessor - at address.

-

Store double coprocessor 1

- - - - - - - - - - - - - - - - - - -
sdc1 ft, address
0x3d rs ft offset value
6 5 5 16 width (bits)
-

Store the double word floating-point value in registers ft and ft + 1 of - float-ing-point coprocessor at address. Register ft must be even numbered.

-

Store word left

- - - - - - - - - - - - - - - - - - -
swl rt, address
0x2a rs rt offset value
6 5 5 16 width (bits)
-

Store word right

- - - - - - - - - - - - - - - - - - - -
swr rt, address
0x2e rs rt offset value
6 5 5 16 width (bits)
-

Store the left (right) bytes from register rt at the possibly unaligned - address.

-

Store doubleword

- - - - -
sd rsrc, address pseudoinstruction
-

Store the 64-bit quantity in registers rsrc and rsrc + 1 at address .

-

Unaligned store halfword

- - - - -
ush rsrc, address pseudoinstruction
-

Store the low halfword from register rsrc at the possibly unaligned address .

-

Unaligned store word

- - - - -
usw rsrc, address pseudoinstruction
-

Store the word from register rsrc at the possibly unaligned address .

-

Store conditional

- - - - - - - - - - - - - - - - - - -
sc rt, address
0x38 rs rt offset value
6 5 5 16 width (bits)
-

Store the 32-bit quantity (word) in register rt into memory at address - and complete an atomic read-modify-write operation. If this atomic operation - is successful, the memory word is modified and register rt is set to 1. If the - atomic operation fails because another processor wrote to a location in the - block containing the addressed word, this instruction does not modify memory - and writes 0 into register rt. Since SPIM does not simulate multiple processors, - the instruction always succeeds.

-

Data Movement Instructions

-

Move

- - - - -
move rdest, rsrc pseudoinstruction
-

Move register rsrc to rdest.

-

Move from hi

- - - - - - - - - - - - - - - - - - - - - - -
mfhi rd
0 0 0 rd 0 0x10 value
6 5 5 5 5 6 width (bits)
-

Move from lo

- - - - - - - - - - - - - - - - - - - - - - -
mfl rd
0 0 0 rd 0 0x12 value
6 5 5 5 5 6 width (bits)
-

The pmultiply and divide unit produces its result in two additional registers, - hi and lo. These instructions move values to and from these registers. The multiply, - divide, and remainder pse class="instformat"udoinstructions that make this unit appear to operate - on the general registers move the result after the computation finishes.

-

Move the hi (lo) regist class="instformat"er to register rd.

-

Move to hi

- - - - - - - - - - - - - - - - - - - - - - -
mthi rs
0 rs 0 0 0 0x11 value
6 5 5 5 5 6 width (bits)
-

Move to lo

- - - - - - - - - - - - - - - - - - - - - - -
mli rs
0 rs 0 0 0 0x13 value
6 5 5 5 5 6 width (bits)
-

Move register rs to the hi (lo) register.

-

Move from coprocessor 0

- - - - - - - - - - - - - - - - - - - - - - -
mfc0 rt, rd
0x10 0 rt rd 0 0 value
6 5 5 5 5 6 width (bits)
-

Move from coprocessor 1

- - - - - - - - - - - - - - - - - - - - - - -
mfc1 rt, rd
0x11 0 rt rd 0 0 value
6 5 5 5 5 6 width (bits)
-

Coprocessors have their own register sets. These instructions move values - between these registers and the CPU’s registers.

-

Move register rd in a coprocessor (register pfs in the FPU) to CPU register - rt. The floating-point unit is coprocessor 1.

-

Move double from coprocessor 1

- - - - -
mfc1.d rdest, frsrc1 pseudoinstruction
-

Move floating-point registers frsrc1and frsrc1 + 1to CPU registers rdest - and rdest + 1.

-

Move to coprocessor 0

- - - - - - - - - - - - - - - - - - - - - - -
mtc0 rd, rt
0x10 4 rt rd 0 0 value
6 5 5 5 5 6 width (bits)
-

Move to coprocessor 1

- - - - - - - - - - - - - - - - - - - - - - -
mtc1 rt, rd
0x11 4 rt rd 0 0 value
6 5 5 5 5 6 width (bits)
-

Move CPU register rt to register rd in a coprocessor (register fs in the - FPU).

-

Move conditional not zero

- - - - - - - - - - - - - - - - - - - - - - -
movn rd, rs, rt
0 rs rt rd 0 0xb value
6 5 5 5 5 6 width (bits)
-

Move register rs to register rd if register rt is not 0.

-

Move conditional zero

- - - - - - - - - - - - - - - - - - - - - - -
movz rd, rs, rt
0 rs rt rd 0 0xa value
6 5 5 5 5 6 width (bits)
-

Move register rs to register rd if register rt is 0.

-

Move conditional on FP false

- - - - - - - - - - - - - - - - - - - - - - - - -
movf rd, rs, cc
0 rs cc 0 rd 0 1 value
6 5 3 2 5 5 6 width (bits)
-

Move CPU register rs to register rd if FPU condition code flag number - cc is 0. If cc is omitted from the instruction, condition code flag - 0 is assumed.

-

Move conditional on FP true

- - - - - - - - - - - - - - - - - - - - - - - - -
movt rd, rs, cc
0 rs cc 1 rd 0 1 value
6 5 3 2 5 5 6 width (bits)
-

Move CPU register rs to register rd if FPU condition code flag number - cc is 1. If cc is omitted from the instruction, condition code bit - 0 is assumed.

-

Floating-Point Instructions

-

The MIPS has a floating-point coprocessor (numbered 1) that operates on single - precision (32-bit) and double precision (64-bit) floating-point numbers. This - coprocessor has its own registers, which are numbered $f0–$f31. Because these - registers are only 32 bits wide, two of them are required to hold doubles, so - only floating-point registers with even numbers can hold double precision values. - The floating-point coprocessor also has 8 condition code ( cc ) flags, - numbered 0–7, which are set by compare instructions and tested by branch (bc1f - or bc1t) and conditional move instructions.

-

Values are moved in or out of these registers one word (32 bits) at a time - by lwc1, swc1, mtc1, and class="instformat"mfc1 instructions or one double (64 bits) at a time - by ldc1 and sdc1 described above, or pby the l.s, l.d, s.s, and s.d pseudoinstructions - described below.

-

In the actual instruct class="instformat"ions below, bits 21–26 are 0 for single precision and - 1 for double precision. In the pseudoinstructions below, fdest is a floating-point - register (e.g., $f2).

-

Floating-point absolute value double

- - - - - - - - - - - - - - - - - - - - - - -
abs.d fd, fs
0x11 1 0 fs fd 4 value
6 5 5 5 5 6 width (bits)
-

Floating-point absolute value single

- - - - - - - - - - - - - - - - - - - - - - -
abs.s fd, fs
0x11 1 0 fs fd 5 value
6 5 5 5 5 6 width (bits)
-

Compute the absolute value of the floating-point double (single) in register - fs and put it in register fd.

-

Floating-point addition double

- - - - - - - - - - - - - - - - - - - - - - -
add.d fd, fs, ft
0x11 0x11 ft fs fd 0 value
6 5 5 5 5 6 width (bits)
-

Floating-point addition single

- - - - - - - - - - - - - - - - - - - - - - -
add.s fd, fs, ft
0x11 0x10 ft fs fd 0 value
6 5 5 5 5 6 width (bits)
-

Compute the sum of the floating-point doubles (singles) in registers fs and - ft and put it in register fd.

-

Floating-point ceiling to word double

- - - - - - - - - - - - - - - - - - - - - - -
ceil.w.d fd, fs
0x11 0x11 0 fs fd 0xe value
6 5 5 5 5 6 width (bits)
-

Floating-point ceiling to word single

- - - - - - - - - - - - - - - - - - - - - - -
ceil.w.s fd, fs
0x11 0x10 0 fs fd 0xe value
6 5 5 5 5 6 width (bits)
-

Compute the ceiling of the floating-point double (single) in register fs, - convert to a 32-bit fixed-point value, and put the resulting word in register - fd.

-

Compare equal double

- - - - - - - - - - - - - - - - - - - - - - - - - - -
c.e.d cc, fs, ft
0x11 0x11 ft fs cc 0 fc 2 value
6 5 5 5 3 2 2 4 width (bits)
-

Compare equal single

- - - - - - - - - - - - - - - - - - - - - - - - - - -
c.e.s cc, fs, ft
0x11 0x10 ft fs cc 0 fc 2 value
6 5 5 5 3 2 2 4 width (bits)
-

Compare the floating-point double (single) in register fs against the one - in ft and set the floating-point condition flag cc to 1 if they are equal. - If cc is omitted, condition code flag 0 is assumed.

-

Compare less than equal double

- - - - - - - - - - - - - - - - - - - - - - - - - - -
c.le.d cc, fs, ft
0x11 0x11 ft fs cc 0 fc 0xe value
6 5 5 5 3 2 2 4 width (bits)
-

Compare less than equal single

- - - - - - - - - - - - - - - - - - - - - - - - - - -
c.le.s cc, fs, ft
0x11 0x10 ft fs cc 0 fc 0xe value
6 5 5 5 3 2 2 4 width (bits)
-

Compare the floating-point double (single) in register fs against the one - in ft and set the floating-point condition flag cc to 1 if the first is - less than or equal to the second. If cc is omitted, condition code flag - 0 is assumed.

-

Compare less than double

- - - - - - - - - - - - - - - - - - - - - - - - - - -
c.lt.d cc, fs, ft
0x11 0x11 ft fs cc 0 fc 0xc value
6 5 5 5 3 2 2 4 width (bits)
-

Compare less than single

- - - - - - - - - - - - - - - - - - - - - - - - - - -
c.lt.s cc, fs, ft
0x11 0x10 ft fs cc 0 fc 0xc value
6 5 5 5 3 2 2 4 width (bits)
-

Compare the floating-point double (single) in register fs against the one - in ft and set the condition flag cc to 1 if the first is less than the - second. If cc is omitted, condition code flag 0 is assumed.

-

Convert single to double

- - - - - - - - - - - - - - - - - - - - - - -
cvt.d.s fd, fs
0x11 0x10 0 fs fd 0x21 value
6 5 5 5 5 6 width (bits)
-

Convert integer to double

- - - - - - - - - - - - - - - - - - - - - - -
cvt.d.w fd, fs
0x11 0x14 0 fs fd 0x21 value
6 5 5 5 5 6 width (bits)
-

Convert the single precision floating-point number or integer in register - fs to a double (single) precision number and put it in register fd.

-

Convert double to single

- - - - - - - - - - - - - - - - - - - - - - -
cvt.s.d fd, fs
0x11 0x11 0 fs fd 0x20 value
6 5 5 5 5 6 width (bits)
-

Convert integer to single

- - - - - - - - - - - - - - - - - - - - - - -
cvt.s.w fd, fs
0x11 0x14 0 fs fd 0x20 value
6 5 5 5 5 6 width (bits)
-

Convert the double precision floating-point number or integer in register - fsto a single precision number and put it in register fd.

-

Convert double to integer

- - - - - - - - - - - - - - - - - - - - - - -
cvt.w.d fd, fs
0x11 0x11 0 fs fd 0x24 value
6 5 5 5 5 6 width (bits)
-

Convert single to integer

- - - - - - - - - - - - - - - - - - - - - - -
cvt.w.s fd, fs
0x11 0x10 0 fs fd 0x24 value
6 5 5 5 5 6 width (bits)
-

Convert the double or single precision floating-point number in register - fs to an integer and put it in register fd.

-

Floating-point divide double

- - - - - - - - - - - - - - - - - - - - - - -
div.d fd, fs, ft
0x11 0x101ft fs fd 3 value
6 5 5 5 5 6 width (bits)
-

Floating-point divide single

- - - - - - - - - - - - - - - - - - - - - - -
div.s fd, fs, ft
0x11 0x10 ft fs fd 3 value
6 5 5 5 5 6 width (bits)
-

Compute the quotient of the floating-point doubles (singles) in registers - fs and ft and put it in register fd.

-

Floating-point floor to word double

- - - - - - - - - - - - - - - - - - - - - - -
floor.w.d fd, fs
0x11 0x11 0 fs fd 0xf value
6 5 5 5 5 6 width (bits)
-

Floating-point floor to word single

- - - - - - - - - - - - - - - - - - - - - - -
floor.w.s fd, fs
0x11 0x10 0 fs fd 0xf value
6 5 5 5 5 6 width (bits)
-

Compute the floor of the floating-point double (single) in register fs and - put the resulting word in register fd.

-

Load floating-point double

- - - - -
l.d fdest, address pseudoinstruction
-

Load floating-point single

- - - - -
l.s fdest, address pseudoinstruction
-

Load the floating-point double (single) at address into register fdest.

-

Move floating-point double

- - - - - - - - - - - - - - - - - - - - - - -
mov.d fd, fs
0x11 0x11 0 fs fd 6 value
6 5 5 5 5 6 width (bits)
-

Move floating-point single

- - - - - - - - - - - - - - - - - - - - - - -
mov.s fd, fs
0x11 0x10 0 fs fd 6 value
6 5 5 5 5 6 width (bits)
-

Move the floating-point double (single) from register fs to register fd.

-

Move conditional floating-point double false

- - - - - - - - - - - - - - - - - - - - - - - - -
movf.d fd, fs, cc
0x11 0x11 cc 0 fs fd 0x11 value
6 5 3 2 5 5 6 width (bits)
-

Move conditional floating-point single false

- - - - - - - - - - - - - - - - - - - - - - - - -
movf.s fd, fs, cc
0x11 0x10 cc 0 fs fd 0x11 value
6 5 3 2 5 5 6 width (bits)
-

Move the floating-point double (single) from register fs to register fd if - condition code flag cc is 0. If cc is omitted, condition code flag - 0 is assumed.

-

Move conditional floating-point double true

- - - - - - - - - - - - - - - - - - - - - - - - -
movt.d fd, fs, cc
0x11 0x11 cc 1 fs fd 0x11 value
6 5 3 2 5 5 6 width (bits)
-

Move conditional floating-point single true

- - - - - - - - - - - - - - - - - - - - - - - - -
movt.s fd, fs, cc
0x11 0x10 cc 1 fs fd 0x11 value
6 5 3 2 5 5 6 width (bits)
-

Move the floating-point double (single) from register fs to register fd if - condition code flag cc is 1. If cc is omitted, condition code flag - 0 is assumed.

-

Move conditional floating-point double not zero

- - - - - - - - - - - - - - - - - - - - - - -
movn.d fd, fs, rt
0x11 0x11 rt fs fd 0x13 value
6 5 5 5 5 6 width (bits)
-

Move conditional floating-point single not zero

- - - - - - - - - - - - - - - - - - - - - - -
movn.s fd, fs, rt
0x11 0x10 rt fs fd 0x13 value
6 5 5 5 5 6 width (bits)
-

Move the floating-point double (single) from register fs to register fd if - processor register rt is not 0.

-

Move conditional floating-point double zero

- - - - - - - - - - - - - - - - - - - - - - -
movnzd fd, fs, rt
0x11 0x11 rt fs fd 0x12 value
6 5 5 5 5 6 width (bits)
-

Move conditional floating-point single zero

- - - - - - - - - - - - - - - - - - - - - - -
movz.s fd, fs, rt
0x11 0x10 rt fs fd 0x12 value
6 5 5 5 5 6 width (bits)
-

Move the floating-point double (single) from register fs to register fd if - processor register rt is 0.

-

Floating-point multiply double

- - - - - - - - - - - - - - - - - - - - - - -
mul.d fd, fs, ft
0x11 0x11 ft fs fd 2 value
6 5 5 5 5 6 width (bits)
-

Floating-point multiply single

- - - - - - - - - - - - - - - - - - - - - - -
mul.s fd, fs, ft
0x11 0x10 ft fs fd 2 value
6 5 5 5 5 6 width (bits)
-

Compute the product of the floating-point doubles (singles) in registers - fsand ft and put it in register fd.

-

Negate double

- - - - - - - - - - - - - - - - - - - - - - -
neg.d fd, fs
0x11 0x11 0 fs fd 7 value
6 5 5 5 5 6 width (bits)
-

Negate single

- - - - - - - - - - - - - - - - - - - - - - -
neg.s fd, fs
0x11 0x10 0 fs fd 7 value
6 5 5 5 5 6 width (bits)
-

Negate the floating-point double (single) in register fs and put it in register fd.

-

Floating-point round to word double

- - - - - - - - - - - - - - - - - - - - - - -
round.w.d fd, fs
0x11 0x11 0 fs fd 0xc value
6 5 5 5 5 6 width (bits)
-

Floating-point round to word single

- - - - - - - - - - - - - - - - - - - - - - -
round.w.s fd, fs
0x11 0x10 0 fs fd 0xc value
6 5 5 5 5 6 width (bits)
-

Round the floating-point double (single) value in register fs, convert to - a 32bit fixed-point value, and put the resulting word in register fd.

-

Square root double

- - - - - - - - - - - - - - - - - - - - - - -
sqrt.d fd, fs
0x11 0x11 0 fs fd 4 value
6 5 5 5 5 6 width (bits)
-

Square root single

-

Square root double

- - - - - - - - - - - - - - - - - - - - - - -
sqrt.s fd, fs
0x11 0x10 0 fs fd 4 value
6 5 5 5 5 6 width (bits)
-

Compute the square root of the the floating-point double (single) in register - fs and put it in register fd.

-

Store floating-point double

- - - - -
s.d fdest, address pseudoinstruction
-

Store floating-point single

- - - - -
s.s fdest, address pseudoinstruction
-

Store the floating-point double (single) in register fdest at address.

-

Floating-point subtract double

- - - - - - - - - - - - - - - - - - - - - - -
sub.d fd, fs, ft
0x11 0x10 ft fs fd 1 value
6 5 5 5 5 6 width (bits)
-

Floating-point subtract single

- - - - - - - - - - - - - - - - - - - - - - -
sub.s fd, fs, ft
0x11 0x10 ft fs fd 1 value
6 5 5 5 5 6 width (bits)
-

Compute the difference of the floating-point doubles (singles) in registers - fs and ft and put it in register fd.

-

Floating-point truncate to word double

- - - - - - - - - - - - - - - - - - - - - - -
trunc.w.d fd, fs
0x11 0x11 0 fs fd 0xd value
6 5 5 5 5 6 width (bits)
-

Floating-point truncate to word single

- - - - - - - - - - - - - - - - - - - - - - -
trunc.w.s fd, fs
0x11 0x10 0 fs fd 0xd value
6 5 5 5 5 6 width (bits)
-

Truncate the floating-point double (single) value in register fs, convert - to a 32bit fixed-point value, and put the resulting word in register fd.

-

Exception and Interrupt Instructions

-

Exception return

-

Floating-point truncate to word double

- - - - - - - - - - - - - - - - - - -
eret
0x10 1 0 0x18 value
6 1 19 6 width (bits)
-

Set the EXL bit in coprocessor 0’s Status register to 0 and return to the - instruction pointed to by coprocessor 0’s EPC register.

-

System call

- - - - - - - - - - - - - - - - -
syscall
0 0 0xc value
6 20 0xd width (bits)
-

Register $v0 contains the number of the system call (see Figure 9.1) provided by SPIM.

-

Break

- - - - - - - - - - - - - - - - -
break code
0 code 0xd value
6 20 0xd width (bits)
-

Cause exception code. Exception 1 is reserved for the debugger.

-

No operation

- - - - - - - - - - - - - - - - - - - - - - -
nop
0 0 0 0 0 0 value
6 5 5 5 5 6 width (bits)
-

Do nothing.

-

Concluding Remarks

-

Programming in assembly language requires a programmer to trade off helpful - features of high-level languages—such as data structures, type checking, and - control constructs—for complete control over the instructions that a computer - executes. External constraints on some applications, such as response time or - program size, require a programmer to pay close attention to every instruction. - However, the cost of this level of attention is assembly language programs that - are longer, more time-consuming to write, and more difficult to maintain than - high-level language programs.

-

Moreover, three trends are reducing the need to write programs in assembly - language. The first trend is toward the improvement of compilers. Modern compilers - produce code that is typically comparable to the best handwritten code— and - is sometimes better. The second trend is the introduction of new processors - that are not only faster, but in the case of processors that execute multiple - instructions simultaneously, also more difficult to program by hand. In addition, - the rapid evolution of the modern computer favors high-level language programs - that are not tied to a single architecture. Finally, we witness a trend toward - increasingly complex applications—characterized by complex graphic interfaces - and many more features than their predecessors. Large applications are written - by teams of programmers and require the modularity and semantic checking features - provided by high-level languages.

-

Further Reading

-

Aho, A., R. Sethi, and J. Ullman [1985].Compilers: Principles, Techniques, - and Tools, Reading, MA: Addison-Wesley.

-

Slightly dated and lacking in coverage of modern architectures, but still - the standard reference on compilers.

-

Sweetman, D. [1999].See MIPS Run, San Francisco CA: Morgan Kaufmann - Publishers.

-

A complete, detailed, and engaging introduction to the MIPS instruction - set and assembly language program ming on these machines.

-

MIPS, Inc. has excellent free documentation on the MIPS32 architecture on - their website - - http://www.mips.com/products/product-materials/processor/mips-architecture/: -

- -

Exercises

-
    -
  1. [5] <§A.5> Section A.5 described how memory is partitioned on - most MIPS systems. Propose another way of dividing memory that meets the - same goals.
  2. -
  3. [20] <§A.6> Rewrite the code for fact to use fewer instructions. -
  4. -
  5. [5] <§A.7> Is it ever safe for a user program to use registers - $k0 or $k1?
  6. -
  7. [25] <§A.7> Section A.7 contains code for a very simple exception - handler. One serious problem with this handler is that it disables interrupts - for a long time. This means that interrupts from a fast I/O device may be - lost. Write a better exception handler that is interruptable and enables - interrupts as quickly as possible.
  8. -
  9. [15] <§A.7> The simple exception handler always jumps back to - the instruction following the exception. This works fine unless the instruction - that causes the exception is in the delay slot of a branch. In that case, - the next instruction is the target of the branch. Write a better handler - that uses the EPC register to determine which instruction should be executed - after the exception.
  10. -
  11. [5] <§A.9> Using SPIM, write and test an adding machine program - that repeatedly reads in integers and adds them into a running sum. The - program should stop when it gets an input that is 0, printing out the sum - at that point. -
  12. -
  13. [5] <§A.9> Using SPIM , write and test a program that reads in - three integers and prints out the sum of the largest two of the three. You can - break ties arbitrarily.
  14. -
  15. [5] <§A.9> Using SPIM, write and test a program that reads in - a positive integer using the SPIM system calls. If the integer is not positive, - the program should terminate with the message “Invalid Entry”; otherwise - the program should print out the names of the digits of the integers, delimited - by exactly one space. For example, if the user entered “728,” the output - would be “Seven Two Eight.”
  16. -
  17. [25] <§A.9> Write and test a MIPS assembly language program to - compute and print the first 100 prime numbers. A number n is prime - if no numbers except 1 and n divide it evenly. You should implement - two routines: -
      -
    • test_prime (n) Return 1 if n is prime and 0 if n is - not prime.
    • -
    • main () Iterate over the integers, testing if each is prime. Print - the first 100 numbers that are prime.
    • -
    -
  18. -

    Test your programs by running them on SPIM.

    -
  19. A.10 [10] <§§A.6, A.9> Using SPIM, write and test a recursive program - for solving the classic mathematical recreation, the Towers of Hanoi puzzle. - (This will require the use of stack frames to support recursion.) The puzzle - consists of three pegs (1, 2, and 3) and n disks (the number n - can vary; typical values might be in the range from 1 to 8). Disk 1 is smaller - than disk 2, which is in turn smaller than disk 3, and so forth, with disk - n being the largest. Initially, all the disks are on peg 1, starting with - disk n on the bottom, disk n – 1 on top of that, and so forth, up to - disk 1 on the top. The goal is to move all the disks to peg 2. You may only move one - disk at a time, that is, the top disk from any of the three pegs onto the top of either - of the other two pegs. Moreover, there is a constraint: You must not place a larger disk - on top of a smaller disk.

    -

    The C program below can be used to help write your assembly language program. -

    -
    -        /* move n smallest disks from start to finish using extra */
    -        void hanoi(int n, int start, int finish, int extra) {
    -          if (n != 0) {
    -                hanoi(n-1, start, extra, finish);
    -                print_string(“Move disk”);
    -                print_int(n);
    -                print_string(“from peg”);
    -                print_int(start);
    -                print_string(“to peg”);
    -                print_int(finish);
    -                print_string(“.\n”);
    -                hanoi(n-1, extra, finish, start);
    -          }
    -        }
    -
    -        main () {
    -          int n;
    -          print_string(“Enter number of disks “);
    -          n = read_int();
    -          hanoi(n, 1, 2, 3);
    -          return 0;
    -        }
    -        
    -
  20. -
-
- - diff --git a/spim-qtbase/QtSpim/help/main_windows.jpg b/spim-qtbase/QtSpim/help/main_windows.jpg deleted file mode 100644 index 3c2b49be49862d1c57831c9d8f0bf7e53e1d9b44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 379586 zcmeFa2UJt-vNs+@1rbD$A|OO5qEtnS(xM_=K#-0Qkq!n#TBuQx4kBGai1bdRcOqRx zKzb8G?}3C80)*t--h0+P_kG{H&U?Q9`nUBhH-wce_ETn_nR#Y@Gy4f;lrjxEr>?A~ z3_5n~80ZP`1ENfT6hX(29sBkBkBjOg)vxQ+i4#;OsZUW;|9a7!K69FehL(n!nwFlH z_6!|xQJ+4`Ku>q}*ZW_c{A&KI74S<(LrwGRj{m)j@&&|5L-p(g6V)*u&~e6NRE)NqgjlP699cl!bV2c2L%$#nU~ z-BagvEU0;0n8ja3r_u1HR|KwJ6O@pYlD>6YM)AIq zvWlvj`XfDk14AQY6H6;=8(TYj2Uje(N6?92y=O9UGsSots}+Tv}dP#cyrz>=O2f`v<@1 zItHTpPqO}tvOm$q2+(yLSc4PPzvw!4+!J_FF`hVi`Nk=xyE@bsF6Vi~U(qn%i%u(P zI?a1i7svASMIS9IpTrD5{ugQgLD|1Y*z5mGl>HZB|D zFJ5nr0-Di-gUO+`O(>GI2^$5(W02D{aVnYMO?*h~@#i9%Qa}$p^uLh@AncnETMFnb z(PpE!rK8o*{0d$QIg^_vo!)bc59lm2 zHHqFXRS<}uaSm$nc^B9pR;wl&Dz=h@!R5;_P(b&~rboz}MQ13W=&KY^pw2YnfFF4Z zjhnQCl0wbn9dWyud-c^d4W*@x1J>6ck99XZR%JAGusZd`^CV}ymg~D}$xs)&N{=ng zn|wO=vnGFH^&X0=34Eezu;93*rjl|`3S(X6S1FPAh=scAn(RT@yT6R0LK2LkqJa8@ ziINmh(Aqr;XkNXOXmO|mKR?G7Vlg1WrAxNow1`>KPS{pz9KcGxx8(J$G-Ny1K|lY5 z1xDE9!CF7VK6yZvKFT1mOv?)>H6ZnBhcDx~>Za@qX0U?WtxQv>F(t87F)|Wd{gi=c|kY+$QVIpQF%oHEhqSLP(Us2X^1U;@LzZ( zR9sf2d9Pn6gq=UgjY)a+MRBIpIX{~GRBm)|D?#_MsgfUul8Z>$nL76MpXE+EA!<6t z@8bC%A1|)97S25HOdYJ%^U--3{WYq{&|%eSs&EPNXJOExfM_$mP(V8x3iODX+8^kB zraH0p%AJfuk%p@W*Csx1fNQe)`XYO;DuGO-uk9|83#_yb=Dk@c+$A`@OG&fA8zRy}94s+;1QLzarQFDW?1n zAHIyFX!)FX06YDDyfbgL)<4OXhU=4Q@>kf{p!CUjD?Tg6cj7d&ai6QLlHKO^E*C0a zE{_9(6wkjp_5VXqIEbG4_zbb^g5Nwk>PPP%k0RP~f)6hG`cOa!Hx&6!;qB+h?G?YT z6UmGe5ClBcEAnpzAG>0I>Zh1t&Og8fr}d*dXN{w{G?9a~C^vA(U@VEfuq{tBo5td# zDVF;3E6CL*cAk$GfiN+f#`$a7Oz}q}Wb>R(CY0dk48z7}O$}=LNjwLU85+!y%(-Pv8TDGa_uXKH z&%b`zqREYI%JS3{i;;+MdEpVMOn$cTZv{S4bR>~JIsH6yqmEf*IEUZS8y#)QY*d!1 zy`d0uw$j_XEW;l-%b)eBQ@zxC|I=3RPH+c?4uDlmJ7*5Vz zp4DlY3nH_Z1596aK2hX8#-1PXJfC75UwfSKcKZ@;?8%j}W!r5zh2~$8U z{j@lMgvr!$6M!P#a)FFeiiaQ0%pzUAG12hFTPrk_2JSw7}7wYHaAU&!9bo|+0- z{wvU>^PfHoRQn(Ca8$^DA`xuU+{uKfG2{&AoNOZ((Gmc_D&4#N2f$@_iMu&OQyFqW z8W3>vqDG;iM@ z<$X~ZZgaP3-paDbM}>4VDh$APSSX;_hZGRrJ&2Pj_eYMXJKMLyO{b96j}CrMU*xc^ zV~~&L&tO2l52}v}dqe9z3nm_qI-L7d(eFloDJxDaXu^fB$dz|~W{>sGX?NP^)x}+e z_e8Z^lF3m@z59$Gj}dkkdTv>|);%*umgltft3E}ROM!eZRd0im4y4KK9c_pmS_-H$ z7eTCr%zX4Uq=4?ANJ#*+5}ubTDtT2{$FQJbVt6r@&{JAO3p36c zTJ`sHRFED(J8FkQ&NhNqQaSKZK^17~gb|XCv!8`~n)XbW^1!Ar>jhDE%bOBq-|&0{ zCOMxc@xvBx#1MNA?bA{mAHlyik#^B8xfaS3ME`6?x zW3)@+IqX>rh^E`wg`3afz;QNe)QjXiYsO$QT+i@njiV#T+N<1WZS>iOs9WAe(55qQ zOyA9u57p0U^`*u)P(XBZv*?49i1|SX$;@iCKT#q@HBYUse0ROZ6jsEQ~RzAi-6W|#z<6B|F@UK!D48i7=$(kvyPruX}K7nE<(h}y{ z`_`(YW5!KZqoqE=ww(nwp4kZT_wT##nKsv0+vv8ef!7fZyHKJn7!ckcz_3>UZI}i0 zE64>8JvxrwasZP>Ya8qC3SBF1Ff_o-_=xeQW^)&&93?{qj$mmE&{6Ur!t&4%Kn+`N z5mDq<(0xe&3S|4UPPqAb1aG4n7uZS(H$ zM!y;H4~75Dh~JF(Z6p43Yxr#}|FK8@X2fqs{PrV$J5>MgdzMe(OPW4DFqXO5`*`j! zz1=4AU`3lx@Sg)hl~zb;PAEw!o747l>ST;jF;5a_oeLjR8&B88@C07LndA&-b0bb8_!2*b2=a7i%lJNhvPR74Rvt!OZtgDF%Vi}T)T(h^s@m! z5GoBZlc2y4#20PFh-s++pcbIQWRGwI4-HZJGGeMb@`iA8<(uf00qpPv+p#6VaJLX^ zQuWsN)BC4rmSkEOm2c=Qy-jf{wv~~5{IQ0+LAXbt%>)_F*2eKpJ{{vFREwy zOz;I=8dSFSdKvzDjCRN_K_Cw6mSp(cUEb%B|H!2an71jl(7s3I|Gug}$w zc=S=feqwJJ~Sd#6J6&JA>#<3_h6j8_h7<-uQ~k>rTV8m)HLWZk7{-+KJt|YZGs7L zufUfBZx|`3F?;k#Z)9O`Cm0-&DtwG?<;z$8rJ zOJo3=0CM%yIZYT+KI%KJ{$^OqY*uKXk?d4w_m~-30a+9^>1rb_KKhzbz~-(0QJ?EyL+fg09_hx zyiEZCp>R8zcn#-C0SV@t$&yc7&myoe1sJrIEQ&vwfb@gqQb4vp@6L2x6}?iKB6>+& zJ|*Hji`s11o%B0d8D>qv)JiQz9~RHG_Y^W|O2utf)RC1Xh}$A*vD!je>bg$i>RPAe zJ%;%AHW$sv9fb7SB9)eYdzm+c#4`&&O}_T2)=)cMYhu61t>PfGnU#_gtrdC?KnXX2`+Q5>yVN z)UmZdOFT^@xs(*WX^}bPP`PzFT#m{iI+AIfEk6+pX5IY7V{Kw*piK6) zXJ1N~F%b@RhfS80$_8n(K61Nlch!1LJi8I|uGKh*ajM>D2HlKcBd$$rw>k&Z<}_o% z8tF@k1unCB^LX>ma*`qm0Y@nQg)dBZZHstT?y`-byF|Hk#6=p}Wr+{8-jgp=O zm?o_~#!Y4TdCg*_+bUTbd2w;xi(xS)%b!;mU|v?+IpgUud@*+nR84Mkh+o)8KvJ~A z9%>|PCY&KpEk5owb2A(%u51kT-j3r^t6QE_Zjc}#{2Rl4WUF>DKuyuOp*k^bx?8rD zgD=t3#Jqqei8^Lj!~RYWtr~NhRhZHf{fub+zWDgK>zAG(nnx+1Y{151cu9`m{i%E} zLQatx?ffrDO)-|s+!tYso$;eOq*i@UCnd68zfvE#Ujvognt1E=Wer{Gm<{)q>y5W_ zX?MSED76$pdU90d>zL_3GA`DF6*9t!y)K_9QWz$;5)0I7YLYu*>Icpg(96uqR`XO< zR|PTKd^76|&vd2D^orS`fN*-7AYYl!VPIxrr6yE=&|TAGK)dRPFF0S#<%L9DFVE_U zijc?M5|tA_)OdVLPsCU$g__!i`%jWtiB))?_C5bI1C3z#h&j=euhwmEz&=Sj_)1+} z!s(1!v7D(Xcu>EF0bOo#_UGt+)ycVM%ofXNTF8?CT*vH2^el>~t}uBN?=^P@RZ0Qb z?3+6i$T=s;lVtmjF;bM6toDaG&kcO}R=)X~x~%IaMuoeHJb>>?S>03RvnUse0=?`p1f)6Rq|Xo`nk=4Gr##{p0b_)YLguxw~>QT?N+p#hQ>!?Hu^D24f(o(>#3n#izw|x+>*zD=@o*) zYg{n4Z<+!ElOB(d=rhb$y`w_vMWZ|OGi5aU%1XB{zlIML6a12W+FZ`(pFVSa>W;$W zWFI8a6ui@eIGjgB!qH!P$6hnMYLvi}bL?}I3$!^_4Ge#naJ~rE)PRZhY8zE0T8b)t z@@o~9o}=cB%0yU=JZkALt+GZyJ787**|e^u=tPV)qIDZJu}v5r0%RI8=3|6^8|*bR zDe$mt&@EXE%fL7xabS?bGL_?KFZq2r@f@padJ5*q&GM@F7n|zMmk8V=FJ7W{@fwD4 z*Nm-I#t#*$96Ez!g0tOetSQB>Ydf+ucjXu4L)aqv z6vEf0^($l3iI#2tf_1U2-tvd0a9{gKS6U-Xi@#Y=nx8dWLi^x7^>1bmR-2`1M{$w1 z1jZqVV*$fCqgC?hL4}KUwc6oD^^P+Q)UyIXAAL1Cq|;3*s1F)@{h%jkXUkN z7+Rbej8|(rLMrT@6_?xM=}-*8?n2r9>*s1eY{pz=FH|PZM~M6gO)|=ipyCk^UIpWH zp)^FW5uV3U;ZnnJV^`6{ij)jAn8cosaY*Rb$ZqkyWLMPIS_PZ0`PfCL8r{D7mWubL zuj`>Tx!eC5Q65)if`h)aH6khD&wmkU@-)AQGi*vx@|E>|FcR)SsM68oPY9ucYAz*r zE<(ljURmC<#6p?S)5%G_;cig&D^at(w4)CGV#Dhdxu{(zotgP0{Dp=e2j&5jk+x&* zxTdq`VF1t1%$ND!IzPWQO6`=qeb;m-+jPL9%V@qMOSV>7tT;Ho))fDYbmcT-FS7l0d9O%`k}+Pl@z0r zWS89RnJzVDBxAzZr+egQ89fh`C(*CaIPGAf((LAGM-Ax~dM=Vs&RQjv2EbXw3}@d) zPv*GKX_EHHn>}YmYRQuzsXOvAIpBBS1j+ zP_LntIl&M+D7{)C@hRkdXEtwshf5yO^)|jgBvtQ}edZMurqp<1R?U_gq1g;XY z@{t1C`wF;%`+EerquAZ3v5dPTSV<_O-FT)+!>YD*77?LR)91!@iaGRAXK6_)VS9b` zJNwwvXdb@TCA`kI1hMs`k=32@fhy8@{@c6cI&RlPxPL#A(f=H|n=FV&w-gyR%fL2Y zyO}9IuB*g@gGJrp6%tjIUI{ec*$6?Wp1v0cOFTL1x!q250qp0+5}cmL6bCVS)`+As z7a1zK(D9}byvBN<6szGRdbu=u*mOCg-Y(?YnV+FH+ZJQ2))A806D?{ZBtslk>(r?q zq+@ePc5sNy*_?DuznPIf^sLg7>AsL~$*N3b;s>PU2ZJlm_8(lx)~iae1LGd-_jc&u z9o5Q+mf4O|Ji(enPB4-?Zfc^Hn+La;b}~Y00wyVBrhLPRS&`AMulSsLY59xzcZ|L3 zdba!*ma$7y1kJ38e3GejTx<@P-$M5SslE!x1ES5+y*=9)h{A}MzAUp*!L|OuuvrMl z1aZl*Vj!#j#}1bknO;gLMaq$Ag@M5Y)ov<(mL97TP8WK0;}~-+g3xkQC1;8&n3aA- zlK!;jPm4Pl9M-?)87^m?@z}vzts!z+19r`Tvr95;aj7SI&P!mw@%z_k_3!FlIYE%= z58jv-=d(orjutSZ@KXdGydA=2+*ts(M;T~pIm#CJ>1P=gPm6HFRKpU|+KtZH8qTaMsSQ9J18J1N{#>RO$pL_Ip#k?!tY!@w2>$$K{+fb!$xc9cy znRrz!zzq?W(0F3dS@QC1jvcI++>rq_vo~OS(YBaXKK{CeV06V@u#>sJLnxHzG6epr z#!r?^yNz?ymx)!H^;1>Mwi}NM8J~qRI9#7Fw@)~xFy!Yb)XZB~1-&8F<Zx5Yw?q(l03>dlr08g8#)egG6f0m{n~y_*r?^Rszb_nm%ET-onWuX0+Y_FWpNw zVZF`u{9-QNIS5^v6OOiX=0Laf5>-it?$ct_zJhqRm(P6f7LvpUeXl+{mHrG{#A}VV zn|M^M3gh#-Qfc(0)rFMX|5`6kK-8$nB-X4v+~HukCdOpb$6R#e>eiHKhJ(Vw6xM8P zXJn`1Xu-$N6Nqn4ejxH&TKl<*g-YU2B}M<7tR-p~T3437JI|d-tlW270%6gR<)VO4 zEqYIr91=6{mn4-oVm-ZRT0tjDuEg{!;eZRs+W2yURdj0! z?9t+tO(9~|;VEz^6jzFv%{^oz35x|i_m!c5-Z_6bLM~81c8F|55w{KCgcdAx#P9WN zCdPgS+e;Sfflp((8-?O(@RF#rW0Z9WmgwxbPMgcyN#JV)2iE3hC zgQJ@hxi910$XvLT-ta=<*p{TCkKRXxmzgWdHysR&`t6^-_2OYVqdWio9IxdRnZOEgfFRx+hy#t4eZ7&1u($%j-|qs4i;VZQpquaqjwER6;RiI*}1dV#H~` zcJj3qx;q07GQqTjie~h`mS0_cXx!|4{DW#lyU5Ljn8W(s#yWrJG=CPjfGG~yk^+8! z=g!MoGZ_jjZF2R?UMaO7t~v=f(C`vS$=LUJO^1p({gs+ZKR9bsV8NM0i}>ip-LSJ7 zKb+XIj@gD%Kzs`%FM>vI))5t%wd3d}lDrR|gWmGBJSu3EaD-MsLwp%wWDmX?~-CIf{jH_z#fJ5l1q} zqvn_KVl4<7_{vU-Z3_n?aF<@WV9J88SsL-WL{b7qvZ!OcrCpb360 zPTE19!r3|?ZWZmNfR0zGEGAtP*ie%~Wub9bF%%I0B6fb$a*D(VNToK;rUHkaL5EbV zX*0v&B$blVR60A3Kyq@<kW>JoP^7>?tiz#N z$-*_j-y+e07KJN~xSa$7nR>+iO!BLfKMDArcO6z&U|nZd7m0O~sum0|I@KE_gTw~0J{rWDatA8|xW~r9x z3o-O5oX6&^!NV^pVxjGVd+~LqNf%Luh~N*a2aZL>uKdi!2i_#6S}cAG)n@NHj<5qy zj6)g7ojN3SB3z`ROTO&y~9Or(l#Mee)yvqOn{te=9pt6!+`M4gr==7Zf|_u*64VFSHg|Q_dIG( z9kWc4ipgX;_GpItCZN2xO^NLTcZQsIor6+&@gB&6HSfwawy?&FN=0y8Yz1H*Tu#M| zgb)g&U}yNkJvI}nMXhc!31(er&m6inCEeF>VC=T-*|+H~<{5v_Q)kJ0w<==|Wh&%Q z=`FFjgNT4k=Yvm^=x2%L8Wa$dx#VEX3Sn`vSGl2KU?%lw)>PI@>~bhJBh^_(z$o?Z z<+n<)PA#=%&gf|rl3G|!+baXi=xE3hnULX?A>q+@VMx@#Pq|-3ZD-kB)!QtnkA0Bgr;IVOku z!7zskQ(sM1a+Ok7a+m@m`S&Xs((2_8PjQ_gGeU^@au}i#`HCZ$5i!qMg@ufR#}Uhj zH7$(Tp~{i7Y(28Nj%-MKE@six40Xh-Uz}&|y}MA6zVYhY;L+0Nm@HzV6d}~9!=Ap?zfoTQ9WY`Rw)!46at{Po=p$1FC{In;GNcSm<#JQSxoHtb@1XhQC z6IV|+cp73H9|vb>0~7i9qoT63A$UJ zLF*_AGM!%QiABsfGp!mZaN`wTPhG^HO-rlyPL1}n5@j9Vu;cw;vPvU;v(Pk^pYF#^ zFDJ#beu#hCMRWc`DgPc5)E5?fWMoH(#F4Y&2uUNC7_Jc{&yN+|ne+3M{E6$nk$S)S zxN(TGQQG*Y;}=OoE9f!FOuI+(k;9ddN6%113{2MU{^C*QzQw@VndH2&?`QgtPKQ~@OBWclQq>tfzXkC}Sy=_L{i zTN{+MUOK&9!jGo|iU+rzPhVLcPNY9$$6zyF&K41*yU|u5n z%tFE-$FgvUp!&=BGp2*PADC7LOmTUA98kJRlU}+X5AY7&fk~Y;uZ}&eZdSm4Fq^W# zb5Yl0ixiLw&Z95^F*ZWaBbtfJ|0x-t2DhRcVVVWUsm^(`YLAbQ zX^YZ)&)NQvlXX4HnKP1{qOg{ea^vg1C!U&dTbZK~z8`35oo#gjg`+(Uw&y5=2ksA9WcC z)``v=Ygs>nD@}aryEc|c@@<}ulXZL*6@zh>0$(@Khek)_?U>3W<-H;3D27ZMfNN5? z3?)8UGpQML+utZ0cgK-Gjl;T!3N=OAQW|i<>s8V&nJ+dfgACta$TCaLcrGalNH>xm zn+aHMi3j7(!9~7?ki-+Eh}O!54^L7&0?Z4-Fz)5Yvfn>98(r32==t*LrTl6KnfB&%8@}?x3}@ZsLt^?Cr*-wARG^EOHl}@7B9q|;~Xe0^pd0h4#4U!0f!YZA*a<<{ZL$bvz|1 zq7iK3$bI!k@pNg>*lfvA(dO&%bMHFhb=)}~@WUtL@sCs6aSN5jH%1&~6&#_xp2d}= z72S9y^PRlL3gP;X8J!3r^DgCzx`wwM)0-q#=Pv-Xo927EfTT8Ls)|nxk>koCq76&> zcIcJ2CbY_Hwwb4Z5YUU&o=;q;TWCFeew)iP%{doFzOLfwe6hqUrcE$d<$-u@^t-#% z?^L`=I9vzm{KPCuW(}jbn#ZbZBSlb5 zw^?4>cn1k9VWHunO<5y%ipEno?JVCkKo_05fc(IZKy^46R89LcPIeJW0cyFJF|AZ%_3?R zelA01o*@Q+l+0!{S>g{!JCfX)0SHb(|N6zP4Yxn^@!#4=0y1XRcND8KwBm8r%TtEo zUk{rB2qCpxT?#cxBk0Vh9-{Kk`)eqm^(08C z-9dwBQ?KaK-TyA?8UJkYm;xebg2yEM%oCq1CAxn4Tm4W#X?%9=s`>HXnPB&aRwEFA zPM}l6tkK)QIrmS?@|$!2hyZ`f+v+f-XhqL<{hrdJ&__- z>2oK>M3H>^pm(*W&4a%W5;1x6;LpntToa~je~GMS_y)1lW(hUZoDO%ir0qnl<&KD2 zhMG8D>i?|Udi792jrR21XH*Qtq77&QE!(Gn^7UuHM>mW{M!gpr-6zjF^Qy?&e2_a# zpnx^MAqh@oRhu_ev`PmRcC*|i}}(fGlatI+GruCha2!(Y1T&-#rsl~ z!!gRo%Fp%+{S4|nRJajhNX6AF5Mf-2vo2a!R&_t}aHH#Nyj_^`qEJ6bsZpHf(qVw% zjy`6t!3u^+mcIq-k@nv@42x>Iew5r2tunt%AU}>l#b>1qN6#AW>rGp|jr_7-Wf;Gk zg#PaB-y3t4lw5dlJHo_K1USs&QqX}e)*+_>s zLYl7PZ5%PrkJ(&$;mCbBoBghltzpQmCb_lK>TBew&`PqW=ac+b4?i*)S(VUc2)F4m zF|`iDlr$c?%{h)D$>%PhmnCP#4mSpXqgH@Qgg2+e4(Ne%Vh({2aNgl74$%Q)Yx9>& zZg%D0h?<@7Q9&mvH{O@N_N<6$|1jM)q}{~oq2kAP(=Xn#l@-K0^z~KpUyzT0{BhD5 ze;lUZMLp-N05-k=e$y0PT8a~y`aGQ2Z`AsV2LspJ zHF>_$@N`+=o(ioY4W>p8Jsh^eaulWpHR(2KeE2-FyPSpc#{l*bnl3?7+HVWu2 ziV=bFK$0R&e%GJ`*DQ6F+Qd)iO+0&kk^_UHnm)06&h0Z|G!-lC=1K}kKq z!;VsUYu28X;dM0y5vvr~%vP?ay^ zIPKkl^GE)*c)6yq1 zCyM(t{$^>G7LL+M^0s*D7V?D}uggOu9SOpLuS>792S41xKI=r2aPsl=`GhZ=ap$+` z_TnEEn6NHB4SQ4hce5-QS0TNT)IKPvR( zsEJAReY95A>a!<(-~1cN|4iofRqpp^A*yd04?E3NR#Zfe>1W-KSr}q()uFbg=RGNF zc$?3_ZPhSOl16G`j73t5@kK%?HR;j~#1F?-=-y-w1;nfKCvt|`C;dk;XP;G6lqR>C zT=W`5lr{bskI#LHNcYR>6}F;)9#KHTfGG7k$8xRZ5*6_QcZdtq8e->wq*^7qwC=4` zG;iu{>(b~9HM;XOW3L~Ct<{|VDzIY4l51(#GOiyHGhk4M-DiJP6r3k&q$a&K3IGNF zlB4E$Hd4SG1%xU<99@j}u2Cp6+>bo^=yL(_N7YdIBV~_(@&U!ZMi#jGk~#h)NyaAH z2G8I2v*X!Aub52r9z>w0%t92cxEkoZ>5Z>t%Eg6TkFCzVpxMnk__^8DjoKyOTL|3u zevkZ@gBUEZK#dDXEd-Z!i@(#{IGtaXnY-ujjat|*5(EAXVRO<^8Frw6uKU~~{GB)# zeY^Tggc)qP+rfWi)L%qk9)ZK7f-yT{zCgaHG_-SBAKqMtX=h+lb6jESfMk zT9NTD@620qT`4VRE8x8^mmH`zGB zt!fb{O#0X6O{JLv+7e#D?5?qqUkd(WL>RzaV2*#>PyV#GRY+=@&~yCgb-jH5=Q#_F znorbW;W+H@KP+K#-vOyjRdm@$sISd%VTd(AvN)};Xe_&h?z zffr%$Z*EWLGwM{^vrL%BBgQpTpnt=uGG`aAg?d*d9u4MvF0Kpz5zBJjO*tQI?R$> z$|t&1BFOt#f0$=aL7Yv92vZe0J57Zb7 z2_8^DkE?p>(z@sEmYxj=AYWis9N&kIIo%kX6L#Ix+r@54uZuB4aN3(M=_w$+jArP; z(^6EidzbH8?ZqkOw;tW%UV9?sgqo0)ggGuP@eYW)wmC-ZJ^H84&Jp9zE%2QF?vW9e z#gn*c%;~wf?*x=@M_GRSJiF^eM_O|Ys@OZNREq30F=L)c)D`9mc z&%(&MZQC6Bn)b~psEZEq3b+jZ;wmYH8`Bk|zg1pV+b^dM)YE^Yi|(riOReI2A1o-y zI}T5ABAco_qc}_zi*KrKi086tH^4AKH;IOE#AKa8ISXd1unY?5Vo+sIKmAW5%cFu>G|gDOd-;)Uy4b(PBZOKRhV zgsfPWqMrLIwqtM_6WSMf3o#tz+vC)0^A1Ut{-s9p{*LXw(kXK#4_mEvFQ1Ch(v6EX zX#80czv<^O(T!A#nZq$(nu`oij8P*@VLkYdLfst^%p^0sTcta4ZZ7nxpNMO>Lp>iiJl9U;noX{ zIpL9c%2{4LZ*D)CDBarL-tgLNJ2JTHYnyJ2ao`Ain|PF*i}~r7uw{C$`;1ATFkZYy z-`MIF^@-?r&xMwHS?#8-K1u3%>FgU)9BWt-pu@U#v-;g*9!(*$f_PC7U!Gs)l1R4? z3d@G0G9V6lWjtO{5C~|AU3qABhwPt7AZ{4gy!za^*nYhTbW1kC_JrjnqI4UYD3I8` z8Cv_8@Z7)8TREQPi=de=2rD?x_^vbW3g^cqmM!Cn+3yP0yKliU>S|XO_|g*+AJ^7Z zR%tBdtv<1c(@*Pszh>*h@42_`i7XX+n@ub`)bM?X7dBBYv(7|3wKI{EPJDO_=H&wO zEG%C+@wJ3uHGY%OU3wIz0D(_*?BVT4hLc$8?5hk$Mm8K*E>wRAL0Z%ZXLBmvdYvIKDydv&p9Z!dy)EsDe( z+lr`Qcqs?5Er8#ZX^P(qsi*O^$TnG(M&RO% zO@FpqmQYy;S~~s}bF)nPdw1mMg@^fa7bR7dDx@7Jvbu%ZwSJ;gqC(~D50xBcpx8|u zK~uvJ&jU|7w@?P)F3-fPPY%drM(&4LiSsU$$Kxlme zMfAh9%t?Ki%iD!A!I36?8=2@zj&hDCO10M3hl-LFAI0SYe6CL|c%B;-&Tm=qULp)F zsh>H2^_#<TshIi+BVTmM!}6v0ceVMXLm+7odj0)(&gPl4TT>4HJ17`mlDYN=V>gYw>4h;f2bLj+ zQmsChKGXaP^3q;1%Oa#wa%eYkeQ7rDSy1Ve`3H{?@EDMUn`LyoVJSThS%}h{GTf|% zZJMV%?rmpyBg57q26EuOh^LQ}_AtbCa;X03;2YMJbH0#zp69dLJ6RTArc5%+)+p_d ztk4{T?9S{R^i0~?Y~Hsl_ItABq^MZQBHMNZu7)S3-4*C4tIY#gq073x*GN35T zYpbzu!L@foF6sb|astx)UXu=q=u*h*>>=t+t0MhLolh%eT)#b z6V-qw+SUHLo5b6Izqc9-7i%fCG$M~4^4bxU2PvRd^g7h~Du6^pIq$=_wgC_iT;Gcu zamRtDAwdWm;2aeb=Ri53>2mvjSQj5Z`B*1 z*L?(lBGV>qk_Va&@l=eJ_-fv6M6Ish=}ZAk@Kk~ASNTXwM3ZPaLs*jG7kj5hUM0tj zmD-e!@p{Rby-K^ya@i~MDmMfe(|RncM(Ium^239`>As3HDY9*~FUD3YrII4^wdsEZ zE%GPa5Ejq;(HV5YNzGE_(V+OXi?0j|UK?@Fv5IuAaGSbKR$}~iZgJBR+rnRXt0Z8g zHV!vG=_s*Gc_L-}ry8$vbBrjkTZC!5&!#ZZe7q?BK~630J`sXd;mzAMu=tS#nNH!p z$}RANe8uaTZ!(y9tcinat6e*2=Qfn8(kgm%u0WPMbEJ|uFar%z;DauYm;-gv0Vtq` ze^*lE3QR>iXjM~mh31+Im1<_2;5!<(mgA@B!3@B|G?p`xfxDH{;SZ#P!&q;2pS4Jm$WVrF|*LMsku+0pH>ug`mO8!GLOJfFC>pX%_XYc1-$yVInH z#*TDudf5Izzrx+4lE!Px=Ep~TO%5WnV?};?zfmupynFHO`E}MpX4Z>zCAaqSAk$G` zW&oje^5r8Y=LsZK{(uvFOyRS~o`$li_xCWW(4M&|MeQMwC%MBG1w3A&9fV<(43z}4 z_{!rTq3);Sbv7!@Xom^5`WGIW-+y}N;;~erM>C#HC>r0hKLmghl^Jb%B1EI6#<8<- zM^l_$Vaj++pTj^^U#~__NmyA`iTw);!Dxf8W%wI!Vso;tx-@JBuyKklEer0~=FG3? z8h8#2u3SwIBM$tO1Cv=cv9c79lFu}R%)wqjYW|oyMTVqacEOO7m7E( zpvzKU;pS##h{39k1vJ7toCvxVZ~nsPCiWbn$YYN#vf>mud_SSO7TLC%tfRUNtmQ{# za5)_LPzNdVD(#)?C@tORjv46b9zre=N>)mdB{u*WmLDh0^A*^DB#5mRU}BBXJI5Yh zSqcSo;hrRtaT!S^ndf_}N;8+9gE)SKM0~V8#ndcc|3RUHFbi4=2qPWzpeBR;2hx+cfI-g7Gvvm~(N7g*U>IE$3 z%q|zYU!^0gukm1`XJZ6(+0D3U+}tmn`*xQ)4aMFEnNDpy-CwVh>mbc06Hk)KFZWD9 zJ{=Ga9KU`kb3`iP-Q@S+Th~{#r0wqTV3*F|R;!qIaWqt=1>g15)bO-G=$nEn}?pZ0b-)M(spAObojR z9$Qdb4eDKAP@S{CFx$Y9QC1eNRUS4qb#?mn3C50#4lKM6uQMO}0(uV06WR{jmCsVs zt0LnQeIRMvkKU9t2AVtG}LwzldukX>R~g)r8uFa(yHL0Sk2 zr@Ty49G6E6_M^)?CsN~1xN$K}jcAYX1ao+Rnl3o(f=f-_(sYzZJGMOGh>W~Z%e(px-}_PcJikJ;WkQ~cnoms6^Wksky+0c=ovHL z+j#V=V*eXJ@ei!O+WbsRFcA1prq!53k4)E#|6AQO##g@BbvWgQ$VSyXMwcC z8{m|`ur25*k`GY>&)Lqg6znTM2M#vb3z56d2eW)IP+=-m(9NfO$S2Ln%NFcNDypaB zK1**&k~=~*9w(U%qJ-Tv1-Sr4t<^ zD3(P+ZEdb(jC`$XsK;(&*Yf4N{*IU5{Lhk{iH3*wO`wl`A$Z%CO|H9HwJKf$!4-$cIt#aoPn6=(8Kp7EeKjeqs4``p-T}`Whg`KF*LA2Z_<^W$^5{}sXjv?99 zI*&2!S{$YNDrCKctnh77lj^&m*Gck#FE%z|j{pwav!j=u-3zS0f$L}jm-VDsW;yy_ zslZEa)Q==e_Y02GV0ruJTsV(=*7&whD39p&i?v&INqv9r=HkqpzS=B#TmRPBwHM3D z-eWyC3_W4XQAORU#;@9jnhS5n_#_zCA! zOH{{yudS@fne5>E9J=@!CUruJ{LIodtA$zR=iOV6c7Z2zm`A3wbMWnuU>Ep=0#C9* z^^eOR%9H2&HYBfJ-p=_PrDvz~CQ&Eb^G@ssmRGuIuXLP+x)Vw5h=p4_I?gD2C7|-S zt9t3Z_2<|(pOcD!vr0v`-V!SDG5a@wipM^MYrnooWEOL{ElmNjXZ)EU$!_8q@)`O= z1=0h2Z?GFZXZ!zR@4cg%TD!eb+*VLTsS0XTnn;OC6G37Fgor3?Kx#xq2oa(J(n2CA zMXG{;fDonkC{$l?iMCpN^HYkwFr^K*2OuhtXFYu#POjW5q$5D1t>+E z#jDze{NQSOGMhc$;UM!+?EzL!lDsHUHbC;e=pyse4*yYHxak7xRX_~m#X5ui5hEte zI=TA`V#j2cqa3kWUi3a;J|7%2^9v_CnFv}> zvLcQVw*u|E%Het94JzQH^yu6SKxJZ-5@5Kb6M3s+)Zi!~NJBS8PCq%HH$0T}L?pnGrA?jsoMOq#-;09F2shtK?2)*h z7H4;*`M|w>p^fLq3q4F8rA)}#CJzlH+48&EW+@@$a5>?7Srt zunxR-Z?OO;MCbSquI6vX)NWh%kOxoJ=;yP7(j{bC;4x9m#T0X-Nhhdy7f(AXySie%l=JGP2Uxlw?P@M))OK}(dDV*$G((#G3(x<&KwSMH#ae|GT4DMJnU8MnMi9#}d-mkC9v%C}E!SGh4ka)M=OscFb8Lb#pJrUz*Th|a{RrhHW;>{= z<5=f`{&5`FY#jc1`F;8%Ru(C3Mz`7sdZg6znIQ*<#C6mtC-gKmT&P=lm%jWy^Uw~4 zt~yDmb0n0?+_bg*-XPKaYho+-afA&kL=OaPTKU-u!+y7F3=^O1E0 zuo*9dY)3ww+p4zrTuktmPbhb|InAvg@I>s_l3RCt;wCvfxGFGicsLS@+wMYu=r9Dv z(*21Q+Op4ziIg>(Leqv$w9A|EqO!~Ca*FwNG6$n2Hqjxp^H6eB{AN+iaF_LmRTge9 zVg=!`X3COl4&R&wtF=%47V&_EzW?s_m>wJrb*@GTXh_=-+@DU=R32|%yIwwjQAgk1 ziKZ~os@fpup=0@?DdK#t!NO5hj?X%5V+>XuudjYqDz5Yb>~}7n&hKB9=gi!#4;Gtw zhqD0#dh);j0y0yCuJcMF zTEDY-TsG#RbhOlY57zwjO2|#<{2`2#u*3dj(Czw0J2c#=5}ijao9(h7IG_ILzb?eM z^G+?}R6iodOx=nY-{I2U2I3^I7zW^MDA2Bt#FBv)$j@q@faY`}mcp4cx7jJ=5y(b+ zCa0wZH>3E2OQwO<#A$EF&473AG@KQF;D6&`#t?ydbH8-|HEtJ_*IxELS)^z^b)Atb zpC`?811ZsXB$r?Du40a%(2mz3+MS73ajCdG&}#kQde;k+cNzf^y`~5aub(Z_&nC9q zdHoT18B*Pu6T2JGA;%6e&^6(HoNe@xFBh-K!o=Kz5U)t8XDxIjvj^EpJrW%s&F&i` z-nYn!d1y=|w&DPJ$il46XsBJS>G1hprCewYV|L?$Pj@*ax33L_!q&+x-4HO#NozIP zrqzCx>*1vbJG({AoE$n)VqO`A%wn3P`x?_qeYFoyJ5ogRHhM^DkRM;@9XiGitNGKl zY1KarGX{=Dj~|JN#;*Me&R0cXR86%)R<5a|^PS&BY5-{^RyZw&;^m z4po zzI2u_tSXo+Q$2uW4$+Fqk}?Y9lx8#vlDQw~`YL@Qc^wsu0s8af~%rW4ro!^|CDEI8b`bZ+uo zggY4M-Y{_;aKAuHrcdTCYB>G&_fPSkB(8zr);Y~>s<7qjEa-1_6nZnOp=aaaBoxxM zU`OCF#dWdUuWQt%rZuKDC|~al&2+BfA~fT9Q_T~}*(#jDkzpn85^_08m8mez@tns4 z+mRs4iW1It5G>BMa{j@^N zjo67n(PcT@4Gg#SyA^;U!G3Fh<~SCf2JSY>=%xTAR^&+(yFwr7+v)_lt(~yTMi{V9xZ5 zm;pyOE5h*Y`=Q0S%|c_H-q7vTQ8 zL!Z-a88)y`*y=Z5D)S=s487Tt0W!nDppyOa5i_AslIlk2Ly$Trg+AF7Ev=4QJqu^Y zfYN-?wT-on2nNYWTtK$BZdItM5#gzJiONV(J)d z0nua)O?h0ED9oNOxC`6!xpicZOEJv;qSqCQOQS&Dg{bCPof~C-tk}1+_J`m+Uk7?B zb&U0M4t*ti08$%w0NfbrB1FHEaXBMLK%CezE%ScI8eF8xyJ5A9krequ!zI z;KF9JV=>Z<-FkpxIudqJ3Bhe2xA+Dvj28u*5hcCy3Q1vm+HY8Usq2LH*KiiZ{k9pr zt9>oN0fP|%Tss_8MpY&tzSaPS*C0q*JF?0TUSGN~*a^VcTJwJEA$fC4SAug>A2<7y z$$Im>aj4#;2e*7Sd~y$q5)acPKZF6tr)$Z5BV&+is0ao|1`uhS4%q&+mTU7dzFrwb znCMIl$xtI&HHI6t{^I1dd&}R?kfIxXUJHgI0>D>YY2ydPjB)$tJPrI2V6cM)jjZY2GI>R( zXfYN)kJH3%R;*A_!N7xVM;f&Y`{a9l9(RPc!WrSp(Es8PU_S{J(a7PZ+eX5G_dvx^ z1RSX@A3ZDm@bg`)d!WF^E8~MRRl5y%IvxPbaSZiNTyILYY!Mx*|IDv0S~4TAUz3aH`#M7AuNoD7{Kdopp~yQU*In;jzt3O`Tk zojzz%049mP*fa_)hi5;tcEhiybjA&g-YlJVYhK5a*BC;c-tOt41lRDuW5VSfYqGSb zDD}E+-N>R-Pje36G#Nd1`0{+~MOg!mFd_s-wgXo$^n+_M%KhzQ;}dZvb!10>+{#&eUf*G>sLxi_CMH#==ht`Km)JLPUWo5^))6`IO@C7q;e=ii)dW2f z<@ld;HSBkm;O4LmPCSsE&l1aF-C@73lmRR*7hUi#8#mZ9S8APrno2>~7ss{UnF#la z(i&XYb?3Qa#HFc9QNWdX4D$#m7#-W+ggP#+8Au^L9gte&zv?RZ^ilCPA+kq!J8q#2zc~-G)$oE^TB75p4NezA zA@tSfkxiakC5@W1^LZ&Gw`YZvN%#5-n2*9`%IWu~2!MDvNWDCP082fk^6742tFc7+ zrvr$d#m-iEHrzjK*sI_6Iz7W7VxKfKhc%MyN z4L=CP=yWL|sP~pz9eL*U&kb22;X4U2rE@akq0Uo&>f&!mQreT}8xr{d2~zz#tO$@* z1E+^qwLls)mFRK^zBQciJWdc}I$@gFm>SUPzObf#b>Hojdt*sOl3yZzWsfIaXx=dR z!x#KlO8H>AP}+R-*|m^+r5T|GVh0rV@WyoB6z3zk+ou1cg* z8W3OSEd>NV&SSTgc2*u`UHQZaukqGiG|P2ThM$LO4VcZJ+w3ceH_y0x;9J?|vGD(p zi8hv52Nmjvm2xhd?92=2T=ty$**IsTG^Hu!my?J3tPv<@bHtVP73p=`pd}r{oO9AU z9teC@%ezs-ce>B~?cJWq!;*7dIwm}&ztsyOsps@r39TDre5?rcUQnb?f)35KR2Sn3 zEQEmz!YF>|n=Q(})Jt_Of7TxBB7x*N>1S2za9rT|xl7wG`hlLjU(5vGQa@;1{cxMM zw_|Qc$w{6z8a^9@&6H?r=n1vd*LzJhbo5kdyOUIo|H-&O==m%gHWS7=KmdC=vp;>m zcrR!f2bf{caM*ax9x(9}{VT4znGvu7stx)TGAsWB-=97vV|(u@g7i-d1G56;LpW?3 z=p@O4xvbM%e>7LOLDvgf5BZHhzKRD-Q8hjPXEpz6%KzD$f8^$$JN2JF@$c2vU(+|! znEPOp`?KsHTnI4jGV?H~E&f->r*;+3_HVpw{dRKsh45y+fV1O#m-GEJ19RC`9#~Cy zlBNQoo_(XOZ)Z2I>P+P}U+pE}SL;JRxVnT=Jyf!p=I+U(F?A#S=D^E4sKg!ZtLS~9 zvU=?pby;^`uOaK%g(U6b2xg;;+1-0jemPnI6>pNd8L%#zsKxfx_hkEKr2*ttUh;Y*y;D|$hF zJ=25{MS01BCnHqemWG8ekZ4TGb!A9_%6I#RLq`huWNamWN|_FywV zLW_Z`4!tmOh2G*%N^#e*=t?hUh=k`&$E}&y+;m?WmlgMpJJp?<+i3cpKZna`mLtoK zWkJRv0?m15z=%b=ay{cI&?HOK+-gi5oevV%Hr$KjB|OBV6kjnwL`DcUhOU889R|isa=pIK z)4Xj{t#7zGo|gPnQFeWJ4;aWJGxUq~xy}tx;XJWeq)2m2a}$L;ngjB@1^A^f_Lq!? z2bPNXJFSM(TK3-Qj?pV3GLC*MCl&-jyzDIDXPinJC7 zyvMB+FLf`<%NGWFsX>X&fx^bRJoOvG`Mh6`@|1&JX&NtrA}xUz6Hs5Q2B0=}*y$s~ zALMJ9uTVE-D3F{5&6{Qb725K z;u|PfE--e_L)>zNRL6m2%1EO@rKgt$7NNurjjZ0~uK^ATEn zm08AM5in1%VwwO(S-!n(nd8C;5=c8~52DT>>RL#HG`K!f98^Pt`X;gQf^%^6U zXCLx!qSxLXYc}%NI&)Yn^}_*ns^E=H-3Lt5D$0sO<-yLpJjl1isn){}9&Ia$-6p-= zr;&z`XX&#;K7d1)!}*b%Ul=#6rMjIoRB>Zao|$1ehJ=bJNaW2N&Awovi@Gma>vQd~ zpNOW{PQUxQCr$2Qqv=H@X)}q3yB?+W5R0N)druun?G%#B5PTEabuw_^%|J7b=?Na7 z{Dx^otZQzY$gve>MKe~Tw?o~9Vzni!&f#ZEbA036I6KmT-`sg@BuEXTuMYAS8?hX& z*>{+Y&|_v{tAb!xm*j6Gaqw0A77ua+;Kxr~5>+yBV@Ylquy-mgvA7Kw$^ZVa_FbVu z2|qm$+`gA&T@cqv1OLZIhNHACS<4PrjYt7A7)D@;%9pnwNj_{0+KHQyNym-q;X=9o zA724b2&U1iEHy8rmmJt~c<>BCsi(OMUF5!P{h>`Ha#9LrV% zJno63%O?qxb1|IT(CyF!yND2r-G{Bc0I8bC`@Pm>kjD9f$}iHegZV0w~6vF z#yM4MN*9%W*;zUU<#sx>>qt?rW36ci?BDnIxuz(1STVm%w)O{cE`Kx5HvmLf_pUJE zG_cFe8$^f&!98?FQ!D$~@#`ZrJ{qC`gYUO?a^^&>hv&0;w)T!fH)X&olXYGYg6b&h zS&0F!>K6mR2toJx!DWLS>BG}O!&Pm!j;ArnG(2qt*2d}Obgytm)@dxTooEF^9$H-H z=xqs%C4NR`v95!3ohBQa*743|O>YoRwxs&U?lZX4T$?rPZy2O{5T10T4=0R44q?u8 zmS3E}2{>G^d@_&auI$cR?Gmb3oA}nHm2HvoG4%7TBnc`+G9KOXl?Bc(^R30G099$I z*^d@;oYUPH#iXOy>#MQ}C)X!TKLy=MDk=AG;?+h4-#!#2sY1!-ZLL53x$$&9ABM5y ztD!c5J7Q1uCu9bDwe4~bHtf#5D{}TETq4uMzWMYgiS($a-?@HWeXb#?%(r4d-OZNHL|4MLEn1Xr$eeyk%#1DTWku4UHm!GAVC1Q$j z%PXs(dD)Xp%{5I3Lyl@5)mgn0^cJ_?X2U%0E>d$$teuGG1t=Eu z)bN)Wxb!Ox)%~#^Hk0mdExy;KJ{5)8ON1}nj2y(yX*oj@uj%urz#*icZ%fJ3fgzS# zKZZnZWy?J%$s-J;QOe11T+LudQUUqjuM*_n1uZ36JE-;N+xYXdx>nJXf;MS^9T< zp!4s#-~+Gdf3IBZxBs((fA+wL_0Jysvj@L98~@0`U)_UE9S+Y1)7HIh-334-yQ_{p z3ub^xs_}sE4J)KM-nabd?x56mxku>Lj*P(;JK5)(r1G=%JPSw(W8{gZ;&Iq$Fr-km z7D^SXLkP%eI5X~B0?0O6#m9 z2k&J3=C=Q#2mW=R^MT2I6weELk){Y;+x_A+O&Qin01f&%SRP8b>9K@71V*Df z-mLv(agT(GiCev*s8wOc>&r@vU+QHfLx*=gv=2Hff#0in5Tgo6PQXOxhXuoLc0emn z%)xW!85VO9du5x)4uvlEc7MI=?{UdU?u~Z1`e|Zn-!EK}?O-j!UNB*2DFFK5g10|{ z_4LARoMO;FKSgLi^@D3a$e2?48)FJ{UF-)}EoS9ZutyP(^Nf3MYvd%99S5_g~XMFUJ>o){^U`YFLM774nZs#Ej9E4SW>C(3d@Ei9ZANs-N{w9Anf2iLJ zp~q!nlg^$UsV`FvElv$>nOSaWWWCKA&ocC1j*7{4YDmM?Ty(eu%Z$Y~2qOdX~&(zz9^IZ%)H>h4C6Lo*5`4C)tX^s3vmK=V;uFesz1te)6MO7XOxJD|^XGr@i zHHRLzbl}s-R*p9tv>v*iEeIFmc6%co-@y~5=^XMlhgpb?334Pvk@|;K(6NZZUxQ7p zB1sk?xj=XpF)v0g7fe6@yjUHUVlS9B(^74~1AJgt!tzc}E1@Ix(HdQx!}CU9BTxK9 z8*4WhN^SlU4%p=yaDvd`FgipB+;5)M(o<7=k0JlsLj|38hAV+FfG3zan@Iy!z~RQL zIL;+-xbaV~iCibKGhLv4)1!scVHh3sdagp#xR_ly6Mem7xwBXcX5WLBqlrXzr0?@Q zb-&JIdf_VA)^eV%Lz@`Sb-qr|4d_=;+Iy}1{clmh*hR0WWeeLM24{~nLSS{LPagAm zHU3tzb?|-{i?GRqox5p;YaNN5!PDE!@od47W4KYxa8OVM|8USI;WSx>37AhHRq3N@ zFBpfWrRG>{3dgw?4z}QCU?I~-p1jT;^s{@|XUl2cQ8z}7}Lu_off2H({=9$PZoU@Fj7xF}}iqjj~or|ly zQfya`Nn!y!P_m>v8lo`Ajj7j784~U_=8Z~1P`$=gtNC~_2JILdX&=`8iIH6v_8XqY zi=nAQGot!ib1TirhcO4>&K`1_R^9xYA(6VJ@;O;zvNw$iSy60Eh4-WKs>@|a%Hj&v zU}^ax><{Pr2QgaV{`=d+&*>UDSb4x5HI98T!L7kJ0XYVo8_+51B)B*#EM4kEQ%n;r z;7Y~57V(WX%ZndkzCDQ3?{Kue)o(7Tj%Y+snkl`_-vq^q60l3E-#H)@+65L1Bo@N9 zWGXel2;Lh4f{>uD`dMrVXJXb9fl&I38ic?qO3QWK*H6kA11fuJ;afXk0qW)OEMCJ5O&Vv=O#UVzp{pI~&Fd8(!u5 z%`jBRHdAGUH;zYRLw_kd)eyT~_3}_C9E7y*f%CJWAlxzXTLI7;R5IOw75oNA(Z#Kz zdUJW_6a&E2;92J%Tvua)a7(>-Pze!n)$c%Oqt4Mt+7O~%u6e8JV;?T-ydEH!c{-Lpm6ZE)|W9*;BSBl)Aq@6 zJaY}yG0XB0dYS@m<|)|Wvjtv11g@T4bfFZ$3{O zoU0FUdq!$~>{d1Y2D7IsD}Al{L+tKgh=)1#oi%ltbTU%z4Ic8VXu9 z#8)#c&wvIxYFx+2yJ^OHeQcCW{f3?#G?02n4eS-}6dszgWIwMxxX&j}?z#sv9Dq(Q zY@nH!3D3zzDbZ34DC;C-;LW_K>?LKG>epp*LFEX$V3M7_am>Ao^`5ixZ5igRrAkv% zQ=abeppghljzh%g9HR}j&DHNC&EAm2uz6Rze*En}+>}2YzB?AoaqTqjaskJLqv{dd zG|XanURuJTDY4%N9*Aaq1q|KiB{3&b{@qpqC(I0Co^BZ>Da znLKyEqTfv7?7YcLyJn`rq6Q;Y!SA@v%NI@z~TGxlba>xREuXb8=D-I%R<_w6W)MKFo+yz zE+rTJl^ZTZcLi0V;B>tSo__11&ggoXZx)#KNU5!TX&$ zaiFgJQ&od0djd)ui=9XVi4TImZZ!*ANwXvvRYeqOA;cMQ+=WWFho+eN zAB8vhu#zQ0r?cxLPU>~k{OvE#tX_E%qC8cR+uI`Tv_&KimC3sZR`jUKtEnyz^>6m8 zI@0o}f9bBrfJ0ofhlP5}9o` zHK#qQxxPe>A!ySRZAUpnBZ8VjZFGbB^cw3uC7q6UDYU%R%SW@UbkqxJ zecre9dYAWfjNdu#5w+dpP4;V_%PZQ7VV(V}{cvoY9@IMY;=8nNi{K%r(i!SN-sgy} zER^#A?q`$qM@vhGim+T6ztt7pCh)T4Iuuyq>3|yMpla}1bY({#R9St>Vv=a#>e*H`96~l__UGuU7lOoa^r;7M7pQ3c~NfVMn8$~fwp3pxx-OUZ_^FSFi zYz-zP_JY=5|A>=GZCbA|sWjFzQeR%PxI`f*ty```F6dv-k-}g;4874lPm@@jn zCP_;V6q0F6c4#uSYjvu(H!7&baC(}lN^YiFVJe~wq??o7LOCF2@aJ+$8Mk8zB5FHu zReIQC7)iQQ%-GP?FCrHfI6{o*LYIhU*JF7uaGJTStW=n>mivi9pFE9jEHufO+VuUw z-}`{{rPc#sD+AM~s&J!*?;R&4<@3679rO(G{iZBwsS3lFOZ{n;vf^`)pIn+hxN3x$ za2kd23~_W0D;uhLgwJ2pwEj?~VB=VCC;BE?0`0axft{p$*6sT)5k+on>!T-=G6w2T zR!+f4h`N4^TPBdF1U%L}ghU*=2N+2QSm;(#n=Ro-AFv@ zD78AjtiADgc7!T!B!azU<9sG&VXEPn;oB7wLvL7ZZu9$AjVOpe;-P2MI*4gH1#@g{T&JO#Ui|}0>qNF%VPWdM zf?rEEIW0@e>oEwZtx@Ch%+Lfb<4>sXw2bJuJ9<1=ZNa8^&e7lP4JMw(s>NZR5v%a>LAPwkxIqp9{nipcnAE4cTy1=;X(Z&W=`a-$J45~xM;ZbBTT*@t z=R^+92bPQ&mPq<2m=3KxQ%6rT*k2Us>AETIRqV1vJD3?vK7OX;9emySez=UD$3S@O z%@^x~@9|C`WI?J(s05iq47%bi%uQsK;duPQ@DDC1(sg;=SOc#RI;^@C@E5%MX~Zi$ z{WeYjbXRuD03P(1s!~LND<7BTJUAS(-n^$1F5m50(g7{B&&i2XGZq^4@7-0ravP|8 zWr~u0jky8(tHD4V6p%5fX?t18+sRVTaQ|i63SV7$t~W2j%qh92^_6$FmhFR%rVPRk zl~2kIap85VdSzyo0ehRHM;vIL3WUa4J4)Qe_BpTjgCn-iFnt#*>ZF^M+)@Fl1M&Z* z&DZ;{H{UoewXJO(jf)|cZhDFk&5@TQeEAHPigI&r|Xr8DrsC$xL<3q2}18PL7 zV>K>N^=B#HLl?)o$VBZl1=jQGDH~{iOPEHg%(RoH?e4#2Om1NZA|q+kk@bxN(g+Q? z<%~k<)jiB~USY?NOwtr8t((##Cp*gOe{kLU3oe)kC4h4QSO*77Ud>|3_d+$qao|Lv z?W(~<+~*mJa9ke#B;u-lyQSsD!Oxa5a*KzLKM%JSG|0llv{}VcZEWn7Bgo)TpKm{W{;Me{G4spE!QqhJZVMDN{ zV4sONwBMRV^R+iDt8uOt%7Hr*Ke%+~+E^#3Z|z$#7URNws&{MdzX%(&peQp4wZrOk zLX}quM-;eMQ-@V9t}BX1XACzW)6LbV*{5e?dxj5vX$*o6Umv)2s79%ynW+Q`j0Q=J zl;$Bp@bp3VX8l47ua=u%YG0#vNNILVYCqW*0J(6gKe9x{e|bV-H-3IaxxUOxJfU@^ z?CfmBoeuq8-1oC?Ke((w5O3I9*~SN3+9n%%H#zB1Ahz`807sn>+MV*rRywf zTM;`8Hu_!^S`+_+>i`f?BWf4I;=P~ZAVP)oYYxgk%ny}*#oH}VTlv6tLhioY_K4Iw zvV5^*8}jCvw&##_y>fA|r&~;PEu3nx{(?bTNCgvH;T@IY?mQDUXXml}^t|9_3{;$C zF9GegU2BJdXpN&Y`c&jbP*YX>VpLz94@CO?)AFN|%C3&yas(XM-U<>1zkOnCyZd2c zBIy|kk5=pkd&zBDw%6nGsjO3s=~o(742T}d-nz@QXSk{1PFIT08=533UcZQV=OM|x zBPsU4^}|oiN^d8v2RzhHhr|amicPHx$Qc%-4kT65$Xky3r>{$)5jER_>oZ8fCx*(hSaG}HkkxVoVVf|7DtfXN~x`~J&@v+{ru|OBN zS2L8~{r-*O&YkriR+G}!J3)gTh#O5mwufDgG0sCC6Z*uItoN~xiNpgpSkeS1Q}5@G zI$XUr#ixPPYggOPYTV}YE^bKQL@aYNGu6P*Uma^#gs}u{(lPb`DhIGIQIw1>cyt%} zVUJxQ#y`xRlzlu}?U%29QO{kBUWAw?xZ~DOci8~06ILR%97RTYcwzW4og){*Un%!= znHu>WHN!Rik3D!D(9Q6 zJdehJ4(GjG6-a=!atFo$%+0zp?=ZeUsmTB$t*n$?&l~PM*>M*RKQDh$xYhg)16`Zf zI?$-}cRtwi5t+DAi+*`b6u^G~stvXS4Goq1iaHiovxmgsW$jAwYdzD^oh=H-qox>%U~s$%l$@8@>Z3YR>g_=p8&1#~FrEOs#g(cH3OkVNVDKmXGOP{XST zm}LKkC!%am9kbLG2UQ)?3`SggW({En5&N)5-NEK*SO^O_LA&4ZreS~bxW21PPxsh$ z!C);PdAU(ypoJRpejS;=OdT!J0Ya30+4=!vlu#Fh0MJ&SsM)LGapduwrUb=Q-|D8I z&voJ*{?69D*Zm5jqctoTvIRxU`cLxz2e~zNdZjq#IGs|<-d)e{4yo6?NVhEtcT2UN zp;`_5q>SVdG>W2;Pj--0BWfmxE<@inD#a&Jn?B|f^$A`b7*>qk&@6UATx4;!hgCk} zvL)|*aE=TbAUix@cy2ysD?9{a!Pr|nEFK|%BLJ`ONG^P;_Pa~^^>a~SQP`o4>s5wA zl4)<=eZGh4KsA75abT~t_4yJYd;-CR(dsUjBmnW%&$gcB9?Ko85T4e~FUzlF>Rk&( zUF;cXI0v_V%q_A%Cr!~$0;E+gIcG?M;}AXNzCoul4}r>!%QS)YfT0lw3sSOxTPfb^ zg)TZSO2aKw{2nY%*hdYe?AFvpnjcbps(+b;LYr~5k}j*wnijXiVY(adGt z1HOmo$PuyBCu(Bx?<%}o9^(tlKoSb@@lKxUoIv`TRp~3dxw|w+>nnLag}kLaZ<1dw z0A^;sBi1?*Y|*tz{C=E+qeZP7{*bahuEtY4U^Lv18rqBBm5R!RduPnyA3WE0mMHS? zRU+NWDf`9XEcU6ucC{v?nskR6>{=&!DPpC&xUS61soOLjNv!s`b(lCa~J_-p(-bj9_kfQD=EO|i_9_Uml4%kS4uy`QS zzzYVeiTlCjCXq+lK-?23H8dYVUo2Xzn3*ri*f=fw1mI_JzwmAGB2riF#Jl>xt4Q&kbzX{5zjL2>cCs3o)xtJ?g6Ws=>exOsp3~5wGvCj2#gXtzg#<}^ex!Vx;GWz=6gBKsDG{0 zb}+#c6{;|pPBomxHgowdLNo_lo+#Jecz8nEJ0(UMHIjs0oFcb8h3m5^eJ4ByVl2v_ zumCjF^8zhP(dnMQLIJQ)-Kz^jAec$-Evjo~zr zk7`_IwACDw!U+N>9eNRY%;4Y<;JMtU*ZaL!?z_FP3V*{B$=vMM&Bw<+S{~3gFkdw| zIFF!*xqJTLx~)QqsjeP|zd$1)@lT$7hCd2@s;YjU>%oK9r=^wmoQ}ZG>zOX2VqqnN z#Q1nHiPJEZ5XbB(6FEfy-R66IfQ)fE&D(9hKWQ3?jEPyre^0=5NVM$%hC z0Erk#ozoM5*@m}`1oVq9sO2&txGG&`9Cd!&?v=^FSPOW|E05Y=HMDo7SvS;{Vn04D za&vTWvlyDWbtk|sw9#K)+bnrI?;+PW;-ut)g^@;U+Is&||0}EP)E;PjKUQ{0GdHQ6 zJW8R3jzYo+Ia(>!zze<7c6otYl|+V)zp}wzt2%pT_0S$=buW)&BWH_O-rTTxW z2R1+AF^E!?=QqX1kXA|0yb}VwXxgGh3*{qg=n6L-@@)j{Z^>WeSUN3gT&bcv8Au+r zf_}M=1dpxjvBmD(~d|v)t-5iHK(vTT+}w6pJE3 z92xTV6-g*@Ez4g4o-J=A=TVdY_8p4MW?tlUX`TUIFnA!m0P~Bdjt_c`wwuF`J=Jd$_5?jPQkC@XjIzPC!)Bm-mfm2Bz zyB`z>8zkhO^!F+Z4LRE)6Ql-#oG$RYmvwX7i90^6e0tFfd4@fGaY38$V<7XgXKTZ{ zGmy&IJF)A9BYnMV^aocE6r(y0S=bB4QNq+(`RHFL_U(OFA9r9`!cu)ZetmdPkY8P& z4-6gvqj7XFI21`LVVoCiFR8Ou@}2U&&^l66`aYPuC`?VkrtGc7rio&8e$7;sO9%XL z;_;cZYrMBNN<3VrbhA;er&geq3Y?cEl3ufRk^^_j;ESG${q{L+qCgsCySut+@8aFE zQc}l4T4l7@osfd2&nKRK{=jU#G75cqi4cVwjmFV$jU3{PsKjw{vt}XOw)A(z!X9D* zqUxA>uysVORg6ogGTiW$d|onok9HKfM_u=2mC3ftD|)xAghp(=s7tM_Lo`RKe%nw` zw*qF4geD6*i?mII*tACEa^XZFWg|xf_WmLUKgNlNeKGu?b!umLykRFmniB3JspRoc9K zKiyw>2BZHOkfq1h9Xr=^qO7~!?`@ht^w3zrcn{a7!}Ztatsx*~ z{=hM1po{^(L?_hp`EQB%I+deF3qgu&CnW=6a^Q)$4qH-~y8>%KR)ti2)y?5jh=Eu@ za43h?PP+_bzwm2Yp)ca@O||Q z2$q22P5LwP6Oosd3M>>I=99+)bNSqlhWE6)dWkt6A1Z7bveb^@eMo(4LK4~bJ$hKS z`&Id@vGMIDQ?s$90fm7&h#2;qyHi6Ag%Y>BO8-L3nzsWLtpaZ`L?NM)U3ZJPW859} zbNn`zHynH}n<$Ut=muoq^zINC3hJ+^!Klw2GYH_Ephv$*g1#bVRvvP%(lE*ridK`> z-?emePh?$o9gh?p<|Y^6cSGo|(1jq`!H&z$n`U$IOD&BqBXv!=&n7&xMPxL+E%DIo z<<)8Az?~Icbp@1H`g8LAKF(22Z>0)Q2u`|gh%}f098dIMlrJFllir}V`44`yIN_dl zrgem|d{rsn@m)daXG#lhC(MZ;h=K{N!FFP90chkX?10W_6yTFSFvB_N?VZx~GVSn( zQd44~7piZtUgJZ4?PQ-s>;1>)$Pd6FUXn|+!=UfA-`&}Qj`!D4#xX>`km;W>f^p~& zBMY!ANpIz3NbXj!ePzRA-dc#9_LMLi(0yO+Y=V56>Loo*y2u*XkWM2Ed53I96Utbd z*vX~35wwS9dbTB}sn-osbdgl=Gfo!P$+mE}Dwk%zB-?NrB6{*P+pT7s zQlx*}nBT*w?&PaqGF*8^xxScY8BMM`$#}<8skydo>Duor=I7#j_M60<^LATuDY<9_ z2TA!#7cpKSuC&9s1FCr*5(H&rPq?w<)+pKqkf4`TzV(nZ!B>&&=wv3eNfa5fs8VTN zbDaMO`J1=;ICMeAZUPs!6%)4F76=k_l?zA*PIOK%q$0=4n#I%&_<1#Tyl|S&h+ch9 z^AF({V$PsLc3#xgoYlJF-6L3JPAGvkLKDlv%!`JX)*M-dXye&Wrme#gU`pWG0I*co zy8^_FFV#Z@+_gvQuGVj_q9$q`k9S1BBsFLG|1Mw4;Q6E7{Ji8j$Hl?;e6Uc$2&XM|1_eYDgB>}^C7RVRcVOj## zIWL;Zc~VZR%Kn=W%oP!qQ8Y zZgL~z#W>4^BL#$_7*~+uqPt@qvj*CZ)*=sHFoW2wd?Rp=Rtef;3iQ?h#@Y*;7|0TIcG>z*@n@4G^O=`!IP1DzVxO~g1$}@s%63kS= zm;|PE{vKivj}$Q@4S<@`)kJSsTX3e8teHgDR?BVQ0Ms?f$ID#po$`Z z=7(QNe-~6>1i9DtNwBx3S^2vu#Z9cX`Av<_(y?LBXj7nQ3kx9lE6SI+WpLl~Ocx4g z)aGyAj&7wa6O%v%6M1T&tSfVhA6KP_IS2l2Iwc?sE8Z|>K{%XVdzi&TGTDA9-qJ8) zZ?behjHtp+QYu;2nvR^xU=Ozqbx5-WRBNCN2XA-x>2VFLP$?r0a~c07+x4yzcVV5( z@zQhNk<6=TsyG}kVeO&m5I(fP9`Zh6Z9_L&_wA{a$J_;C$H2tN+^`@K@WwgXIC|qU z%q=xbZC|A-HVBn{JrQ8@>b2gu2|tT*?b1G@|BJi#4r;3X!bPznA|gmpP@+^71D{G! zqKLN(hqVyZd+U zx#ylU=g!sin9tgRDvT64}JE@?FFUeQ3;BtmokmeIx)ws>M(6%&_eQ_e+rIOI&Hciv2Hj z8Vi+WO(C@yANbA2w{$N}afsn|OmKs$4~yh1QpJhRUAXp1$Z`0xGT zj9dd6nq5tI>+LJ`eA9nx9no`ISpSfqm}WVooiJ7POQPUm!f;anALo7Mw>$W^Q#Tk) zj)iKtoqROFG$@2+r#iv>mawRquE7<$;BjU4$mb!sv`*`}=Q`w%HrC=vD8PUnv5SEP6T@Z`cB8cod8dP9X;jPYuo7ZTcX$m&$ni#_hOa zFF%*SlqeiZ*3`#oo2_urE6s=qz=cmddXsdLXE)N~K@XER{=f}9uL%#$gX!wcE(VPl zE6?=qs(ndsbi8rvUL14Jr85rCu0Wz_1mTX=SiPSw0+=$0V?+LIU5iGFzM(hEngEsV zia)eBWk7i>IxQw0i=a9y3Q+rkMe-+YP*vx0*f+-(@?i6+TBDop1J0ANT_!_c=Bq<# zgA`lLwtm$ZZ-u#jb)5*}O3zNLa?c(vXInbfvl61hAEORUOAHHoDkj|)n_gqX#3mq5 z{WwV`e(%fQ+vPlaQkmL&ccX`EK$_*Djew)OyxX|{tNbWQ1*Dg8!5B%sM5i+axgfVwkNdC8dThm z;+`orG&RO*zYysRzv7wnc2)hjrS;9*)90*EK+Aq$VBu#T*+iQ?nl|zjGOC={O#SM- z?Yl{t@|XdN4=kGtaEm3YkBe*m4Hp(jw3T{xFtc77O;}Y;BlhdpXsm8Nth!3c;F4w> zu=jusnt((wa$=zLlg4cWGchfvD=Im4PrXaO*Li@clP;gqlDnQ5nq0?f9hJLaU%$h%AG6v^JS%_UPo7JOlqW=dmc*^R%^sJKB|_%mSUQ`_4D65Rz||3m=DM zHhM%FH4Kv2;*71Rnem(z#r{KUA3&y}OJ!i1-X-%rxz_O9yYPupMuYA?N@cwUoV{}(Pqy(aYQ<+>w zbzgBJ!Mpz1|9-u; zu;w<{^TjhYTZcIA@VF#dvlfY+r8)s)hJ`!eO1Jd7tAmRzs+Q`)@_XYtsP|}6M~(Wr zE&Mbb`eQZIpLGPDe){7zMxMKGCz#tjOJTlZ;Pyc?LGArGVJ_lM^T;ZLz+Ti%;OT+U z!?F{BVp1+iC-I}5HWfnF$`bu2;)_EZ`y8wf;;f-&KbYzvs+9<^Or|vcPM{&>{G)ZN z0{$I8eqk_Med*8M)t`mlN}#UWr@=LQ#1J!v2!`2}U&;C3ly|~#FHqNl3q8WZuP8UW zSpKTW9AnQqKI(JnSCUCcy>`#UkqZJYJjFHIF-4}BkWosEld#*6qucq$qZ<0)^6x%P zJ2w(nPbL;Vg`doxe5sV$(x@6dai}uhbnd3yvmMRa)XHI~_rF4KXZwDKUY?k-zYEtu zK*tsYy4yQz^NZV40yWg}|8;S@)oiAx=OLFc3yIO&n;FdU%4N|yU;W+aQ6JMqHHgUG z(A{%TM>v+fza#nhv4<4QO(v^K)m8(QE4kAywv=-R7l$`q| zt@iGn`lDxe!#G4!E&xjJyM&1c*q67n@6Z*JfX<0T7kx^N`NXnhntQZUCsBk6kzVqe%Brd>^LG3gE0?o*z$G-HT|Kfb z+-6L7SHV>B5+S=eY&LavV4zszKffmLF{kWI-W#CB@_zUKmrn-J>s1)RG+|N=|L?Ct zNJNxC*<*?uH1d0>O`uF9SLM3Ig_iszk6dBg|LArj{pQS(Yjf8)MWDp5F0=`%uiRlm zA-~~9gN1iy_YH@nF|EBOPgcX1^G`#R?QmlMV8@%=c(`qu3erZZdJoD$$tW%$`%8~p zL)N#Sf(JUI7C!rl0G01_9O*Ye*!?Y$m*6chmc?w2|0}eiWD>^LeEA$CeTU(lD(Jwh z-Ny+TEvF&@^zfFB_J$^q^gn`WPM8TqhG&MNGK*t*PV|#%&aC-F3c+1r=Rix&WhVWN zaaJ?zwVg&uXPNM}(4k%T(9i!Tsp~WfwqxmQ1dJLxx=N3%$@P&y0+^Lz9g7xGFDe>G zs&yjfmVjI9#r<`T=M&7r25nAqN)HxfZo5)kwfDgY50j?|eaYL+nwNe(Tb&*A8*}j6 zQLdUm$1V@Djd+r^G=>tVSDzH#saJJ&h zTR2#wX|j2Cd+*xCi{;|in)y*$;>QL3Fjjs~jxsyAGwj?{Zm5-qL#X;mPwV9UX7y>) za2@LK{miLZ)7XdCPCe@Nn*ZoysD*;_vzYqOO4NfomT)Xjf({Ywsw`@yo6}jnA6wQ7 zWOcAIm1XsRDgRaREM(oyOg={Zj01G`KcgS_)o@`z#WX(DO_QvL9O9B($$*AdCetCh zqCO1LL2aQvcRQ!$@L+z(F0C7hL6-IJ`;wym@K~h!=U8hEiRG#W0!bN{-tvPiSWjiD zlWgzG`9AwKh2wve|GiUowtA(6y4cgi+r!TaguK$56BJjW904@J{ArKs>($sm}{f?aQqo1g=z~v2GNV#B80PMSp z1)>s*@LFH|skbLT-@oM7^CDc8yIYMp{PCvPC7b3CAvdxluYtcj5Z6}llzRAC*mi-~ zYt*_>95g*KwOG}WlDf7Pw3Cc^mXI0hJoa@*GIqO%11QwO^LZD5e_wK6bvc7xRVm}y zpjWojv$kZA{fPF926E(@w`Hp;htoTnp?p1jcEA`kB&TjVv=L~RH(E{k4YYNZiWs)m z3jqQWI7}OuOIvW?Bm@VLcWr-p)C{%3hE8x3X-sFg)J~lt5NA3mf3EOJEPA+X+KH;E zmT!G*<91K%`q1|%U}D`2cA}@tc|M8mB3|q2BNG#H1;~bn+Mjdgg1_${kaZv>8)9PZ zZW!!2+I3`WBK|oh6_5bpno`m|)(P{W-d#hHa>3o$$fltPyyrzHm`?ZpOrgk7htEDg zz!v-iI)yd`JwlR32t-j*V=cyoj#OXgE>aS-*v0M3*9nVY zfBm4ZA%nRY4B?sm70d{`}6#S?*hT+uIsL%_IEp`TspD;D7sDAJ%DIHCbPC!vz=ae2DjG zE_PU34T9}q|=^8Y_1%YQB@zd_wjJSSW?#5_|DiMXqJft3Fc%*>HXvU5w5>Drc$|!Ct4s@q zgW#sl#^Is`+AQHtH_LWs;F1zu-gpY!V;CuN4$EBF4)FmRSDBMci+tj?qaT;$I<;e}x{CN~`2KzQD{E z;Pm>hWDe-pTffO|Mr#@X^W6=AhKH-&l~{Y|Y53qW6p{t7Ess`1bL82G7|qp+%@EBB z=YIDZVnd=T&{@?CJo?^L?5FWz-LuyxXD9v#4oDl%fL|7{s=$54xOE5V-$?|0H9R)m ze?N?2V6zOEo~T5g2KS7Qsb^?h?~Jh2Vs#!~O-CR8D>F)eyQ$rR=I3xmhn5ethA-Wi z>p$%FjWJ4?uTQody%I(l=>djNa&*~B?jHSYm+mH6>~5|#VlNb$$Mu5?xj@tRUkdQ{ zZfy!#@md4dDQcY|TH9-%w{qr!cGQr#>+GwGfEwF_j)=zIrx&v#lMwgmx+7o)`4N)( z!>xjn9=Qk=3_U*iGFJb_(<9TPxvVG-WrU~#Dbx4})UGE`I*CIjhN`vcU2mK|HFYP8 z4}~6_m>guEzt{aRa_(Lub`XoYX}xa<$j&$f0+-1MsgJAPgWUS$P`6N81r=e0hF*5@ zAZN6PmF**Z%$_~y4rWcAmzCINuf|y3gO#T>15hz%hc@J#4jki>J2%JO&z++xZxA4n zW6SjsmHAs&y9EfAs6YfmH+u1}&@uG+#U`&;tf&sbA#PS~2mQxalst>Ce<}EpZ{+Ng z%r*I9r)iVMd&_T(Q>1R}s>_L^doLpxrY)p&1|cCpQ(+(L-SmMGvI%RFD%3#MIOO$f za40ljeRAN3i`NYw8`QfBU&qW}L`n1nT9i9bjWT{^DHtUT6HjzW4~&t54?SIYUfIkq zFc^6EvcG@tGiTTCk&B8o(e++8&drnBK@%P~xv7RFO+R1pp0cP{4Wzi4eI7E`ymv3j znHw1_t0VlccGkQ)o-Cgl&M?w5V4uBw+|aawGq=R6y7(L*m{uW3nwQ3}`h0wwlE|aF zY*$M$;rQEDaJ1c~PZ!r|N1mHhtvSc7oOKiJd5Kcf4cDq4M(OIj0N3}wI^J}tZhA_8 z>r#l!c#@oyhnl)vnkqH|S3`=CTN8N1PHTT{LCUuKBb6+zWIOzQc2C@DypWZD)qqJJ z^4Cp*XGr9ltUaqKeE@^e#hKNGsGB%DH~%)lWiI?=PAtmmk!IYfx|e|o%Ag#MH1IMR zj&1S1Vts8-LD>r2x9|4+$wdcCz0v5>X@08!w!LJ}cUaYA^^vV6(#JP^$5vOUV+$;2 z>eY@GMBJZj0$^o>>WtzAATEd2Njidh`W`u9`!ztEYpQR=$I@d0wCif2ipfEZ>j*z8 zgJIu*?=Qdcs(1UrzL-j*KU>j`T;Uyeq$ekt{WBo|a)`QQJHZ7rqc|-r)6Afz6zxuQ zU|fu7zvKYysYFtebmqn3j3eb)eirM2b?DGuqs+HIaCVa^W4|K$7j~B5HQx(R zu$)EZc~5kQ-~`(+l|BSoB%Wg>*386_WRMfL$11fd?H9WlYwAvtdlL#^>T%J#5a7ho z)aYY_;?hg*TC5iL%dDWvyh%tfe1DC%_S+N}i#dqo=Lk_HjOdGT;TjFUYk7A$r5Rxzti9dMbiYixY^rXu#56GZrpxb)EE_XzDamriwT8;)0FJu`XUbxnEor~FmkK<-)7 z`a}10-;C zHNsasTxZbDxKn2DO^J%G!f))148{e1rgtpeX_h7@yqC&V+qvh4y2DK`=iccwI!IJT zX?_a`lQBSBpll3dw415D>Yc^t?2_pN-|L^fQC(Y8d=tO?7-rKHv%dU|K&7Olr>+hR zjB2fV#l&&Y8(MXVQzPMtQ|D*WO*8RiO0SV;HCLqt5C^PwhXr@~Ls+UHab$4^iIoUb zIL?B!Yq2WRa^*fE=aU9=1J=!NBo`1dnN<DmcMirKd+c z7|9)DYJ;REe+?-VK2iqjX3H&XZ6S`Cx7Ue`DejGXVScaX>g8UDPgil+$A>>QH(N4^ z4XyPD+!s26m4SmVAsLS!8MdBw`1TVmgYFh6!}_<;>PX6U_Kb(fz)S*I%R_A7y(s+R zOt)YB@)iMN@MYSh;h|}SY;Rw8VNCv?1biyjcn7xNAz3^s>&n6;8p@k_=i!bzSu#GK zpKj385j5+5jaJg8@Rj5le0^{f zk|z5nw?XCurnz32oo(0*-!{-94W)sjD5JdK?x7%|m)kIH%Ftu#b)KKf|@i_|A+frS*z;S3(|GRQf4i zyr@`b>U>F2+Q0Be;lS8{;38zc@QT`~uJYzbg(d8{aRb92BkoqFV3m9e?Lg0Oi`ZE3 z=2eoI?*$)1njX3iTp#Bd80xc?HbzcWyrL4J98+lWSjHsn;-@1gEhaVZ!abepSu07w zCBCvjV>&WNTDt}YI?JVW*otW(C%?ZaD-%(EBeXZO5B`kk{SYQU<>Eg_8sFgvb6?HC zg&9911*cJFT+A#+81=Aubko2K7=W^GEFn;OEPwBln@X8(&P>BWrTCXeue+uVWxRZq z4zwe9KuvGH@UPH^;;vHE!|5wTc3Nd9J*kkU-JL3((K70ttvae5d2SgsF;w@x{Pf_k z59#X9x!>Y57^V}8#K|IjE8@c0YM+db>TvI&&a$%RRU4x-t6JxbANS|Y|C>1Y$*IG z64xQn5tqTr1un3G*rkLyt)Y-~$WYHkzum?9u-z^`e=bld=NV`Ps2=QHS3s~#&7oPxU zrD_L_k@8`aaw4TUILr^%+FDiZ^*LT@&IjxQv0l_Kbqc`OQx^<|GuW@_+1T#t*VAWM zex=$|#4N^u>XKP=+GwhGta`M&noqy_nI~1|D&~V1#c#3zRM3N?#;$JHjCB@{C7wcA zd~HDl&Q$NKe%W#rk%zS486DC|0Jo$J18V6b>OQquK8*=1^w9wFch)m z;KD3pdec{JI-yGtHlx;##GfExrzJ9XQAd$=k;9@5ek|!8C>AFM2;__yvhmuhLJOc{n_(w;5(QkG8S7!tR~U!0EGK?sacm(>X_|Jc z{o>vEsD8)3U6BJ}9d`P68KI!PTo2nZyi005Su4&7fl#}5v+a#XG}th-xtaD3et<2K*7cIv~uy zW2M$oY|`J^;h3qkSa_4I-!i>Cs0AgyzXdKy}FTr1Ni`f4#d~kXh%xWN~w$yzsbc zrSM}$ioJ8O$|%trIX>l=^|a2aXiom>fV((X75ho^C~7Z1vk-B@*`x@$)HAI#%JXM{ zb&iiPz=~UTt;q`&X*X1q*Cb}6n&|u@{JpB*IRI_|p@JyYK$&ad z+Hz`Wi{!S03(lpPu;w5g+lq>{=&JL6@88s(lDys)yel)Jyq1YcuI1azMKNHY14^gJ8yh14B3dJ*A3wt=!TuH4n=9U{;89Z#y|QJuPxW zVsi2(`*BD?qt|}d=rOHh2=gj5jX{a<6R1rh6#)()+C$D6+Fw5OUNv9T_szIgj`NiE z2ZZ+hi>UDH&6ZE!v9HstsIbkQ4O&3;a5EO6QoZn-Sr@dJ+JKj8OowE{RU+jZ5?)`l zl1RHu1F2u!Z`*fRWY^oIZZl`L_;@u3#jRuwbrTK0wFI-3KINRlv*(65Z)51RJ#Jj| zN;k{d*(qO{yhtc};0TtL_-895-UV%Fyn_FUI{^4b!H>>DI#)qRmzyIzC+|Sk;+m+~ z^(FgZZ!)-QKGm(p*V`^+_V$bIz8uS_JMy0|UaxIwAwxzM{}oEW)8IGfp_(2&7&08I z&(8#GRy7rPr{k>a*lL{vvbG~Fn)IE7Jslsop6#{2o=s#>RnvZNt{|$@IO~5Y37?fa zuADu6MKmGHLl{tC8G*)84rIW_!i=H%a<J$bS3()8JEcDNmsY@=BCh? z$!iBXt@iFYgbJT_G0oY-Zw#PCdmKBD(uK`nK+eDP28+Y;pbCGrgm<5mcO=#&1~-Nu zOQ1}A@~EBKrIi-5=N}P^WBR7nwHT^H$Iy=H1W%&|Yct9-Z}MNvEJ(A-ry|js>Afz! zq6x`E$q!6=ko}z7 zp8T_+frNB}7d5^tjy!uaJDy#h8z>fTrf2lD7U%?fD+uhqDwkUF3nsi46S-`3FPku#x>T9w6 zId1OETcTolDe^ZQn`_pEwqd&e<(W^-831e_IefNWIN_SIG0f1V4*s z^J;gn_rHO~_^(+aMTAS;!!Zv|S;&~`o;~%VqvW$bWdI~hx(AU$`a>uhsHbckLl>)W zaX6t2>Co;>EDn5_Zg`CB_u5y@p{A}jr23u9gnr7Ghk-sd@>L6R*3>`!wPe&^{Cv~} zc2=jm3gRHLoW2#SuS<7zTGWe-WBA}jv#;8irZ8pFpL7<2d5xV`Y5#oGpy&VnGDkXf zjyH@>Tb;}IAm0qz90f zY7Ol{sUZ#yT@B0i*7ctz76)s8sj}I#z0)7!(`OSO2{GlrGxEe8;VH2-qrBJ-*!OI7 z9Bav3Px$3Vvz6!$IH3G`xh(GaJOk0-A&Q)RZ5=-SSLEZr4^^1uB8@pkTu-*>ZB|#& zOSb%{%sE;@r5cH~tcNB+{Z(5LyA+|7(#oog%b!nA8}t>NNOGHk4k#xx1G&8<7hUkC zRei;yK=ttzGDbO>2mUcu#n6j6QvU4NJ<3bLAgE?28Vw9{?5IPQ_k2Z?Ot^ssC-;2% z?N$`QPiwlHdpB;V)&HsPgl0s`({{CMh-1b&r}o<`_H;ldEbnl0*(*yOIz|TsN}#FhK6LB1@GEU`Ne!GoD5^rur=efb zX?$G1xzuprFtw;9MPPyx{MF#fow;aZ3Lqn^#~a0h6joX;d9tvK3#@D3RyJHf(R-G~ z@+POoMI)M>PVbnvMyg~^%_Ig9E)1wm-77q~g~v_+8CVp`zmn^5n>)nH>*<_69vPb8 zY0=0I!bx*dPaJrdy>c3A+*$Mf{M@I5?^9k5IMn;`Z;Lp)VA&LQsv5Lj3@1t9<9UZATqsELDSNXP3vq8LL3EL%|ENewoRX@WLDTh zwtX7Lf;eAgPh9O$dXdXA@Le27fFDJCdHKjT-iE3x6#t~}+MSgHO8AhU9i$0Sx?0!2 zLeZ3*!z^5vW|ZL>;75wO0x{4m=5aM%-REryRACw@iEg{?Qu$k+^35UN=JKz+u`~-! z<%+acN&9UPi>bcfQ-sCMZA5LY+j(q?(M%4FWo6ID0uV`mx87hYTRudlUpEoY z^qW@qPO~gNs>1J3uC46qEUP`%|JZ8VA?F@ClZ&NW@IqMY9$%SwOQz&cXL8l~2j3q5 z@L74R;Fz(OeX+K-N#;V#VT)pPvWP&Oizw=v4ABpJ_Yj_(nO zz^eqkIE77;0`xiQ6ZqUuTh=SC?=-m`BwWDaXdGe$5}O25Yv<&u6{6QTQ+> z9;=p%9`vXMB@$)1vJ6e&#m^e;;uhcHzIs}=7@UlBXp>ct`!?75O*yG3&0>C3Q^u{P z$ymnbxKj8Lw{Uw%2Z^gL+#w$4K>+uB0$8xftWQm2rG6TDJ9mrYmc4RdaWJH6&h*tA zs%C-foS75z)b&$g*-MLZca@lD&yXT*pdnoiQzYj6)XqdL{_JJz9j$Lf=(FOrn>0)? zCf>*s6opd&N&)-ECT>@e2hzJkL5_8I==BCN{RTPU?26n9%y#`$4F#XDk~DrwgZWsh zDdcH`Yjw?kFymbUb>7*gugm%lY~%LlwAcFTg$bIshFh-8c;;&N#Zx;yfn?>F{>c-QfU)gcEI1&O7}~EX43Y z0aS7P^nrau55Gc#D29_Q&-MLsxbfjmqvJ=Ra75)iC|j*h!R$_HTo3V|-T zx`VWVRh2v1d=8UH$_IMC0~VizZksv_Un19mTkM&G*+%lUGKxb8-C`ytk3&k z2u5v2N4w}2TC{i%QEe&q)Q?O|WadOy+EMW%lif=v-Z-Vc<>#3Mo1B%IKh$@icXuuf z2E$Mg#JT>drspmj2G+4>3Qpz4o)P+g`xLohdg^g2xH-sw`}VhjJc}lTKnNr!;GM@` z)>Ht0d$1~KHWIw{$#(*5!MkYuAPoP&ut%8XjC)j<9XDeR^MS_u$NQ7`j*7bkaG_X2 z*tPcnS4Wy(in&Jv6qemOm)xNaIr76RifPjfOP2w|`D3S(MVq0sisl-MNq0wXoKAfk z`UtM>W_;eq%sRrW;B%5_wv*$fu#x6tAC%@U1*J*GrH$>>JM##u6L)^qj*Tf+HVdjD zIXzYkELXJ?bQG=N`&&E_eUazG{y|wSvbta5yVZ0Hl51H!t-`GT>g>G0`fjO7RZ7TS zVOGhR{2hPuk#%4-Pco~6LPd1-dq|?JxizyYT*`eIoS`#X6;OCT5Pst61Z{$!(=Ksn zxWa~^4f4AB?CS+^jwS~RU~%u32sJ!J6hqQ!3BxMc7%=jPoYxeYL|ttCR^exh(9W`A zgMZgwxX#l3{cua-nyQoOp&NudtYCqt3M*^Y;nV7Ir51NKNKJv8`{e!BR%?)R=(@T=o3g|;1ip^a5#90y9q+OH;px*FW|t$U?OPHaQ^ zDjb!%xn@a>(W$q}8zt~0IhGzLkj-6jJAd;q5a7RojGWg72gy$zrv3srd(*vv-pWv! zv=632X^zSf4|ep2El(w@1w#*;y(G=VdWh)Dv(|flpHH7wX&p5@O@scfq(y_l8`a{z za)BJ2`jBTROd;u!w@> zt}&br4|W{k-Jc09A3#`+1gd9!)|`Vr##h(4WjR)&$5b2Mbb4OwoOl$&Ue3A9$D;y) zW;hnu-m8x&0#FajWd`$_xw=wCqRTa<+Y6|feU>SnKNCzIyfZt7|EH`?{xT_6`d;6N z^w~y}p<0C1=v(hVgyG%e;1kIfzY;=R%k)BTj;7!Jr!oYI1F$dg-BiocV>DL z@PPNz5>D1oooDk6zvKctm2<9zJX=Hdj3~SZuh>|+YH64Br5IJDn$&J8%Dk;UTK;3` zC7`J~d8fmuPBVHFk|+mHP46<=<;%$djkOrjEstCJ{*K@UtwY~HIqOzRb*|t^i9O2A zdus-rMlO%1XRwTT(nihzn%9F#pgMHoL|_W?!!5$a$Op3>)AEKO32xES?J+fC1NIh8 zY;zznSGjiL+ME?k@j5ZIq9RfxL+dR__uSYRzG-?u1wJuvJ=Xf8x+0YwXMMPuhH-ak z-XO*>9|h(G?Rdp zS5#;(IoylLy)dNI{VDadpXAYVf2DzRG^g!K8mKM>S=&XFw1(8mfMsStY}OBM{TS`F z$J`nI?;Q630zTa>1J0}hZVvO=f6MmSk|2mT^qBjR)nUyYW>K724HaINV6X3=$bTOh z^4%6Y!A96$JO6B7lBl}SuVUe2)q21iTE1Jj1^vX!fgnj(c~MpI z!M_Wf&x=64_Z3_p@3&L{b5qABLR6bpsSb=vKm~~i&!j{Ll*?OLIuh2vT1&8xnetGL z74Jl<_?2&$&R=)B{qgR3DV<%HrDxav+@>ZS5o(RYBro$eHqWYV!)Yt)VU)C{jjNjC zf-dLBMu%Hqd0bpKT8qu8nf*K)Wy4l&YVuutQgF~D?^9aZ6XzS?cl9+4T8vvZA=&4T zZn$y$&;5}k|NO@N|2uynsR#TiJyLqs3eKcD?|=VWSEaQ6BBCwpRyIgM5^-Arivo8< zQ^ z1crk*{72^Oqd)gYvix)Y<$q72G}W9Umv4s<7dD)KD~+Oe35JYV1&=72o1kM{0z)>Y z#Y|ZhV5YH8eXtzAA91kFuhbI`gP*vtk`!KW&eBTh!h=pq9tA4^@>7~ zAeD#gld`e>>pz)YwGI~`HK^=#fH)ce8SeL;B1!=z3uO%O;`nszj_iLmP#QD@vZHFi zI^E+NMQleK)B6;VXByo3SLg=vc{48IU!kRcg_!A^+8qFjzvhZz4%q?hIR%AEJ(2&> z9qA`&e7&QFcMULZ!E&EgK&Ss2R;K9NlwF#3<)S%*BlCTNku%AmS9^112xfDrXm_jE zVlxlDe?j&Fx!^}xegM!`HEs1b6yg`OsIYarb1r=ih^utBBni3lu`VB*zE&^S|5BZ3 z&5z~y*iz|9Ph77l=eV0PKOS$liF>z=Z&8sUHO=j(rM|Nz;mkZu&Yo%OF)fzCZ6zmL z&Sw#dO98xG9O#l8MU$j9<;MkJXYQqr_Wn-}IPr~Hx>e9mhqT}Fjj;NSPTO?qQpLbLmd7gJDgJ}bH% zJXRgD*D}~^M;<=#Fje673 zB*csI<^~}x@iw!u;o|kl`-5|Xi6e*%_l1RN-d50r`}6dLa`F^b!`C&*wW?2}-;F4* z47|thAIic4mLn&=6G`B*btjm9AmWlmA?M@mVF_>U#$(LD1LzU1im_;1^<;;_dEM+bFRPwIxmFz*> zR}Q}}WxaSh9U5zgIZNwDW`khmXLnrKjFT z@S2w#TEbPD>%tNm<|lhaj-CE||DWsv+|}0Ea^ga_WmX^i9p2vR>Pm{k{uy#)T3Xt# z)su$Y9;=Opf#P}GpDqX~lo9_QfgANm) z+bo~HCOI`u?4I!Vd-yv3$dA8z|6m1a6c(cWN@+zr-cTQJQ)k$1T*Gm#?AepKA3<|a zP0h$*5AGrTDS(Tl;V1mZYr9)_8L}e=$Ymf*CAP3_4f$|3YwPycjaJbPn;~Ew8LGFM zKhF8_Ql+XOQvL3@UYYWxJ|&3{cVgsP9cHSTIMz?jO991Dehe?JX;O#1lLmJ&CJo>J zSd)V8-+^l0kI-2Dt|ak)J_fGRML;R?L4V)QEqB@k((?A$JPy(jx#LwzAFwphZAea& zaHH}Yra}0LE2a|$qzs8!vCjh^iQdYaP}<;%Eu1>U@DEF+T7YHXW~pX*zSH&=P9D7` z!9iBdi`$ytkJ@B)<|uG8s!u9)QVp=tEtt|pIn;B`tI#~RA-~~?ynYVsb6&PhhWx%a z4-dsB!oC|S^)t?(K}%Tru>cpGG&sJ;EY300QERLDJ1Xf3Tj_HRVxlpx4nDXaCOhN7 z+(XAwuePUW4n=s4Dc6(nBK75sc(=nlCN21;I7Eh28s$TWp2SCMC!tf}A}1&g6)>Hg zlOr0NV%Jxw-RAN~zwre#?)=>4E;39NdqM40}k)#4Vx95*UOq
  • $jnY^X(Zgk^dq&1y#9ZcThy zdH_vPh=WT8Xx_n}Rx0_!>1PRD`#KK}Ewm%Hu!d;6;%L7b_QM*1j(~ znaegVw`!aQ&V-fJT|7{9IxiK}7rgc(W|-5IDr>6&?W$yqO=+Yu=L!%F4U1>2+HXP^ z3vh!26Ptu|&pFz6AYPpTl5GdT7*{hEZ*ZxNYKUWigf*i8A0$R~tfA60@FdPBw_O5U zTiW~-#;M*@@I4cIzneo3(LRpwvq&>J4n!%6{sU@M2PPb}HvoH-dwr>$zyTdR{>5E2 zjh-%0bub^(dD@}UR8hY7k%p7W^31@?s2#bM9(p=6W=1?7tveQAbZAj;tdbv25DTv8 zp-)-p>shsgpPh|!^x2QoPx|bnaJlN_XnyL=S5hzSDpfxJE0kvWWBVP^o!62|9xkb$ zMG_zJhId9{u|tzqflXmkyndjWwA{m%W#r_C8g-R>>_;M^oV_)0F<9Hm8j!%`lA{3p{UGqOSA6x2|xIkH%Z|qB99vi3&xGajeJTs&3WMRMO(~6s#!_% zVx~-Pepm3L(-@84qpPQ4{FZ5+@Q;Lx*G&&RJNC$~zItHv>IMy$vF(vlL{)EA=~uXG zZGEC8ak5fnjzv`mK)|T1+ScvDfls^>{2aqm$cb*tGSt117Kx&XU(=$EEbRnBq`paL zsSeC;vtpv%0*Zhj2reu5dtl3yS=<*TE2pG;I()Kg8* zMfzR=-29@tf|EKPZYhg^1C=j0YxIuVoX)X1mJt5Vd~^x3%LukABp}O0=ECS=5c{Sq z2r&H(37^7hhoPnh_d2c^{Ot+g@x3+3v@)!DdN_z_` zA9@2%Lm{T1r6MhEPI{ghv>FsN+9UXyBg6JiG~CPWF=eSm-(%qtw5=2tDaK=7grhx$ z(=E3?41T_LNTM$%s@V7|N6P;0sbX1Sim`9t3FV@utGLW*Ko}iv#q(r?V$q5wm5X|y zsCvy9n&=#BA9Jdw3v(2?V?R>0x3-U9sag(~#qFK{J9)x%EIRgK+Z&P`P7ZK|Cjt1M zFDSOZ0+uQKsXDUZd3Ae&C*8F0DIIgfV^Ow&vvtvF2>vX0qu=JKANDaj>}AgB6aIbn z^e+*z8}^MMMn0as>oDSIj0IBUD+QK(^&OUl4rhia_U$IcgZI@r9j%@{R7t`tU+&|Ps*RrhxzR6Rln3U zaN6_O1RqFIA9=)5y*n_}qa7fL3PTX`xp=(Xe0Ajl1yGNioNwZo*)+HW$NKyvFGsDs z_GwEU%4mJ*$O)g`Qe&Q^A2aePF_Z$lK}}|}S`T_iPK@^!xU1j?Uf(gB5`^zzknzTl;xS;?Jk;PJWVb%l*M3xWxMnubHn^w7Lv_M)Ut{`MTJ7!pAU?i~5XF=W{t+k%F<+Nsb|Q}rS9!pc?3o%K3_Na)T%qcsQ+yoo9E1aWL67MiB6t~zvop9>gt^CCK%#?ip$BugrP5-I0YH3&igNEV` zqpq`Y5r#*3+8_%BB%se?|_F7i?hk&{k&#(qiWLOFNl&+LLY z?I`_c`|a38Snu}>ON{L6J?&!;+CwdWj=&3c^n-ODILTjxDEr@vu)px5 zS7ajDDgYQr7GQws1T?fLry`{7T6;&ATp~6Yn6c_%TI)RFuCMW-_gt;Hoc5d2dp2!C zyvnZ|qlXJiU4H!z?3(+*qEe}*WGk&I$;&p^&VT87@qV|3zL0uOi|0A(qd~3>2yc8A zDY!XoQ}3*`O-ZqIaA+Yplsc8x8?=HB0-mP^AQ}CSF1QR7z(>6nUHE5ni75=xd=y}!UuD}UJCisfkVvjtj6qizKqc5ydJ z45i7I?ZinzRfqBXOWgztXE3%aZ3Hy3zzUWi$r*q~H0#yDvts)!0fvZzv zHqU@2cK68-?G``j4o!cKdR|#nT*ei5|5`tFeax!p3V5Y@c_w`3uSfS3gH)_%bbgEt zWkR7Gcth{HTOr49yPkUXvU0w{-H3eAa(?-0vulIZX6+m$h?+fF_=R_ra~ufC4`@6w ze#r!bNGe1k+V`5 zAa=PqH-W8thZ{x5MjFaTb#KL#Ik_YKyB(-J&a)m*@Bf3n_YP`m|KEM>iiikO1O!x? zO51d$Bq|~T8xR!`0z?I*#1N4dAS7Fq-lRrBh|*gKC4jVqj)?RUNTdr$PpE-}?6dZ{ z_jl&r-Gd z3Y31Y{E77*t}m$^e7p`1fDcd96ej|1skd|c@S9@t$A7x{Cg_L0`E-Y%o${3`!Y^oDzyj32CNNqW z-6dH`A{Q-zz#}LNdYk%ke~xBZ@nUr?;5wbOgY^3Opi=gE($)}HG_17-ONAJ3ldivK z<-G&LF<~HJzb^O2I|gD+8hN<3U}gfC{j=3gin_dgzY^bCYR)tVet74F2);(W`^TTB zf%P+lzP>X+2e%<2ttHO&ePO=w&$pd$c%sK*9)(u-MUTWudlfE~kKx~jBwRbE+G9E9 zTk!mrmIw&hqq9M*Q(yN@7@%&I+qz|z=M$5ha|;g!?UhMYBl``O+fJAYm*z13+aoO>WWf4JQj4iQ zm4Jt!oIanK3J&+!S`PQF+l_I8h~-ASQxkM{ej008`n_>BSt@cYGt-!1LG4tovE`5p zjD2x>wUb?ew81UVS*8f<7#lXgkw+39F$DGzp(`4QFbYRxpi-0BI|CTaGCmfKYh#D3 z#2*e&spp!m?7@$Top}jzj<*uSlFJAk&~T6f{ZtK|+$b4BlBCPM+a_?knM{j&Js^?# zoEu7o`k_?aRG;!ai}%7SH~z#FvmPZs>G)as1KB%!_U#n!MW$g(YB4q1mJsW)rr_-< zg!S=6=+YrZKGLtvFT&59?2NRA-WE94%Y*#&_25=@-Z6RfPHu3hum zHv9X~>sa!hG$hCtKCwaWLLWUy<=lXvUNH@3fQ5Y+xFRp4UX6~`A0h_n+@XF_JNVH_ot!7%y?Qh)khR4$YDz}|LZ z8E8@%(kLntj%@zkBY!VANVeMnyyfPs8u9q8QoqRDGKKBJ2)j)`8HQwK@Z-m|dH2Q!Z9B^ysfPdBUefa@W(k@GF&HC`vgDcuy)7lp_w*qwR7F zdp+Pv(th!_mFTTnUnw(xQGFIvzeXkZ<>dITuPW>thpSUTaW$IJKJ z5XlqOE?t=Nyhh1bkN^YQ3^NaR5NF!tF&(Gl!q$tk>-$jfpu&kI>L*6i1(N3AqEP3B z%N`rS)8Q8ZZS)rbiqQEE#2?jPkz>!36MyijTvV}(8P%PY($EmpP`tW9)+0_F zR85)yNubY@@Jh}H7+lXnJGcV6BF4~ZB546m9cBJy@);r~Vm~&nfEmyNp=17nv$eD$ z-jTlIwkalZq=R?GpC!R|WE!#_j3WozY8~EDHOTK|2a2!M zGskD*E>2YC$+W&Ud1d{mG?F@UGv(_0gM_Q>2ExYuk^h<5>w6wJe#Nlf?cTAkc6a|Y1 zt*xvmAIWnK#n|iRDI0G&Fw(B64ye{fX{UiU??*QuQ)?!RsPjfn@>L=t(ELp2FQd%f z2T@j4xE8bqiJ}Cbke8QNC%TrXr)g~L(2SH*rRBWqQ1#9owM%@ap3iiBH@O4DVp6Wz z=r*0_YZ3f5{n+I1Jo0EQ5FmmCM*?AC~!bVPAtJrr0Q`$(AIa*=SzV}53%D) z8-98gRnQdXo%lMF#Ka_Uk2JcE)!I@hmX+(1z393nov)qMwU`my7sl>N9E*=_z=Sef z+HeB8j=&Ba5uPv#{av*yAxyu6H0PYR;cj&t))@OzS0DIM9N(X1dFqnQ0tlj3*fA$O zSwU{+9gCahZIcv&O-K&DRKLN#j5o?=@;2_L6frJ)pdRIyOja$H{&YJxx#+1@|81ny zT(N|f`~3aO6eBc&9=Ezj-vn?pM0-k${Lz^`jeJ7h0KQUx+TMi2w|Z}X;#y7}@$KVt zX<8ZMPm}J4KCtY6@8RtOb<4T2d0Vd7&fmAcZGr^}tj>+dCt?-gkCy_q>vu*}>$Xi@ z*Qq0viORJ#8b*}U3O!tpn86%o3q(PIKE}zgNnSL6BQ^G|+ceG8w)f$%vT62?iTvVz zNX(~N)t5CjDJH(K0w@0@b(&>&$JqJHDZ&p{#s0XYJyp(%4p!A`5^O^$A7rz+7=#Xx z3Vre&>QN3d@d*>-CxM%}O58iMm^}^x&_Ql87IS;cbEU|)!qHPV9=7N;z-+Vff9C9z ztWWGunjpp@CQlZ!cwH_u1tn$u#+oOR;)-0_C(F#)=XYleSIStB<$Y4t?14+0W)}jtLBKvQ_!S!1m;>09 zf1-fmNHWOv4(;K2Qag2|_S_H4K;QHPC{@X04!1Su*GjV7EcyA!3dl;2@o*l_&baB| z#~BzLm>9U0ay33C`|9)4%vejGSjFD4w4ED(G1rChe0fH)W%Av`1%`R6p4o2e$+ihm zhT=km528xFB8{(n*_f!peahMLU7HkYS*qBR*kev1J|2qvbWw4~4sE&_u>K->rN+@Y z^SEaE`mhP9;5B}&s$pxmYMcfFRxZJ>VGdWB=?qrO#w7bnKjXq|MT|Oh< znw>ZD@q5aW((Z}M`5KLXs}eirVxag@x~l^RJNQ6$QgoSCj^UY%&pIK4S7_oJEgNXzZn)tZ;s-(e@Cy7#FSjblTfA+Cz*zZJ42VUgD^+C$7F zyDXnRfak+8Q;8W8wL>U>ObPoTvtcI2dWNSRTQ~ufyaFCui=qj+{?Mnxc%I64ceuk* z9~#4tx;Oq2=sUss3LWd^oPJZxh90Dllu-BS>k%Ab6tbEbl+9HP*X7Q$NBY^aY{dvf zjGLQn!)V~C_xI8SOGM^P0wd1L%)Sf2HTKdv>=@=NAdoV0ecC0m{(}1CnbGB4qrgID zKo8}K5j@2$uOfN-Md-x%Ylzk+t^A9~FHK#n>$S?vFooJ8FZj_*K9$u)u* zdmu8PrbcOZZq5`eot@>9Y1(m@>W4muY0^_bi?ClZFmW2V2r@tC$`bCJt_}hyoY^8j zxvoDeqR|?fs$Yas%&Ym--F$QdFR8RHUv`u7=X$?60;L=AhE;*f+au_nD1+IL?DH-& z$a;&C7C*g^UlW?hwUl2r?s$!&h*hrG3siN!3jJfA*z2cWu7~01R_kZbeL&F$+cp^v zKEqZiW~M=y7Do>Vx2s3g#SL=a)40QbLAn%;;h_7$LVjHS^ZB6$WAiT!6M@+6NA@l) zK%;I(BGA?#++-dRApUvKJFwxFt?6fDtWhApFsU-e$L)fxbnIKFAJt;cf8K2cQB5Y2 zQ_6mkXht>q!?I}$hYpVhiLGg zV`~o7o1FdB(gNZh+%n}h7+5DR{<)+5iLWUy!gNLW%tnN4$}QH9hYIfxpK8DWM@RLc zEN02)nOUu5VYDhUuhl`JbO67$zFy+(DpOTIP?A$Sur1~Z&%0B#D^&g`>!Ak3|EN~_ zv9?cDxF{f)TjD&^2F~!W_n(4>qYvYz=F@VPs7cy212UrNRXJXsFlQNJRrThbDCv=& zoRaM7CvWAyJKkDpF#pFCdHgVaeRVmP8Ov$`i2)?|JmzcHOWGmBoR}iF)WmNkZHfqD z6pLo$pqSMi*TZi(Z&-87N9GZ{$Z%zB-(dv(kOqyg)p=cHY5kpwvvyf?;{(89d`G*PE%QNCS#%mtz$buLL6>u6bLC zDk#j>={plJu|W|(4#CRVBS5)S4EXtIJmGNoS|Cb6)(E& zW(P>Bnq`G`_T;JPIH=Bc-E*_Mf+MGT{{Pgx|C<8?pKy*aS&Z|I1cq8mhQ{C)E&>=PFnLd4 zBVAK53a(PN6%E4j0`iFbCH@Y9MVaKD`M~bzv{Tg9oLA5?;Z`ceXW-;5G8Ae}Q zGU4t%-DOYj4O5TdH5pj1y!$o$hm}}0L+00`>sgn^y(BU^bn5F9MNN(08)xSbpMOfP zvZeK`^*RTMk5_uA&$*7d&txM+cK4Jul0YnPXOQGOI7MUk3A;sJ78uC5h`% zMBrqfGB+Pr(&x)&!{^hC?p6lFwT$Y>oI$v@$Z2&ff6L*-E@Vg!-=JkbMsR7f`vp-~12b z^}oZUIV3v38N3{m-B9p~-7v5b$}|1UdxJU2A#=tskL_o0#mV1-8^d<45h9UPtY#j+l<{}`-)^o3W@e5U)w2&Y-+>q5hT zR6}{_Rk@6D$d9`(Z$50&UwJ8U7L-OeXGg_jC`Onq*a-9;`X*9-=470%!L9af3T=lk(q=uk5M^@Won#m=V2Ugi$2#)>`_N#Y#4s=c)s zL8E(rBzb#&a>AuPwA$N5i<_s{OVKN4POi%5Pmm)~+%vo(7K_j`m6C_0VAfP;`Y=M{ zC~V&Tws^>RyW%v9e^pKQA(^T&S2AEmXu_O8vVgAOG(E>Q^l3(1^9_{B6gT-qF-5xy zt1*$|=dYO6>F>NFpOzDQ<9OtUiK*<6JdyBYH+OnNz(hk}g%P`(I#>OM?K8D5@)P-d zc}2U`R;Uu5PfGMmkuYrx8EuiZXs0yoL1K9%Ph(vF(cs0`HM$T-nafQRYG3JXlu@5> zqM|#^B1m>tK{xFUcUkD4SuupS8`T#@tM<|mkX+8gg}ObK4LrA~TrIBVLc7w>lCJMR zYcX>g4HI$py$N7v=qRim%B}0jsBTn)qMjr+rjmh`<>l#yz_zYwLt>q4`)7i>#UdBa zAe?3U6_!8i&)wrBvm?6t@BVP+gWAHa7ywb!7BK%d7e>|0DnUN`V(Ma6*$@e9kjahf z4)M5RrOcH8PS<}^<1cb?1l)|HN&(|WM_~7BS|dlB?ianLtKzdG{#=pUwrU7!^tFpu zcIwW`v&5^juqiga<3y�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 z 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�E2xP!gz=cvZ9*uexewwkiFBV^J1sc^d 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ν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Π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

    gseo$inl!?q^y*a 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 - - - QtSpim Help - qthelp://org.larusstone.qtspim.1.0/doc/qtspim_help.html - ../windows_images/NewIcon.ico - false - false - true - larusstone/qtspim - - About QtSpim - QtSpim is a self-contained simulator that will run a MIPS32 assembly program and display the processor's registers and memory. - - - - - - qtspim.qhp - qtspim.qch - - - - qtspim.qch - - - diff --git a/spim-qtbase/QtSpim/help/qtspim.qhp b/spim-qtbase/QtSpim/help/qtspim.qhp deleted file mode 100644 index 7665ca9..0000000 --- a/spim-qtbase/QtSpim/help/qtspim.qhp +++ /dev/null @@ -1,72 +0,0 @@ - - - org.larusstone.qtspim.1.0 - doc - - qtspim - -

    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - - - - *.html - *.jpg - - - diff --git a/spim-qtbase/QtSpim/help/qtspim_help.html b/spim-qtbase/QtSpim/help/qtspim_help.html deleted file mode 100644 index 3f4810b..0000000 --- a/spim-qtbase/QtSpim/help/qtspim_help.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - -QtSpim MIPS Simulator - - - - - -

    QtSpim

    -

    QtSpim is a self-contained simulator that will run a MIPS32 -assembly program and display the processor's registers -and memory.

    - -

    QtSpim reads and executes programs written in assembly language for -a MIPS computer. -QtSpim does not execute binary (compiled) programs. To simplify -programming, QtSpim provides a simple debugger and -small set of operating system services.

    - -

    QtSpim implements most of the MIPS32 assembler-extended instruction -set. (It omits the floating point comparisons and rounding modes and the memory -system page tables.) The MIPS architecture has several variants that differ in various -ways (e.g., the MIPS64 architecture supports 64-bit integers and addresses), which -means that QtSpim will not run programs for all MIPS processors.

    - -

    Getting Started with QtSpim

    -

    When QtSpim starts up, it opens a window containing that looks like -the one below. (The features in the window look slightly different on Microsoft -Windows than on Linux or Mac OSX, but all the menus and buttons are in the same place and work -the same way).

    -

    -

    - -

    -QtSpim Main Window

    - -

    QtSpim's main window has three parts:

    -
      -
    1. The narrow pane on the left can display integer or floating-point - registers. Select the set of registers by clicking the tab at the - top of the pane.
    2. -
    3. The wide pane on the right can display the text segment, which contains - instructions, and the data segments. Choose between text and data by - clicking the tab at the top of the pane.
    4. -
    5. The small pane on the bottom is where QtSpim writes its messages.
    6. -
    -All of the panes are dockable, which means that you can grab a pane by its top bar and -drag it out of QtSpim's main window, to put on some other part of your -screen. - -

    QtSpim also opens another window called Console that displays output from your program.

    - -

    Loading a Program

    - -

    Your program should be stored in a file. Assembly code files usually have the extension ".s", as in -file1.s. -To load a file, go to the File menu and select Load File. The -screen will change as the file is loaded, to show the -instructions and data in your program.

    - -

    Another very useful command on the File men is Reinitialize and Load File. It first clears all changes made by a program, -including deleting all of its instructions, and then reloads the last file. This command -works well when debugging a program, as -you can change your program and quickly test it in a fresh computer without closing and restarting QtSpim.

    - -

    Running a Program

    - -

    To start a program running after you have loaded it, go to the Simulator menu and click -Run/Continue. Your program will run -until it finishes or until an error occurs. Either way, you will see the changes that your program -made to the MIPS registers and -memory, and the output your program writes will appear in the Console window.

    - -

    If your program does not work correctly, there are several things you can do. The easiest is to single step between instructions, -which lets you see the changes each instructions makes, one at a time. This command is also on the -Simulator menu and is named -Single Step.

    - -

    Sometimes, however, you need to run your program for a while before something goes wrong, and single stepping would -be too slow. -QtSpim lets you set a breakpoint at a specific instruction, which stops QtSpim before the instruction executes. -So, if you think your problem is in a specific function in your program, set a breakpoint at the first instruction in the function, -and QtSpim will stop everytime the function is invoked.

    -

    You set a breakpoint by right-clicking on the instruction where you -want to stop, and selecting Set Breakpoint. When you are done with the breakpoint, you can remove it by selecting -Clear Breakpoint -instead.

    -

    If you want to stop your program while it is running, go to the Simulator menu and click -Pause. This command stops your program, let you look around, and continue execution if you want. If you do not want to continue -running, click Stop instead.

    -

    When QtSpim stops, either because of an error in your program, a breakpoint, after clicking -Pause, or after single stepping, you can continue the -program running by clicking on Run/Continue (or you can continue single stepping by clicking -Single Step). If you click Stop, -instead of Pause, then clicking Run/Continue will restart your program from the beginning, instead of continuing from where -it stopped. (This is roughly the same way that a music player operates; you can -pause and restart a song, but if you stop the music, you need to start playing -at the beginning.)

    - -

    Display Options

    - -

    The three other menus -- Registers, Text Segment, and -Data Segment -- control QtSpim's displays. For example, the -Register menu controls the way QtSpim displays the contents of registers, -either in binary, base 8 (octal), base 10 (decimal), or base 16 (hexadecimal). -It is often quite convenient to flip between these representations to understand -your data.

    - -

    These menus also let you turn off the display of various parts of the machine, which can help reduce clutter on the screen and -let you concentrate on the parts of the program or data that really matter.

    - -

    Changing Registers and Memory

    -

    You can change the contents of either a register or memory location by -right-clicking on it and selecting Change Register Contents or -Change Memory Contents, respectively.

    -

    Settings

    - -

    The Simulator menu contains the Settings command, which brings up a dialog like this:

    - -

    QtSpim settings dialog

    - -

    The dialog has two tabs. The first, shown above, changes the visual aspects of QtSpim, such as the fonts. -The second looks like this:

    -

    -QtSpim Settings Dialog

    -

    It changes the way that QtSpim operates:

    -
      -
    • Bare machine make QtSpim simulate a bare MIPS - processor.
    • -
    • Accept pseudo instructions enables QtSpim to - accept assembly instructions that MIPS does not actually execute, to make - programming easier.
    • -
    • Enable delayed branches causes QtSpim to execute - the instruction immediateyafter a branch instruction before transfering - control and to calculate the new PC - from the address of this next instruction.
    • -
    • Enable delayed loads causes QtSpim to delay the - value loaded from memory for one instruction after the load - instructions.
    • -
    • Enable mapped IO turns on memory-mapped IO.
    • -
    -

    The button marked Simple Machine enables the most common options (Accept -Pseudo Instructions) that are what most people use. The button marked -Bare -Machine turns on the instructions corresponding to a real MIPS processor (Bare -Machine, Delayed Branches, Delayed Loads).

    - - - diff --git a/spim-qtbase/QtSpim/help/settings_dialog.jpg b/spim-qtbase/QtSpim/help/settings_dialog.jpg deleted file mode 100644 index 81069d3628e8f905a2886fe02e7e4de49fa16c12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52497 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

    k>{KqAm0W-fqR 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

  • i*b39z| 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%0A>Z75GJ7Gz#w2M}{Q5T!c}CVzPL8;f~| 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ⓈZan_Nb6&Wl#vf8E3tC@(GEY~q;fxb4O3 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 CU6H&1 diff --git a/spim-qtbase/QtSpim/macinfo.plist b/spim-qtbase/QtSpim/macinfo.plist deleted file mode 100644 index 29b8525..0000000 --- a/spim-qtbase/QtSpim/macinfo.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundlePackageType - APPL - CFBundleIdentifier - com.larus.qtspim - CFBundleVersion - 9.1.23 - CFBundleSignature - ???? - CFBundleExecutable - QtSpim - NSPrincipalClass - NSApplication - NSHumanReadableCopyright - ???? - CFBundleIconFile - NewIcon - - diff --git a/spim-qtbase/QtSpim/main.cpp b/spim-qtbase/QtSpim/main.cpp deleted file mode 100644 index b9c676c..0000000 --- a/spim-qtbase/QtSpim/main.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include "spimview.h" - -static QStringList parseCommandLine(QStringList args); - - -SpimView* Window; -QApplication* App; - - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - QCoreApplication::setOrganizationName("LarusStone"); - QCoreApplication::setOrganizationDomain("larusstone.org"); - QCoreApplication::setApplicationName("QtSpim"); - - App = &a; - SpimView win; - Window = &win; - - // Initialize Spim - // - message_out.i = 1; - console_out.i = 2; - - win.SpimConsole->show(); - win.show(); - - QStringList fileNames = parseCommandLine(a.arguments()); - - win.sim_ReinitializeSimulator(); - - for (int i = 0; i < fileNames.length(); i++) - { - if (fileNames[i] != "") - { - read_assembly_file(fileNames[i].toLocal8Bit().data()); - } - } - - win.DisplayTextSegments(true); - win.UpdateDataDisplay(); - - a.setStyleSheet( -" QTabWidget::pane { /* The tab widget frame */" -" border-top: 2px solid #C2C7CB;" -" }" -"" -" QTabWidget::tab-bar {" -" left: 5px; /* move to the right by 5px */" -" }" -"" -" /* Style the tab using the tab sub-control. Note that" -" it reads QTabBar _not_ QTabWidget */" -" QTabBar::tab {" -" background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," -" stop: 0 #E1E1E1, stop: 0.4 #DDDDDD," -" stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);" -" border: 2px solid #C4C4C3;" -" border-bottom-color: #C2C7CB; /* same as the pane color */" -" border-top-left-radius: 4px;" -" border-top-right-radius: 4px;" -#ifdef _WIN32 -" min-width: 32ex;" -" padding: 2px;" -#else -" min-width: 8ex;" -" padding: 2px; padding-left:10px; padding-right:10px;" -#endif -" font: bold 12px" -" }" -"" -" QTabBar::tab:selected, QTabBar::tab:hover {" -" background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," -" stop: 0 #fafafa, stop: 0.4 #f4f4f4," -" stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);" -" }" -"" -" QTabBar::tab:selected {" -" border: 2px solid #FF9933;" -" border-bottom-color: #C2C7CB; /* same as pane color */" -" }" -"" -" QTabBar::tab:!selected {" -" margin-top: 2px; /* make non-selected tabs look smaller */" -" }" - ); - - return a.exec(); -} - - -static QStringList parseCommandLine(QStringList args) -{ - for (int i = 1; i < args.length(); i++) - { -#ifdef WIN32 - if (args[i][0] == '/') - { - args[i][0] = '-'; - } -#endif - if ((args[i] == "-asm") || (args[i] == "-a")) - { - bare_machine = false; - delayed_branches = false; - delayed_loads = false; - } - else if ((args[i] == "-bare") || (args[i] == "-b")) - { - bare_machine = true; - delayed_branches = true; - delayed_loads = true; - quiet = true; - } - else if ((args[i] == "-delayed_branches") || (args[i] == "-db")) - { - delayed_branches = true; - } - else if ((args[i] == "-delayed_loads") || (args[i] == "-dl")) - { - delayed_loads = true; - } - else if ((args[i] == "-exception") || (args[i] == "-e")) - { - Window->SetExceptionHandler("", true); - } - else if ((args[i] == "-noexception") || (args[i] == "-ne")) - { - Window->SetExceptionHandler("", false); - } - else if ((args[i] == "-exception_file") || (args[i] == "-ef")) - { - Window->SetExceptionHandler(args[++i], true); - } - else if ((args[i] == "-mapped_io") || (args[i] == "-mio")) - { - mapped_io = true; - } - else if ((args[i] == "-nomapped_io") || (args[i] == "-nmio")) - { - mapped_io = false; - } - else if ((args[i] == "-pseudo") || (args[i] == "-p")) - { - accept_pseudo_insts = true; - } - else if ((args[i] == "-nopseudo") || (args[i] == "-np")) - { - accept_pseudo_insts = false; - } - else if ((args[i] == "-quiet") || (args[i] == "-q")) - { - quiet = true; - } - else if ((args[i] == "-noquiet") || (args[i] == "-nq")) - { - quiet = false; - } - else if ((args[i] == "-trap") || (args[i] == "-t")) - { - Window->SetExceptionHandler("", true); - } - else if ((args[i] == "-notrap") || (args[i] == "-nt")) - { - Window->SetExceptionHandler("", false); - } - else if ((args[i] == "-trap_file") || (args[i] == "-tf")) - { - Window->SetExceptionHandler(args[++i], true); - } - else if ((args[i] == "-stext") || (args[i] == "-st")) - { - initial_text_size = args[++i].toInt(); - } - else if ((args[i] == "-sdata") || (args[i] == "-sd")) - { - initial_data_size = args[++i].toInt(); - } - else if ((args[i] == "-ldata") || (args[i] == "-ld")) - { - initial_data_limit = args[++i].toInt(); - } - else if ((args[i] == "-sstack") || (args[i] == "-ss")) - { - initial_stack_size = args[++i].toInt(); - } - else if ((args[i] == "-lstack") || (args[i] == "-ls")) - { - initial_stack_limit = args[++i].toInt(); - } - else if ((args[i] == "-sktext") || (args[i] == "-skt")) - { - initial_k_text_size = args[++i].toInt(); - } - else if ((args[i] == "-skdata") || (args[i] == "-skd")) - { - initial_k_data_size = args[++i].toInt(); - } - else if ((args[i] == "-lkdata") || (args[i] == "-lkd")) - { - initial_k_data_limit = args[++i].toInt(); - } - else if ((args[i] == "-file") || (args[i] == "-f")) - { - return args.mid(i+1); - } - else if (args[i][0] != '-') - { - return args.mid(i); - } - else - { - error ("Unknown argument: %s (ignored)\n\n\ - Usage: QtSpim\n\ - -bare Bare machine (no pseudo-ops, delayed branches and loads)\n\ - -asm Extended machine (pseudo-ops, no delayed branches and loads) (default)\n\ - -delayed_branches Execute delayed branches\n\ - -delayed_loads Execute delayed loads\n\ - -exception Load exception handler (default)\n\ - -noexception Do not load exception handler\n\ - -exception_file Specify exception handler in place of default\n\ - -quiet Do not print warnings\n\ - -noquiet Print warnings (default)\n\ - -mapped_io Enable memory-mapped IO\n\ - -nomapped_io Do not enable memory-mapped IO (default)\n\ - -file ... Assembly code file(s)\n\ - \n\ - If argument does not start with a '-', it and all subsequent arguments are file names.\n", - args[i].toLocal8Bit().data()); - } - } - return QStringList(); -} diff --git a/spim-qtbase/QtSpim/menu.cpp b/spim-qtbase/QtSpim/menu.cpp deleted file mode 100644 index 6811bf1..0000000 --- a/spim-qtbase/QtSpim/menu.cpp +++ /dev/null @@ -1,875 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2017, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spimview.h" -#include "ui_savelogfile.h" -#include "ui_printwindows.h" -#include "ui_runparams.h" -#include "ui_settings.h" -#include "ui_breakpoint.h" -#include "spim_settings.h" -#include "version.h" - - -#include -#define QT_USE_FAST_CONCATENATION -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// -// Menu functions -// - - - -// File menu -// - -void SpimView::file_LoadFile() -{ - QString file; - if (((QAction*)sender())->objectName() != "action_File_Load" - && ((QAction*)sender())->objectName() != "action_File_Reload") - { - file = ((QAction*)sender())->text(); // Recent file menu entry's names are file names - } - else - { - file = QFileDialog::getOpenFileName(this, - "Open Assembly Code", - st_recentFiles[0], - "Assembly (*.a *.s *.asm);;Text files (*.txt)"); - } - if (!file.isNull()) - { - read_assembly_file(file.toLocal8Bit().data()); - st_recentFiles.removeAll(file); - st_recentFiles.prepend(file); - rebuildRecentFilesMenu(); - - DisplayTextSegments(true); - DisplayDataSegments(false); - } -} - - -void SpimView::file_ReloadFile() -{ - sim_ReinitializeSimulator(); - file_LoadFile(); -} - - -void SpimView::rebuildRecentFilesMenu() -{ - ui->menuRecent_Files->clear(); - int i; - for (i = 0; i < st_recentFilesLength; i++) - { - QAction* action = ui->menuRecent_Files->addAction(st_recentFiles[i]); - QObject::connect(action, SIGNAL(triggered(bool)), this, SLOT(file_LoadFile())); - } -} - - -void SpimView::file_SaveLogFile() -{ - static QDialog* saveLogFileDialog; - static Ui::SaveLogFileDialog* slf; - - if (saveLogFileDialog == NULL) - { - saveLogFileDialog = new QDialog(); - slf = new Ui::SaveLogFileDialog(); - slf->setupUi(saveLogFileDialog); - - QFileDialog* fb = new QFileDialog(0, - "Save To Log File", - "", - "Text files (*.txt);; All (*)"); - QObject::connect(slf->saveFileToolButton, SIGNAL(clicked()), fb, SLOT(exec())); - QObject::connect(fb, SIGNAL(fileSelected(QString)), slf->SaveLineEdit, SLOT(setText(QString))); - } - - if (saveLogFileDialog->exec() == QDialog::Accepted) - { - if (!slf->SaveLineEdit->text().isNull()) - { - QFile file(slf->SaveLineEdit->text()); - file.open(QIODevice::WriteOnly | QIODevice::Truncate); - QTextStream outFile(&file); - - if (slf->RegsCheckBox->isChecked()) - { - outFile << ui->IntRegDockWidget->findChild("IntRegTextEdit")->toPlainText(); - outFile << "\n\n"; - } - if (slf->TextCheckBox->isChecked()) - { - outFile << ui->TextSegDockWidget->findChild("TextSegmentTextEdit")->toPlainText(); - outFile << "\n\n"; - } - if (slf->DataCheckBox->isChecked()) - { - outFile << ui->DataSegDockWidget->findChild("DataSegmentTextEdit")->toPlainText(); - outFile << "\n\n"; - } - if (slf->ConsoleCheckBox->isChecked()) - { - outFile << SpimConsole->toPlainText(); - } - - file.close(); - } - } -} - - -void SpimView::file_Print() -{ - static QDialog* printFileDialog; - static Ui::PrintWindowsDialog* pwd; - - if (printFileDialog == NULL) - { - printFileDialog = new QDialog(); - pwd = new Ui::PrintWindowsDialog(); - pwd->setupUi(printFileDialog); - } - - if (printFileDialog->exec() == QDialog::Accepted) - { - QPrinter printer; - QPrintDialog printDialog(&printer, this); - printDialog.setWindowTitle("Print Windows"); - - if (printDialog.exec() == QDialog::Accepted) - { - - if (pwd->RegsCheckBox->isChecked()) - { - ui->IntRegDockWidget->findChild("IntRegTextEdit")->print(&printer); - } - if (pwd->TextCheckBox->isChecked()) - { - ui->TextSegDockWidget->findChild("TextSegmentTextEdit")->print(&printer); - } - if (pwd->DataCheckBox->isChecked()) - { - ui->DataSegDockWidget->findChild("DataSegmentTextEdit")->print(&printer); - } - if (pwd->ConsoleCheckBox->isChecked()) - { - SpimConsole->print(&printer); - } - } - } -} - - -void SpimView::file_Exit() -{ -#if 0 - QMessageBox msgBox(QMessageBox::Question, "Exit", "Exit?", QMessageBox::Ok | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Ok); - if (msgBox.exec()) - { - this->SaveStateAndExit(0); - } -#endif - this->SaveStateAndExit(0); -} - - - -// Simulator menu -// - -void SpimView::sim_ClearRegisters() -{ - initialize_registers(); - - DisplayIntRegisters(); - DisplayFPRegisters(); -} - - -void SpimView::sim_ReinitializeSimulator() -{ - write_output(message_out, "
    Memory and registers cleared\n\n"); - InitializeWorld(); - SpimConsole->Clear(); - initStack(); - - SetOutputColor("green"); - write_startup_message(); - write_output(message_out, - "QtSPIM is linked to the Qt library, which is distributed under the GNU Lesser General Public License version 3 and version 2.1.\n"); - SetOutputColor("black"); - - CaptureIntRegisters(); - CaptureSFPRegisters(); - CaptureDFPRegisters(); - - DisplayTextSegments(true); - UpdateDataDisplay(); - - // Scroll to top of windows - // - regTextEdit* rte = ui->IntRegDockWidget->findChild("IntRegTextEdit"); - rte->verticalScrollBar()->setValue(rte->verticalScrollBar()->minimum()); - rte = ui->FPRegDockWidget->findChild("FPRegTextEdit"); - rte->verticalScrollBar()->setValue(rte->verticalScrollBar()->minimum()); - textTextEdit* tte = ui->TextSegDockWidget->findChild("TextSegmentTextEdit"); - tte->verticalScrollBar()->setValue(tte->verticalScrollBar()->minimum()); - dataTextEdit* dte = ui->DataSegDockWidget->findChild("DataSegmentTextEdit"); - dte->verticalScrollBar()->setValue(dte->verticalScrollBar()->minimum()); -} - - -void SpimView::sim_SetRunParameters() -{ - QDialog d; - Ui::SetRunParametersDialog srp; - srp.setupUi(&d); - - // Default values: - // - srp.addressLineEdit->setText(QString("0x") + formatAddress(st_startAddress)); - srp.argsLineEdit->setText(st_commandLine); - - if (d.exec() == QDialog::Accepted) - { - if (!srp.addressLineEdit->text().isNull()) - { - bool ok; - st_startAddress = srp.addressLineEdit->text().toInt(&ok, 0); - } - if (!srp.argsLineEdit->text().isNull()) - { - st_commandLine = srp.argsLineEdit->text(); - } - } -} - - -void SpimView::sim_Run() -{ - initializePCAndStack(); - - force_break = false; - updateStatus(RUNNING); - while (!force_break && programStatus == RUNNING) - { - executeProgram(PC, 100000, false, false); - App->processEvents(); // Check for events in midst of long computation - } - updateStatus(IDLE); - UpdateDataDisplay(); -} - - -void SpimView::sim_Pause() -{ - force_break = true; - updateStatus(PAUSED); - UpdateDataDisplay(); -} - - -void SpimView::sim_Stop() -{ - force_break = true; - updateStatus(STOPPED); - UpdateDataDisplay(); -} - - -void SpimView::sim_SingleStep() -{ - initializePCAndStack(); - - force_break = false; - updateStatus(SINGLESTEP); - executeProgram(PC, 1, false, false); - UpdateDataDisplay(); -} - - -void SpimView::initializePCAndStack() -{ - if ((programStatus == STOPPED && !force_break) || PC == 0) - { - if (st_startAddress == 0) - { - st_startAddress = starting_address(); - } - PC = st_startAddress; - initStack(); - } -} - - -void SpimView::initStack() -{ - // Prepend file name to arg list - // - initialize_stack((st_recentFiles[0] + " " + st_commandLine).toLocal8Bit().data()); -} - - -void SpimView::updateStatus(PROGSTATE status) -{ - programStatus = status; - switch (programStatus) - { - case IDLE: - Window->statusBar()->showMessage(""); - break; - - case STOPPED: - Window->statusBar()->showMessage("Stopped"); - break; - - case PAUSED: - Window->statusBar()->showMessage("Paused"); - break; - - case RUNNING: - Window->statusBar()->showMessage("Running"); - break; - - case SINGLESTEP: - Window->statusBar()->showMessage("Single Step"); - break; - - default: - Window->statusBar()->showMessage("?"); - break; - } -} - - -void SpimView::executeProgram(mem_addr pc, int steps, bool display, bool contBkpt) -{ - bool continuable; - bool breakpointEncountered = run_program(pc, steps, display, contBkpt, &continuable); - - highlightInstruction(PC); - - if (breakpointEncountered) - { - static QDialog* breakpointDialog; - static Ui::BreakpointDialog* bpd; - - if (bpd == NULL) - { - breakpointDialog = new QDialog(); - bpd = new Ui::BreakpointDialog(); - bpd->setupUi(breakpointDialog); - - connect(bpd->continuePushButton, SIGNAL(clicked()), this, SLOT(continueBreakpoint())); - connect(bpd->singleStepPushButton, SIGNAL(clicked()), this, SLOT(singleStepBreakpoint())); - connect(bpd->abortPushButton, SIGNAL(clicked()), this, SLOT(abortBreakpoint())); - } - bpd->label->setText("Execution stopped at breakpoint at " + QString("0x") + formatAddress(PC)); - breakpointDialog->show(); - } - else if (!continuable) - { - updateStatus(STOPPED); - } -} - - -void SpimView::continueBreakpoint() -{ - bool continuable; - run_program(PC, 1, false, true, &continuable); // Execute instruction replaced by breakpoint - highlightInstruction(PC); - UpdateDataDisplay(); - updateStatus((continuable == 1) ? RUNNING : STOPPED); -} - - -void SpimView::singleStepBreakpoint() -{ - bool continuable; - run_program(PC, 1, false, true, &continuable); // Execute instruction replaced by breakpoint - highlightInstruction(PC); - UpdateDataDisplay(); - updateStatus((continuable == 1) ? SINGLESTEP : STOPPED); -} - - -void SpimView::abortBreakpoint() -{ - updateStatus(STOPPED); -} - - -void SpimView::sim_DisplaySymbols() -{ - WriteOutput("
    "); - print_symbols(); -} - - -void SpimView::sim_Settings() -{ - QDialog d; - Ui::SpimSettingDialog sd; - sd.setupUi(&d); - - sd.bareMachineCheckBox->setChecked(bare_machine); - sd.pseudoInstCheckBox->setChecked(accept_pseudo_insts); - sd.delayedBranchCheckBox->setChecked(delayed_branches); - sd.delayedLoadCheckBox->setChecked(delayed_loads); - sd.mappedIOCheckBox->setChecked(mapped_io); - - QObject::connect(sd.simplePushButton, SIGNAL(clicked()), sd.bareMachineCheckBox, SLOT(unset())); - QObject::connect(sd.simplePushButton, SIGNAL(clicked()), sd.pseudoInstCheckBox, SLOT(set())); - QObject::connect(sd.simplePushButton, SIGNAL(clicked()), sd.delayedBranchCheckBox, SLOT(unset())); - QObject::connect(sd.simplePushButton, SIGNAL(clicked()), sd.delayedLoadCheckBox, SLOT(unset())); - QObject::connect(sd.barePushButton, SIGNAL(clicked()), sd.bareMachineCheckBox, SLOT(set())); - QObject::connect(sd.barePushButton, SIGNAL(clicked()), sd.pseudoInstCheckBox, SLOT(unset())); - QObject::connect(sd.barePushButton, SIGNAL(clicked()), sd.delayedBranchCheckBox, SLOT(set())); - QObject::connect(sd.barePushButton, SIGNAL(clicked()), sd.delayedLoadCheckBox, SLOT(set())); - - sd.loadExceptionHandlerCheckBox->setChecked(st_loadExceptionHandler); - sd.exceptionHandlerLineEdit->setText(st_exceptionHandlerFileName); - QFileDialog exceptionFileDialog(0, - "Open Exception File", - st_exceptionHandlerFileName, - "Assembly (*.a *.s *.asm);;Text files (*.txt)"); - QObject::connect(sd.exceptionHandlerToolButton, SIGNAL(clicked()), &exceptionFileDialog, SLOT(exec())); - - // Mapper from exceptionHandlerResetButton clicked() SIGNAL to exceptionHandlerLineEdit setText() SLOT - QSignalMapper *exceptionHandlerResetButtonMapper = new QSignalMapper(); - // Connect exceptionHandlerResetButtonMapper to exceptionHandlerLineEdit - QObject::connect(exceptionHandlerResetButtonMapper, SIGNAL(mapped(const QString&)), - sd.exceptionHandlerLineEdit, SLOT(setText(const QString&))); - // Connect exceptionHandlerResetButton to exceptionHandlerResetButtonMapper - QObject::connect(sd.exceptionHandlerResetButton, SIGNAL(clicked()), exceptionHandlerResetButtonMapper, SLOT(map())); - // Set QString signal to emit when exceptionHandlerResetButton clicked - exceptionHandlerResetButtonMapper->setMapping(sd.exceptionHandlerResetButton, stdExceptionHandler); - QObject::connect(&exceptionFileDialog, SIGNAL(fileSelected(QString)), - sd.exceptionHandlerLineEdit, SLOT(setText(QString))); - - sd.recentFilesLineEdit->setText(QString::number(st_recentFilesLength, 10)); - sd.quietCheckBox->setChecked(quiet); - - sd.regWinFontLineEdit->setText(st_regWinFont.family()); - QFontDialog* regWinFontDialog = new QFontDialog(st_regWinFont); - QObject::connect(sd.regWinFontToolButton, SIGNAL(clicked()), regWinFontDialog, SLOT(exec())); - QObject::connect(regWinFontDialog, SIGNAL(fontSelected(QFont)), &sd, SLOT(setRegWinFont(QFont))); - - sd.regWinFontColorLineEdit->setText(st_regWinFontColor.name()); - QColorDialog* regWinColorDialog = new QColorDialog(st_regWinFontColor); - QObject::connect(sd.regWinFontColorToolButton, SIGNAL(clicked()), regWinColorDialog, SLOT(exec())); - QObject::connect(regWinColorDialog, SIGNAL(colorSelected(QColor)), &sd, SLOT(setRegWinColor(QColor))); - - sd.regWinBackgroundLineEdit->setText(st_regWinBackgroundColor.name()); - QColorDialog* regWinBackgroundDialog = new QColorDialog(st_regWinBackgroundColor); - QObject::connect(sd.regWinBackgroundToolButton, SIGNAL(clicked()), regWinBackgroundDialog, SLOT(exec())); - QObject::connect(regWinBackgroundDialog, SIGNAL(colorSelected(QColor)), &sd, SLOT(setRegWinBackground(QColor))); - - sd.textWinFontLineEdit->setText(st_textWinFont.family()); - QFontDialog* textWinFontDialog = new QFontDialog(st_textWinFont); - QObject::connect(sd.textWinFontToolButton, SIGNAL(clicked()), textWinFontDialog, SLOT(exec())); - QObject::connect(textWinFontDialog, SIGNAL(fontSelected(QFont)), &sd, SLOT(setTextWinFont(QFont))); - - sd.textWinFontColorLineEdit->setText(st_textWinFontColor.name()); - QColorDialog* textWinColorDialog = new QColorDialog(st_textWinFontColor); - QObject::connect(sd.textWinFontColorToolButton, SIGNAL(clicked()), textWinColorDialog, SLOT(exec())); - QObject::connect(textWinColorDialog, SIGNAL(colorSelected(QColor)), &sd, SLOT(setTextWinColor(QColor))); - - sd.textWinBackgroundLineEdit->setText(st_textWinBackgroundColor.name()); - QColorDialog* textWinBackgroundDialog = new QColorDialog(st_textWinBackgroundColor); - QObject::connect(sd.textWinBackgroundToolButton, SIGNAL(clicked()), textWinBackgroundDialog, SLOT(exec())); - QObject::connect(textWinBackgroundDialog, SIGNAL(colorSelected(QColor)), &sd, SLOT(setTextWinBackground(QColor))); - - if (d.exec() == QDialog::Accepted) - { - bare_machine = sd.bareMachineCheckBox->isChecked(); - accept_pseudo_insts = sd.pseudoInstCheckBox->isChecked(); - delayed_branches = sd.delayedBranchCheckBox->isChecked(); - delayed_loads = sd.delayedLoadCheckBox->isChecked(); - mapped_io = sd.mappedIOCheckBox->isChecked(); - - st_loadExceptionHandler = sd.loadExceptionHandlerCheckBox->isChecked(); - st_exceptionHandlerFileName = sd.exceptionHandlerLineEdit->text(); - - st_recentFilesLength = sd.recentFilesLineEdit->text().toInt(); - quiet = sd.quietCheckBox->isChecked(); - if (st_recentFilesLength <= 0 || st_recentFilesLength > 20) - { - st_recentFilesLength = 4; - } - - if (sd.regWinFont != NULL) - { - st_regWinFont = *sd.regWinFont; - } - if (sd.regWinColor != NULL) - { - st_regWinFontColor = *sd.regWinColor; - } - if (sd.regWinBackground != NULL) - { - st_regWinBackgroundColor = *sd.regWinBackground; - } - - if (sd.textWinFont != NULL) - { - st_textWinFont = *sd.textWinFont; - } - if (sd.textWinColor != NULL) - { - st_textWinFontColor = *sd.textWinColor; - } - if (sd.textWinBackground != NULL) - { - st_textWinBackgroundColor = *sd.textWinBackground; - } - - DisplayTextSegments(true); - UpdateDataDisplay(); - } -} - - -// Registers menu -// - -void SpimView::reg_DisplayBinary() -{ - st_regDisplayBase = 2; - setCheckedRegBase(st_regDisplayBase); - DisplayIntRegisters(); - DisplayFPRegisters(); -} - - -void SpimView::reg_DisplayDecimal() -{ - st_regDisplayBase = 10; - setCheckedRegBase(st_regDisplayBase); - DisplayIntRegisters(); - DisplayFPRegisters(); -} - - -void SpimView::reg_DisplayHex() -{ - st_regDisplayBase = 16; - setCheckedRegBase(st_regDisplayBase); - DisplayIntRegisters(); - DisplayFPRegisters(); -} - - -int SpimView::setCheckedRegBase(int base) -{ - return setBaseInternal(base, - ui->action_Reg_DisplayBinary, - ui->action_Reg_DisplayDecimal, - ui->action_Reg_DisplayHex); -} - - -int SpimView::setBaseInternal(int base, QAction* actionBinary, QAction* actionDecimal, QAction* actionHex) -{ - actionBinary->setChecked(false); - actionDecimal->setChecked(false); - actionHex->setChecked(false); - - switch (base) - { - case 2: - actionBinary->setChecked(true); - return base; - - case 10: - actionDecimal->setChecked(true); - return base; - - case 16: - actionHex->setChecked(true); - return base; - - default: - actionHex->setChecked(true); - return 16; - } -} - - -// Text menu -// - -void SpimView::text_DisplayUserText() -{ - bool changed = st_showUserTextSegment == ui->action_Text_DisplayUserText->isChecked(); - st_showUserTextSegment = ui->action_Text_DisplayUserText->isChecked(); - DisplayTextSegments(changed); -} - - -void SpimView::text_DisplayKernelText() -{ - bool changed = st_showKernelTextSegment == ui->action_Text_DisplayKernelText->isChecked(); - st_showKernelTextSegment = ui->action_Text_DisplayKernelText->isChecked(); - DisplayTextSegments(changed); -} - - -void SpimView::text_DisplayComments() -{ - bool changed = st_showTextComments == ui->action_Text_DisplayComments->isChecked(); - st_showTextComments = ui->action_Text_DisplayComments->isChecked(); - DisplayTextSegments(changed); -} - - -void SpimView::text_DisplayInstructionValue() -{ - bool changed = st_showTextDisassembly == ui->action_Text_DisplayInstructionValue->isChecked(); - - st_showTextDisassembly = ui->action_Text_DisplayInstructionValue->isChecked(); - DisplayTextSegments(changed); -} - - - -// Data menu -// - -void SpimView::data_DisplayUserData() -{ - st_showUserDataSegment = ui->action_Data_DisplayUserData->isChecked(); - DisplayDataSegments(true); -} - - -void SpimView::data_DisplayUserStack() -{ - st_showUserStackSegment = ui->action_Data_DisplayUserStack->isChecked(); - DisplayDataSegments(true); -} - - -void SpimView::data_DisplayKernelData() -{ - st_showKernelDataSegment = ui->action_Data_DisplayKernelData->isChecked(); - DisplayDataSegments(true); -} - - -void SpimView::data_DisplayBinary() -{ - st_dataSegmentDisplayBase = 2; - setCheckedDataSegmentDisplayBase(st_dataSegmentDisplayBase); - DisplayDataSegments(true); -} - - -void SpimView::data_DisplayDecimal() -{ - st_dataSegmentDisplayBase = 10; - setCheckedDataSegmentDisplayBase(st_dataSegmentDisplayBase); - DisplayDataSegments(true); -} - - -void SpimView::data_DisplayHex() -{ - st_dataSegmentDisplayBase = 16; - setCheckedDataSegmentDisplayBase(st_dataSegmentDisplayBase); - DisplayDataSegments(true); -} - - -int SpimView::setCheckedDataSegmentDisplayBase(int base) -{ - return setBaseInternal(base, - ui->action_Data_DisplayBinary, - ui->action_Data_DisplayDecimal, - ui->action_Data_DisplayHex); -} - - -// Window menu -// - -void winUpDown(QObject* sender, QWidget* widget) -{ - QAction* act = (QAction*)sender; - if (act->isChecked()) - { - widget->show(); - } - else - { - widget->hide(); - } -} - - -void SpimView::win_IntRegisters() -{ - winUpDown(sender(), ui->IntRegDockWidget); -} - - -void SpimView::win_FPRegisters() -{ - winUpDown(sender(), ui->FPRegDockWidget); -} - - -void SpimView::win_TextSegment() -{ - winUpDown(sender(), ui->TextSegDockWidget); -} - - -void SpimView::win_DataSegment() -{ - winUpDown(sender(), ui->DataSegDockWidget); -} - - -void SpimView::win_Console() -{ - winUpDown(sender(), SpimConsole); -} - - -void SpimView::win_Tile() -{ - ui->IntRegDockWidget->show(); - ui->action_Win_IntRegisters->setChecked(true); - ui->FPRegDockWidget->show(); - ui->action_Win_FPRegisters->setChecked(true); - ui->TextSegDockWidget->show(); - ui->action_Win_TextSegment->setChecked(true); - ui->DataSegDockWidget->show(); - ui->action_Win_DataSegment->setChecked(true); - - ui->IntRegDockWidget->setFloating(false); - ui->FPRegDockWidget->setFloating(false); - tabifyDockWidget(ui->FPRegDockWidget, ui->IntRegDockWidget); - ui->TextSegDockWidget->setFloating(false); - ui->DataSegDockWidget->setFloating(false); - tabifyDockWidget(ui->DataSegDockWidget, ui->TextSegDockWidget); -} - - -// Help menu -// - -void SpimView::help_ViewHelp() -{ - QProcess *process = new QProcess; - QStringList args; - - QString helpFile[] = {qgetenv("PROGRAMFILES(x86)") + QString("/QtSpim/help/qtspim.qhc"), // Windows - QString("/Applications/QtSpim.app/Contents/Resources/doc/qtspim.qhc"), // Mac - QString("/usr/lib/qtspim/help/qtspim.qhc"), // Linux - 0}; - - int i; - for (i = 0; helpFile[i] != 0; i += 1) - { - QFileInfo fi1(helpFile[i]); - if (fi1.exists()) - { - args << QString("-collectionFile") << QString(helpFile[i]); - break; - } - } - - if (helpFile[i] == 0) - { - QMessageBox msgBox; - msgBox.setText("Cannot find QtSpim help file. Check installation."); - msgBox.exec(); - return; - } - - char* assistant[] = {"assistant", // Windows - "/Applications/QtSpim.app/Contents/MacOS/Assistant", // Mac - "/usr/lib/qtspim/bin/assistant", // Linux - 0}; - - process->start(QLatin1String(assistant[i]), args); - if (!process->waitForStarted()) - { - QMessageBox msgBox; - msgBox.setText("Cannot start help browser (Qt assistant). Check installation."); - msgBox.exec(); - } -} - - -void SpimView::help_AboutSPIM() -{ - QMessageBox box(QMessageBox::NoIcon, - "About QtSpim", - QString("" - "
    QtSpim
    " - "
    " - "") - + QString("

    ") + QString(SPIM_VERSION) + QString("

    ") - + QString ("

    SPIM is a simulator of the MIPS R3000 processor.

    " - "

    Copyright (c) 1990-2015, James R. Larus (larus@larusstone.org).

    " - "

    SPIM is distributed under a BSD license.

    " - "

    For more information, source code, and binaries:

    " - "

    https://sourceforge.net/projects/spimsimulator/

    " - "

    QtSPIM is linked to the Qt library, which is distributed under the GNU Lesser General Public License version 3 and GNU Lesser General Public License version 2.1.

    " -"

    GNU Lesser General Public License, version 2.1

    " -"

    GNU Lesser General Public License, version 3

    " -"
    "), - QMessageBox::Ok); - box.exec(); -} diff --git a/spim-qtbase/QtSpim/printwindows.ui b/spim-qtbase/QtSpim/printwindows.ui deleted file mode 100644 index 97ece73..0000000 --- a/spim-qtbase/QtSpim/printwindows.ui +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - PrintWindowsDialog - - - - 0 - 0 - 297 - 174 - - - - Print Windows - - - - - 10 - 10 - 261 - 121 - - - - - - - Print windows - - - - - - - Registers - - - - - - - Text Segments - - - - - - - Data Segments - - - - - - - Console - - - - - - - - - -10 - 140 - 273 - 23 - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - true - - - - - - - buttonBox - accepted() - PrintWindowsDialog - accept() - - - 126 - 151 - - - 148 - 86 - - - - - buttonBox - rejected() - PrintWindowsDialog - reject() - - - 126 - 151 - - - 148 - 86 - - - - - diff --git a/spim-qtbase/QtSpim/qtspim.rc b/spim-qtbase/QtSpim/qtspim.rc deleted file mode 100644 index d862c43..0000000 --- a/spim-qtbase/QtSpim/qtspim.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "windows_images/NewIcon.ico" \ No newline at end of file diff --git a/spim-qtbase/QtSpim/regtextedit.h b/spim-qtbase/QtSpim/regtextedit.h deleted file mode 100644 index 9be4766..0000000 --- a/spim-qtbase/QtSpim/regtextedit.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include - -class regTextEdit : public QPlainTextEdit -{ - Q_OBJECT - -public: - regTextEdit(); - void contextMenuEvent(QContextMenuEvent* event); - QAction* action_Context_ChangeValue; - - bool isIntRegs; - -protected: - virtual void closeEvent(QCloseEvent* event); - virtual void hideEvent(QHideEvent* event); - virtual void showEvent(QShowEvent* event); - -private: - QPoint contextGlobalPos; - int convertIntLiteral(QString val, int base, bool *ok); - int regAtPos(QString prefix); - QString strAtPos(QString pattern); - -public slots: - void changeValue(); -}; diff --git a/spim-qtbase/QtSpim/regwin.cpp b/spim-qtbase/QtSpim/regwin.cpp deleted file mode 100644 index baa4b28..0000000 --- a/spim-qtbase/QtSpim/regwin.cpp +++ /dev/null @@ -1,619 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spimview.h" -#include "ui_spimview.h" - -#include -#include -#include -#define QT_USE_FAST_CONCATENATION -#include -#include -#include "ui_changevalue.h" - -// -// Integer registers window -// - -void SpimView::DisplayIntRegisters() -{ - regTextEdit* te = ui->IntRegDockWidget->findChild("IntRegTextEdit"); - te->isIntRegs = true; - QString windowContents = windowFormattingStart(st_regWinFont, st_regWinFontColor, st_regWinBackgroundColor); - int scrollPosition = te->verticalScrollBar()->value(); - - windowContents += formatSpecialIntRegister(PC, "PC", PC != oldPC); - windowContents += formatSpecialIntRegister(CP0_EPC, "EPC", CP0_EPC != oldEPC); - windowContents += formatSpecialIntRegister(CP0_Cause, "Cause", CP0_Cause != oldCause); - windowContents += formatSpecialIntRegister(CP0_BadVAddr, "BadVAddr", CP0_BadVAddr != oldBadVAddr); - windowContents += formatSpecialIntRegister(CP0_Status, "Status", CP0_Status != oldStatus); - windowContents += "
    "; - windowContents += formatSpecialIntRegister(HI, "HI", HI != oldHI); - windowContents += formatSpecialIntRegister(LO, "LO", LO != oldLO); - - windowContents += "
    "; - - int i; - for (i = 0; i < 32; i++) { - windowContents += formatIntRegister(i, R[i], int_reg_names[i], R[i] != oldR[i]); - } - windowContents += windowFormattingEnd(); - - te->clear(); - te->appendHtml(windowContents); - ui->IntRegDockWidget->setWindowTitle(QString("Int Regs [") - + QString::number(st_regDisplayBase) - + QString("] ")); - - te->verticalScrollBar()->setValue(scrollPosition); - CaptureIntRegisters(); -} - - -QString SpimView::formatSpecialIntRegister(int value, char* name, bool changed) -{ - return formatReg(QString("") % QString(name) % nnbsp(8 - strlen(name)) % QString(""), - formatInt(value), - changed); -} - - -QString SpimView::formatIntRegister(int regNum, int value, char* name, bool changed) -{ - return formatReg(QString("R") % QString::number(regNum, 10) % (regNum < 10 ? " " : "") - % QString(" [") % QString(name) % QString("]"), - formatInt(value), - changed); -} - - -void SpimView::CaptureIntRegisters() -{ - int i; - for (i = 0; i < R_LENGTH; i++) - { - oldR[i] = R[i]; - } - oldPC = PC; - oldEPC = CP0_EPC; - oldCause = CP0_Cause; - oldBadVAddr = CP0_BadVAddr; - oldStatus = CP0_Status; - oldHI = HI; - oldLO = LO; -} - - - -// -// Floating point registers -// -void SpimView::DisplayFPRegisters() -{ - regTextEdit* te = ui->FPRegDockWidget->findChild("FPRegTextEdit"); - te->isIntRegs = false; - QString windowContents = windowFormattingStart(st_regWinFont, st_regWinFontColor, st_regWinBackgroundColor); - int scrollPosition = te->verticalScrollBar()->value(); - - windowContents += formatSFPRegisters() % formatDFPRegisters() % windowFormattingEnd(); - - te->clear(); - te->appendHtml(windowContents); - - te->verticalScrollBar()->setValue(scrollPosition); -} - - -// -// Single precision floating point registers window -// - -QString SpimView::formatSFPRegisters() -{ - QString windowContents = ""; - - windowContents += formatSpecialSFPRegister(FIR, "FIR", FIR != oldFIR); - windowContents += formatSpecialSFPRegister(FCSR, "FCSR", FCSR != oldFCSR); - - windowContents += "
    Single Precision
    "; - - int i; - for (i = 0; i < FGR_LENGTH; i++) { - windowContents += formatSFPRegister(i, FPR_S(i), FPR_S(i) != oldFPR_S[i]); - } - - CaptureSFPRegisters(); - - return windowContents; -} - - -void SpimView::CaptureSFPRegisters() -{ - int i; - for (i = 0; i < FGR_LENGTH; i++) - { - oldFPR_S[i] = FPR_S(i); - } - oldFIR = FIR; - oldFCSR = FCSR; -} - - -QString SpimView::formatSpecialSFPRegister(int value, char* name, bool changed) -{ - return formatReg(QString("") % QString(name) % nnbsp(7 - strlen(name)) % QString(""), - formatInt(value), - changed); -} - - -QString SpimView::formatSFPRegister(int regNum, float value, bool changed) -{ - return formatReg(QString("FG") % QString::number(regNum, 10) % (regNum < 10 ? " " : ""), - formatFloat(value), - changed); -} - - -// -// Double precision floating point registers window -// - -QString SpimView::formatDFPRegisters() -{ - QString windowContents = QString("
    Double Precision
    "); - - int i; - for (i = 0; i < FPR_LENGTH; i += 1) - { - windowContents += formatDFPRegister(2 * i, FPR_D(2 * i), FPR_D(2 * i) != oldFPR_D[i]); - } - - CaptureDFPRegisters(); - - return windowContents; -} - - -void SpimView::CaptureDFPRegisters() -{ - int i; - for (i = 0; i < FPR_LENGTH; i += 1) - { - oldFPR_D[i] = FPR_D(2 * i); - } -} - - -QString SpimView::formatDFPRegister(int regNum, double value, bool changed) -{ - return formatReg(QString("FP") % QString::number(regNum, 10) % (regNum < 10 ? " " : ""), - formatDouble(value), - changed); -} - - -// -// Common register functionality -// - -QString SpimView::formatInt(int value) -{ - QString str = QString::number(value, st_regDisplayBase); - - // Negative numbers are sign-extended to 64 bits in base 2 or 16; just return the non-sign - // extended 32 bit value. - if (st_regDisplayBase == 16) - { - str = str.right(8); - } - else if (st_regDisplayBase == 2) - { - str = str.right(32); - } - - return str; -} - - -QString SpimView::formatFloat(float value) -{ - int* ival = (int*)&value; - switch (st_regDisplayBase) { - case 2: - return QString::number(*ival, st_regDisplayBase).right(32); // number returns 64 bits - - case 16: - return QString::number(*ival, st_regDisplayBase).right(8); // number returns 16 digits - - default: - return QString::number(value, 'f', 6); - } -} - - -QString SpimView::formatDouble(double value) -{ - if (st_regDisplayBase == 16 || st_regDisplayBase == 2) - { - qlonglong* ival = (qlonglong*)&value; - return QString::number(*ival, st_regDisplayBase); - } - else - { - return QString::number(value, 'f', 6); - } -} - - -QString SpimView::formatReg(QString name, QString value, bool changed) -{ - return registerBefore(changed) - % name - % QString(" = ") - % value - % QString("
    ") - % registerAfter(changed); -} - - -QString SpimView::registerBefore(bool changed) -{ - return QString(changed && st_colorChangedRegisters - ? QString("") - : QString("")); -} - - -QString SpimView::registerAfter(bool changed) -{ - return QString(changed && st_colorChangedRegisters ? "" : ""); -} - - -QString SpimView::nnbsp(int n) -{ - QString str = ""; - int i; - for (i = 0; i < n; i++) - { - str += " "; - } - return str; -} - - -// -// Change register value -// - -regTextEdit::regTextEdit() -{ - action_Context_ChangeValue = new QAction(this); - action_Context_ChangeValue->setObjectName("action_ChangeValue"); - action_Context_ChangeValue->setText("Change Register Contents"); -} - - -void regTextEdit::contextMenuEvent(QContextMenuEvent* event) -{ - QMenu *menu = createStandardContextMenu(); - menu->addSeparator(); - - menu->addAction(Window->ui->action_Reg_DisplayBinary); - menu->addAction(Window->ui->action_Reg_DisplayDecimal); - menu->addAction(Window->ui->action_Reg_DisplayHex); - - menu->addSeparator(); - menu->addAction(action_Context_ChangeValue); - contextGlobalPos = event->globalPos(); - - menu->exec(event->globalPos()); -} - - -void regTextEdit::changeValue() -{ - int base = Window->RegDisplayBase(); - int reg = regAtPos("R"); - if (reg != -1) - { - QString val = promptForNewValue("New value for R" + QString::number(reg, 10), &base); - bool ok; - int newRegVal = convertIntLiteral(val, base, &ok); - - if (ok) - { - R[reg] = newRegVal; - } - } - else - { - int reg = regAtPos("FG"); - if (reg != -1) - { - QString val = promptForNewValue("New value for FG" + QString::number(reg, 10), &base); - bool ok; - float newRegVal; - if (base == 10) - { - newRegVal = val.toFloat(&ok); - } - else - { - int newIntRegVal = val.toULong(&ok, base); // Read as hex; treat bits -- not value -- as float - void* ptr = &newIntRegVal; - newRegVal = *(float*)ptr; - } - - if (ok) - { - FGR[reg] = newRegVal; - } else - { - QMessageBox msgBox; - msgBox.setText("Bad FP value: " + val); - msgBox.exec(); - } - } - else - { - int reg = regAtPos("FP"); - if (reg != -1) - { - QString val = promptForNewValue("New value for FP" + QString::number(reg, 10), &base); - bool ok; - float newRegVal; - if (base == 10) - { - newRegVal = val.toDouble(&ok); - } - else - { - qlonglong newIntRegVal = val.toULongLong(&ok, base); // Read as hex; treat bits -- not value -- as double - void* ptr = &newIntRegVal; - newRegVal = *(double*)ptr; - } - - if (ok) - { - FPR[reg] = newRegVal; - } else - { - QMessageBox msgBox; - msgBox.setText("Bad FP value: " + val); - msgBox.exec(); - } - } - else - { - QString reg = strAtPos("([A-Za-z]+)"); - if (reg != "") - { - QString val = promptForNewValue("New value for " + reg, &base); - bool ok; - int newRegVal = convertIntLiteral(val, base, &ok); - - if (ok) - { - if (reg == "PC") - { - PC = newRegVal; - } - else if (reg == "EPC") - { - CP0_EPC = newRegVal; - } - else if (reg == "Cause") - { - CP0_Cause = newRegVal; - } - else if (reg == "BadVAddr") - { - CP0_BadVAddr = newRegVal; - } - else if (reg == "Status") - { - CP0_Status = newRegVal; - } - else if (reg == "HI") - { - HI = newRegVal; - } - else if (reg == "LO") - { - LO = newRegVal; - } - else if (reg == "FIR") - { - FIR = newRegVal; - } - else if (reg == "FCSR") - { - FCSR = newRegVal; - } - } - } - } - } - } - Window->DisplayIntRegisters(); - Window->DisplayFPRegisters(); -} - - -int regTextEdit::convertIntLiteral(QString val, int base, bool *ok) -{ - int newRegVal = 0; - - if (base == 10) { - newRegVal = val.toLong(ok, base); // decimal is signed - } else - { - newRegVal = val.toULong(ok, base); // hex is unsigned - } - - if (!*ok) - { - QMessageBox msgBox; - msgBox.setText(QString("Bad ") + (base == 16 ? "hex" : "decimal") + " register value: " + val); - msgBox.exec(); - } - - return newRegVal; -} - - -int regTextEdit::regAtPos(QString prefix) -{ - QString regStr = strAtPos(prefix + "([0-9]+)"); // Register name - if (regStr != "") - { - return regStr.toInt(); - } - else - { - return -1; - } -} - - -QString regTextEdit::strAtPos(QString pattern) -{ - // Position of context menu is location user right-click. Find the line at this point - // and compute the address of the memory location the user clicked on. - // - QPoint mouseViewportPos = this->viewport()->mapFromGlobal(contextGlobalPos); - QTextCursor mouseCursor = this->cursorForPosition(mouseViewportPos); - - mouseCursor.select(QTextCursor::LineUnderCursor); - QString line = mouseCursor.selectedText(); - - QRegExp rx(pattern); - - rx.indexIn(line); - return rx.cap(1); -} - - -QString promptForNewValue(QString text, int* base) -{ - QDialog d; - Ui::ChangeValueDialog cvd; - cvd.setupUi(&d); - - cvd.label->setText(text); - if (*base == -1) - { - cvd.hexRadioButton->setVisible(false); - cvd.decimalRadioButton->setVisible(false); - } - else - { - cvd.hexRadioButton->setVisible(true); - cvd.decimalRadioButton->setVisible(true); - - cvd.hexRadioButton->setChecked(*base == 16); - cvd.decimalRadioButton->setChecked(*base == 10); - } - - if (d.exec() == QDialog::Accepted) - { - if (cvd.hexRadioButton->isChecked()) - { - *base = 16; - } - else if (cvd.decimalRadioButton->isChecked()) - { - *base = 10; - } - return cvd.answerLineEdit->text(); - } - else - { - return QString(""); - } -} - - -void regTextEdit::closeEvent(QCloseEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - if (isIntRegs) - { - Window->ui->action_Win_IntRegisters->setChecked(false); - } - else - { - Window->ui->action_Win_FPRegisters->setChecked(false); - } - } - event->accept(); -} - - -void regTextEdit::hideEvent(QHideEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - if (isIntRegs) - { - Window->ui->action_Win_IntRegisters->setChecked(false); - } - else - { - Window->ui->action_Win_FPRegisters->setChecked(false); - } - } - event->accept(); -} - - -void regTextEdit::showEvent(QShowEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - if (isIntRegs) - { - Window->ui->action_Win_IntRegisters->setChecked(true); - } - else - { - Window->ui->action_Win_FPRegisters->setChecked(true); - } - } - event->accept(); -} diff --git a/spim-qtbase/QtSpim/runparams.ui b/spim-qtbase/QtSpim/runparams.ui deleted file mode 100644 index d4f52e7..0000000 --- a/spim-qtbase/QtSpim/runparams.ui +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - SetRunParametersDialog - - - - 0 - 0 - 318 - 207 - - - - Set Run Parameters - - - - - 10 - 10 - 298 - 187 - - - - - - - Address or label to start running program - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Command-line arguments to pass to program - - - - - - - - 0 - 0 - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - - - - buttonBox - accepted() - SetRunParametersDialog - accept() - - - 158 - 173 - - - 158 - 90 - - - - - buttonBox - rejected() - SetRunParametersDialog - reject() - - - 158 - 173 - - - 158 - 90 - - - - - diff --git a/spim-qtbase/QtSpim/savelogfile.ui b/spim-qtbase/QtSpim/savelogfile.ui deleted file mode 100644 index a6baa6b..0000000 --- a/spim-qtbase/QtSpim/savelogfile.ui +++ /dev/null @@ -1,224 +0,0 @@ - - - SaveLogFileDialog - - - - 0 - 0 - 370 - 286 - - - - - 50 - false - - - - Save Windows To Log File - - - - - 10 - 10 - 350 - 235 - - - - - 75 - true - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Select windows to write to log file - - - - - - - - 50 - false - - - - Registers - - - - - - - - 50 - false - - - - Text Segments - - - - - - - - 50 - false - - - - Data Segments - - - - - - - - 50 - false - - - - Console - - - - - - - - 50 - false - - - - Save to file - - - - - - - - 75 - true - - - - - - - - - 75 - true - - - - ... - - - - - - - - 75 - true - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - - - 110 - 250 - 156 - 23 - - - - - 50 - false - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - buttonBox - accepted() - SaveLogFileDialog - accept() - - - 187 - 261 - - - 184 - 142 - - - - - buttonBox - rejected() - SaveLogFileDialog - reject() - - - 187 - 261 - - - 184 - 142 - - - - - diff --git a/spim-qtbase/QtSpim/settablecheckbox.h b/spim-qtbase/QtSpim/settablecheckbox.h deleted file mode 100644 index 725a220..0000000 --- a/spim-qtbase/QtSpim/settablecheckbox.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include - -class settableCheckBox : public QCheckBox -{ -Q_OBJECT - -public: - settableCheckBox(QWidget* w) : QCheckBox(w) {}; - -public slots: - void set() {setChecked(true);} - void unset() {setChecked(false);} -}; diff --git a/spim-qtbase/QtSpim/settings.ui b/spim-qtbase/QtSpim/settings.ui deleted file mode 100644 index a8430c3..0000000 --- a/spim-qtbase/QtSpim/settings.ui +++ /dev/null @@ -1,616 +0,0 @@ - - - SettingDialog - - - - 0 - 0 - 600 - 466 - - - - QtSpim Settings - - - - - 10 - 0 - 580 - 421 - - - - 1 - - - - MIPS - - - - - 20 - 10 - 531 - 371 - - - - - - - Exception Handler - - - - - 20 - 20 - 481 - 72 - - - - - - - - - - 1 - 0 - - - - Qt::AlignCenter - - - - - - - - 0 - 0 - - - - Load Exception Handler - - - - - - - - 0 - 0 - - - - File - - - - - - - - 26 - 22 - - - - ... - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - - - - - 200 - 32 - - - - Use default exception handler - - - - - - - - - - - MIPS Simulation Settings - - - - - 20 - 30 - 481 - 141 - - - - - - - - - Bare Machine - - - - - - - Enable Delayed Branches - - - - - - - Enable Delayed Loads - - - - - - - Enable Mapped IO - - - - - - - Accept Pseudo Instructions - - - - - - - - - - - - 239 - 32 - - - - Simple Machine - - - - - - - - 238 - 32 - - - - Bare Machine - - - - - - - - - - - - - - - QtSpim - - - - - 20 - 10 - 531 - 371 - - - - - - - Simulator - - - - - 20 - 20 - 491 - 91 - - - - - - - - - Length of Recent File list - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - - - Quiet - - - - - - - - - - - - - Register Windows - - - - - 20 - 20 - 491 - 91 - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - - - - Background Color - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 26 - 22 - - - - ... - - - - - - - Font - - - - - - - - - - - 26 - 22 - - - - ... - - - - - - - Color - - - - - - - - 26 - 22 - - - - ... - - - - - - - - - - - Text and Data Windows - - - - - 20 - 20 - 491 - 91 - - - - - - - - 26 - 22 - - - - ... - - - - - - - - - - - 0 - 0 - - - - - - - - Background Color - - - - - - - - 26 - 22 - - - - ... - - - - - - - Color - - - - - - - Font - - - - - - - - 26 - 22 - - - - ... - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - - 210 - 430 - 180 - 23 - - - - - 180 - 23 - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - true - - - - - - settableCheckBox - QCheckBox -
    settablecheckbox.h
    -
    -
    - - tabWidget - bareMachineCheckBox - pseudoInstCheckBox - delayedBranchCheckBox - delayedLoadCheckBox - mappedIOCheckBox - simplePushButton - barePushButton - loadExceptionHandlerCheckBox - exceptionHandlerLineEdit - exceptionHandlerToolButton - exceptionHandlerResetButton - buttonBox - recentFilesLineEdit - regWinFontLineEdit - regWinFontToolButton - regWinFontColorLineEdit - regWinFontColorToolButton - regWinBackgroundLineEdit - regWinBackgroundToolButton - textWinFontLineEdit - textWinFontToolButton - textWinFontColorLineEdit - textWinFontColorToolButton - textWinBackgroundLineEdit - textWinBackgroundToolButton - - - - - buttonBox - accepted() - SettingDialog - accept() - - - 317 - 441 - - - 299 - 235 - - - - - buttonBox - rejected() - SettingDialog - reject() - - - 317 - 441 - - - 299 - 235 - - - - -
    diff --git a/spim-qtbase/QtSpim/spim_settings.h b/spim-qtbase/QtSpim/spim_settings.h deleted file mode 100644 index 3ae1712..0000000 --- a/spim-qtbase/QtSpim/spim_settings.h +++ /dev/null @@ -1,110 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef SPIM_SETTING_DIALOG_H -#define SPIM_SETTING_DIALOG_H - -#include -#include -#include - -#include "ui_settings.h" - -namespace Ui{ - - class SpimSettingDialog : public QObject, public SettingDialog -{ -Q_OBJECT - -public: - SpimSettingDialog() : SettingDialog() - { - regWinFont = NULL; - regWinColor = NULL; - regWinBackground = NULL; - - textWinFont = NULL; - textWinColor = NULL; - textWinBackground = NULL; - } - - QFont* regWinFont; - QColor* regWinColor; - QColor* regWinBackground; - - QFont* textWinFont; - QColor* textWinColor; - QColor* textWinBackground; - - -public slots: - void setRegWinFont(QFont f) - { - regWinFont = new QFont(f); - regWinFontLineEdit->setText(f.family()); - } - - void setRegWinColor(QColor c) - { - regWinColor = new QColor(c); - regWinFontColorLineEdit->setText(c.name()); - } - - void setRegWinBackground(QColor c) - { - regWinBackground = new QColor(c); - regWinBackgroundLineEdit->setText(c.name()); - } - - - void setTextWinFont(QFont f) - { - textWinFont = new QFont(f); - textWinFontLineEdit->setText(f.family()); - } - - void setTextWinColor(QColor c) - { - textWinColor = new QColor(c); - textWinFontColorLineEdit->setText(c.name()); - } - - void setTextWinBackground(QColor c) - { - textWinBackground = new QColor(c); - textWinBackgroundLineEdit->setText(c.name()); - } -}; - -} -#endif // SPIM_SETTING_DIALOG_H diff --git a/spim-qtbase/QtSpim/spim_support.cpp b/spim-qtbase/QtSpim/spim_support.cpp deleted file mode 100644 index c143d89..0000000 --- a/spim-qtbase/QtSpim/spim_support.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include - -#include "spimview.h" -#include "ui_spimview.h" - -#include - - -// SPIM globals -// -bool bare_machine; /* => simulate bare machine */ -bool accept_pseudo_insts; /* => parse pseudo instructions */ -bool delayed_branches; /* => simulate delayed branches */ -bool delayed_loads; /* => simulate delayed loads */ -bool quiet; /* => no warning messages */ -char* exception_file_name = 0; /* The path from which to load the exception handler, if desired */ -bool mapped_io; /* => activate memory-mapped IO */ -int spim_return_value; /* Value returned when spim exits */ - -port message_out; -port console_out; - - -#define BIG_BUF_SIZE 10000 - -int console_input_available() -{ - return Window->SpimConsole->InputAvailable(); - -} - - -void error(char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - - char buf[BIG_BUF_SIZE]; - qvsnprintf(buf, BIG_BUF_SIZE, fmt, args); - va_end(args); - - Window->Error(buf, 0); -} - - -void run_error (char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - - char buf[BIG_BUF_SIZE]; - qvsnprintf(buf, BIG_BUF_SIZE, fmt, args); - va_end(args); - - Window->Error(buf, 0); -} - - -void fatal_error(char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - - char buf[BIG_BUF_SIZE]; - qvsnprintf(buf, BIG_BUF_SIZE, fmt, args); - va_end(args); - - Window->Error(buf, 1); -} - - -char get_console_char() -{ - QString c = Window->SpimConsole->ReadChar(); - if (c != "") - { - char ac = c[0].toLatin1(); - if (ac == '\r') - { - return '\n'; - } - return ac; - } - else - { - return 0; // FIXME - } -} - - -void put_console_char(char c) -{ - Window->SpimConsole->WriteOutput(QString(c)); - Window->SpimConsole->raise(); -} - - -void read_input(char *str, int str_size) -{ - while ((1 < str_size) && (!force_break)) - { - char ch = get_console_char(); - - *str = ch; - str += 1; - str_size -= 1; - - if (ch == '\n') - { - break; - } - } - - if (0 < str_size) - { - *str = '\0'; - } -} - - -void write_output (port fp, char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - - char buf[BIG_BUF_SIZE]; - qvsnprintf(buf, BIG_BUF_SIZE, fmt, args); - va_end(args); - - if (fp.i == message_out.i) - { - Window->WriteOutput(buf); - } - else if (fp.i == console_out.i) - { - Window->SpimConsole->WriteOutput(QString(buf)); - Window->SpimConsole->raise(); - } -} diff --git a/spim-qtbase/QtSpim/spimview.cpp b/spim-qtbase/QtSpim/spimview.cpp deleted file mode 100644 index 93f07ed..0000000 --- a/spim-qtbase/QtSpim/spimview.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spimview.h" -#include "ui_spimview.h" - -#include -#define QT_USE_FAST_CONCATENATION -#include -#include -#include - - -SpimView::SpimView(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::SpimView), - settings("LarusStone", "QtSpim") -{ - // Open windows - // - ui->setupUi(this); - SpimConsole = new Console(0); - - stdExceptionHandler = QString("<>"); - - // Set style parameters for docking widgets - // - setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); - setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - - // Dock widgets - // - win_Tile(); - - // Wire up the menu and context menu commands - // - wireCommands(); - - // Restore program settings and window positions - // - readSettings(); - - // Create a console - // - ui->action_Win_Console->setChecked(true); - - programStatus = IDLE; -} - - -void SpimView::closeEvent(QCloseEvent *) -{ - writeSettings(false); - qApp->exit(0); -} - - -void SpimView::wireCommands() -{ - QObject::connect(ui->action_File_Load, SIGNAL(triggered(bool)), this, SLOT(file_LoadFile())); - QObject::connect(ui->action_File_Reload, SIGNAL(triggered(bool)), this, SLOT(file_ReloadFile())); - QObject::connect(ui->action_File_SaveLog, SIGNAL(triggered(bool)), this, SLOT(file_SaveLogFile())); - QObject::connect(ui->action_File_Print, SIGNAL(triggered(bool)), this, SLOT(file_Print())); - QObject::connect(ui->action_File_Exit, SIGNAL(triggered(bool)), this, SLOT(file_Exit())); - - QObject::connect(ui->action_Sim_ClearRegisters, SIGNAL(triggered(bool)), this, SLOT(sim_ClearRegisters())); - QObject::connect(ui->action_Sim_Reinitialize, SIGNAL(triggered(bool)), this, SLOT(sim_ReinitializeSimulator())); - QObject::connect(ui->action_Sim_SetRunParameters, SIGNAL(triggered(bool)), this, SLOT(sim_SetRunParameters())); - QObject::connect(ui->action_Sim_Run, SIGNAL(triggered(bool)), this, SLOT(sim_Run())); - QObject::connect(ui->action_Sim_Pause, SIGNAL(triggered(bool)), this, SLOT(sim_Pause())); - QObject::connect(ui->action_Sim_Stop, SIGNAL(triggered(bool)), this, SLOT(sim_Stop())); - QObject::connect(ui->action_Sim_SingleStep, SIGNAL(triggered(bool)), this, SLOT(sim_SingleStep())); - QObject::connect(ui->action_Sim_DisplaySymbols, SIGNAL(triggered(bool)), this, SLOT(sim_DisplaySymbols())); - QObject::connect(ui->action_Sim_Settings, SIGNAL(triggered(bool)), this, SLOT(sim_Settings())); - - QObject::connect(ui->action_Reg_DisplayBinary, SIGNAL(triggered(bool)), this, SLOT(reg_DisplayBinary())); - QObject::connect(ui->action_Reg_DisplayHex, SIGNAL(triggered(bool)), this, SLOT(reg_DisplayHex())); - QObject::connect(ui->action_Reg_DisplayDecimal, SIGNAL(triggered(bool)), this, SLOT(reg_DisplayDecimal())); - - QObject::connect(ui->action_Text_DisplayUserText, SIGNAL(triggered(bool)), this, SLOT(text_DisplayUserText())); - QObject::connect(ui->action_Text_DisplayKernelText, SIGNAL(triggered(bool)), this, SLOT(text_DisplayKernelText())); - QObject::connect(ui->action_Text_DisplayComments, SIGNAL(triggered(bool)), this, SLOT(text_DisplayComments())); - QObject::connect(ui->action_Text_DisplayInstructionValue, SIGNAL(triggered(bool)), this, SLOT(text_DisplayInstructionValue())); - - QObject::connect(ui->action_Data_DisplayUserData, SIGNAL(triggered(bool)), this, SLOT(data_DisplayUserData())); - QObject::connect(ui->action_Data_DisplayUserStack, SIGNAL(triggered(bool)), this, SLOT(data_DisplayUserStack())); - QObject::connect(ui->action_Data_DisplayKernelData, SIGNAL(triggered(bool)), this, SLOT(data_DisplayKernelData())); - QObject::connect(ui->action_Data_DisplayBinary, SIGNAL(triggered(bool)), this, SLOT(data_DisplayBinary())); - QObject::connect(ui->action_Data_DisplayHex, SIGNAL(triggered(bool)), this, SLOT(data_DisplayHex())); - QObject::connect(ui->action_Data_DisplayDecimal, SIGNAL(triggered(bool)), this, SLOT(data_DisplayDecimal())); - - QObject::connect(ui->action_Win_IntRegisters, SIGNAL(triggered(bool)), this, SLOT(win_IntRegisters())); - QObject::connect(ui->action_Win_FPRegisters, SIGNAL(triggered(bool)), this, SLOT(win_FPRegisters())); - QObject::connect(ui->action_Win_TextSegment, SIGNAL(triggered(bool)), this, SLOT(win_TextSegment())); - QObject::connect(ui->action_Win_DataSegment, SIGNAL(triggered(bool)), this, SLOT(win_DataSegment())); - QObject::connect(ui->action_Win_Console, SIGNAL(triggered(bool)), this, SLOT(win_Console())); - QObject::connect(ui->action_Win_Tile, SIGNAL(triggered(bool)), this, SLOT(win_Tile())); - QObject::connect(ui->action_Win_Restore, SIGNAL(triggered(bool)), this, SLOT(win_Restore())); - - QObject::connect(ui->action_Help_ViewHelp, SIGNAL(triggered(bool)), this, SLOT(help_ViewHelp())); - QObject::connect(ui->action_Help_AboutSPIM, SIGNAL(triggered(bool)), this, SLOT(help_AboutSPIM())); - - QObject::connect(ui->TextSegmentTextEdit->action_Context_SetBreakpoint, SIGNAL(triggered(bool)), - ui->TextSegmentTextEdit, SLOT(setBreakpoint())); - QObject::connect(ui->TextSegmentTextEdit->action_Context_ClearBreakpoint, SIGNAL(triggered(bool)), - ui->TextSegmentTextEdit, SLOT(clearBreakpoint())); - - - QObject::connect(ui->IntRegTextEdit->action_Context_ChangeValue, SIGNAL(triggered(bool)), - ui->IntRegTextEdit, SLOT(changeValue())); - QObject::connect(ui->FPRegTextEdit->action_Context_ChangeValue, SIGNAL(triggered(bool)), - ui->FPRegTextEdit, SLOT(changeValue())); - QObject::connect(ui->DataSegmentTextEdit->action_Context_ChangeValue, SIGNAL(triggered(bool)), - ui->DataSegmentTextEdit, SLOT(changeValue())); -} - - -QString SpimView::windowFormattingStart(QFont font, QColor fontColor, QColor backgroundColor) -{ - return QString(""); -} - - -QString SpimView::windowFormattingEnd() -{ - return ""; -} - - -void SpimView::InitializeWorld() -{ - if (st_loadExceptionHandler) - { - if ((st_exceptionHandlerFileName != stdExceptionHandler) - && !QFile::exists(st_exceptionHandlerFileName)) - { - QMessageBox msgBox; - msgBox.setText(QString("%1: exception handler file not found.\n\nUsing default exception handler.") - .arg(st_exceptionHandlerFileName)); - msgBox.exec(); - st_exceptionHandlerFileName = stdExceptionHandler; - } - if (st_exceptionHandlerFileName == stdExceptionHandler) - { - // Standard exception handler is a resource in this executable. Write it to a - // temporary file and use that for initialization. - // - QResource exRes(":exceptions.s"); - QTemporaryFile tmpFile; - tmpFile.open(); - tmpFile.write((char*)exRes.data()); - tmpFile.close(); - initialize_world(tmpFile.fileName().toLocal8Bit().data(), false); - } - else - { - // Use the file name supplied by the user. - // - initialize_world(st_exceptionHandlerFileName.toLocal8Bit().data(), true); - } - } - else - { - // No exception handler. - // - initialize_world(NULL, true); - } -} - - -void SpimView::SetExceptionHandler(QString fileName, bool loadHandler) -{ - if (fileName != "") - { - st_exceptionHandlerFileName = fileName; - } - st_loadExceptionHandler = loadHandler; -} - - -void SpimView::UpdateDataDisplay() -{ - // Text segment rarely changes -- update manually - // - if (text_modified){ - DisplayTextSegments(true); - } - DisplayIntRegisters(); - DisplayFPRegisters(); - DisplayDataSegments(false); -} - - -void SpimView::SaveStateAndExit(int val) -{ - writeSettings(false); - exit(val); -} - - -QString SpimView::WriteOutput(QString message) -{ - if (message.endsWith("\n")) - { - message.chop(1); // Appending adds a
    , so avoid doubling last newline - } - message.replace("\n", "
    "); - message.replace(" ", " "); - - Window->ui->centralWidget->append(QString("") + message + QString("")); - Window->ui->centralWidget->ensureCursorVisible(); - - return message; -} - - -void SpimView::SetOutputColor(QString color) -{ - outputColor = color; -} - - -void SpimView::Error(QString message, bool fatal) -{ - WriteOutput(message); - - if (fatal) - { - QMessageBox::critical(0, "Error", message, QMessageBox::Ok | QMessageBox::Abort, QMessageBox::Ok); - SaveStateAndExit(1); - } - else - { - QMessageBox::StandardButton b = QMessageBox::information(0, - "Error", - message, - QMessageBox::Ok | QMessageBox::Abort, - QMessageBox::Ok); - if (b == QMessageBox::Abort) - { - force_break = true; - } - } -} diff --git a/spim-qtbase/QtSpim/spimview.h b/spim-qtbase/QtSpim/spimview.h deleted file mode 100644 index a59bf96..0000000 --- a/spim-qtbase/QtSpim/spimview.h +++ /dev/null @@ -1,306 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2020, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef SPIMVIEW_H -#define SPIMVIEW_H - -#include -#include -#include -#include - -#include "ui_spimview.h" -#include "console.h" - -#include "../CPU/spim.h" -#include "../CPU/string-stream.h" -#include "../CPU/spim-utils.h" -#include "../CPU/inst.h" -#include "../CPU/reg.h" -#include "../CPU/mem.h" -#include "../CPU/sym-tbl.h" -#include "../CPU/version.h" - -namespace Ui { - class SpimView; -} - -class SpimView : public QMainWindow -{ -Q_OBJECT - - public: - explicit SpimView(QWidget *parent = 0); - - virtual void closeEvent(QCloseEvent *); - - QString WriteOutput(QString message); - void Error(QString message, bool fatal); - - void SaveStateAndExit(int val); - - void InitializeWorld(); - void SetExceptionHandler(QString fileName, bool loadHandler); - - void CaptureIntRegisters(); - void CaptureSFPRegisters(); - void CaptureDFPRegisters(); - - void DisplayIntRegisters(); - void DisplayFPRegisters(); - void DisplayTextSegments(bool force); - void DisplayDataSegments(bool force); - void UpdateDataDisplay(); - - int RegDisplayBase() { return st_regDisplayBase;} - int DataDisplayBase() { return st_dataSegmentDisplayBase;} - - Ui::SpimView *ui; - - void SetOutputColor(QString color); - - private: - - QString outputColor; - - // - // Program state - // - QSettings settings; - void readSettings(); - void writeSettings(bool omitWindowState); - QString stdExceptionHandler; - - // File menu - // - int st_recentFilesLength; - QList st_recentFiles; - void rebuildRecentFilesMenu(); - - // Simulator menu - // - bool st_loadExceptionHandler; - QString st_exceptionHandlerFileName; - int st_startAddress; - QString st_commandLine; - - // Register window - // - bool st_colorChangedRegisters; - QString st_changedRegisterColor; - int st_regDisplayBase; - QFont st_regWinFont; - QColor st_regWinFontColor; - QColor st_regWinBackgroundColor; - - // Text window - // - bool st_showUserTextSegment; - bool st_showKernelTextSegment; - bool st_showTextComments; - bool st_showTextDisassembly; - QFont st_textWinFont; - QColor st_textWinFontColor; - QColor st_textWinBackgroundColor; - - // Data window - // - bool st_showUserDataSegment; - bool st_showUserStackSegment; - bool st_showKernelDataSegment; - int st_dataSegmentDisplayBase; - - // - // End of state - - // - // Methods: - // - - // Establish text formatting for a window - // - QString windowFormattingStart(QFont font, QColor fontColor, QColor backgroundColor); - QString windowFormattingEnd(); - - - // Integer registers window - // - QString formatSpecialIntRegister(int value, char* name, bool changed); - QString formatIntRegister(int regNum, int value, char* name, bool changed); - - // Value in register at previous call on displayIntRegister, so changed values - // can be highlighted. - // - reg_word oldR[R_LENGTH]; - mem_addr oldPC; - reg_word oldEPC; - reg_word oldCause; - reg_word oldBadVAddr; - reg_word oldStatus; - reg_word oldHI; - reg_word oldLO; - - - // Single precision FP registers window - // - QString formatSFPRegisters(); - QString formatSpecialSFPRegister(int value, char* name, bool changed); - QString formatSFPRegister(int regNum, float value, bool changed); - - float oldFPR_S[FGR_LENGTH]; - reg_word oldFIR; - reg_word oldFCSR; - - - // Double precision FP registers window - // - QString formatDFPRegisters(); - QString formatDFPRegister(int regNum, double value, bool changed); - - double oldFPR_D[FPR_LENGTH]; - - - // Common register methods - // - QString formatInt(int value); - QString formatFloat(float value); - QString formatDouble(double value); - QString formatReg(QString reg, QString value, bool changed); - QString registerBefore(bool changed); - QString registerAfter(bool changed); - QString nnbsp(int n); - - - // Text segment window - // - QString formatUserTextSeg(); - QString formatKernelTextSeg(); - QString formatInstructions(mem_addr from, mem_addr to); - void highlightInstruction(mem_addr pc); - - - // Data segment window - // - QString formatUserDataSeg(); - QString formatUserStack(); - QString formatKernelDataSeg(); - QString formatMemoryContents(mem_addr from, mem_addr to); - QString formatPartialQuadWord(mem_addr from, mem_addr to); - QString formatAsChars(mem_addr from, mem_addr to); - - - // - // Menu functions - // - void wireCommands(); - void initStack(); - void executeProgram(mem_addr pc, int steps, bool display, bool contBkpt); - void initializePCAndStack(); - enum PROGSTATE {IDLE, STOPPED, PAUSED, RUNNING, SINGLESTEP} programStatus; - void updateStatus(PROGSTATE status); - - - // - // Console - // - public: - Console* SpimConsole; - - - public slots: - void file_LoadFile(); - void file_ReloadFile(); - void file_SaveLogFile(); - void file_Print(); - void file_Exit(); - - void sim_ClearRegisters(); - void sim_ReinitializeSimulator(); - void sim_SetRunParameters(); - void sim_Run(); - void sim_Pause(); - void sim_Stop(); - void sim_SingleStep(); - void sim_DisplaySymbols(); - void sim_Settings(); - - void reg_DisplayBinary(); - void reg_DisplayHex(); - void reg_DisplayDecimal(); - int setCheckedRegBase(int base); - int setBaseInternal(int base, QAction* actionBinary, QAction* actionDecimal, QAction* actionHex); - - void text_DisplayUserText(); - void text_DisplayKernelText(); - void text_DisplayComments(); - void text_DisplayInstructionValue(); - - void data_DisplayUserData(); - void data_DisplayUserStack(); - void data_DisplayKernelData(); - void data_DisplayBinary(); - void data_DisplayHex(); - void data_DisplayDecimal(); - int setCheckedDataSegmentDisplayBase(int base); - - void win_IntRegisters(); - void win_FPRegisters(); - void win_TextSegment(); - void win_DataSegment(); - void win_Console(); - void win_Tile(); - void win_Restore(); - - void help_ViewHelp(); - void help_AboutSPIM(); - - void continueBreakpoint(); - void singleStepBreakpoint(); - void abortBreakpoint(); -}; - -extern SpimView* Window; -extern QApplication* App; - - -// Format SPIM abstractions for display -// -QString formatAddress(mem_addr addr); -QString formatWord(mem_word word, int base); -QString formatChar(int chr); -QString formatSegLabel(QString segName, mem_addr low, mem_addr high); - -QString promptForNewValue(QString text, int* base); - - -#endif // SPIMVIEW_H diff --git a/spim-qtbase/QtSpim/spimview.ui b/spim-qtbase/QtSpim/spimview.ui deleted file mode 100644 index 54dab74..0000000 --- a/spim-qtbase/QtSpim/spimview.ui +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - - SpimView - - - - 0 - 0 - 1172 - 770 - - - - QtSpim - - - QMainWindow::AnimatedDocks|QMainWindow::ForceTabbedDocks|QMainWindow::VerticalTabs - - - - false - - - true - - - - - - 0 - 0 - 1172 - 21 - - - - - &File - - - - Recent Files - - - - - - - - - - - - - - - &Simulator - - - - - - - - - - - - - - - - - &Registers - - - - - - - - &Text Segment - - - - - - - - - - &Data Segment - - - - - - - - - - - - - &Window - - - - - - - - - - - - - &Help - - - - - - - - - - - - - - - - Qt::TopDockWidgetArea - - - Int Regs - - - 4 - - - - - 200 - 600 - - - - false - - - true - - - - - - Qt::TopDockWidgetArea - - - FP Regs - - - 4 - - - - false - - - true - - - - - - - 0 - 0 - - - - Qt::BottomDockWidgetArea|Qt::TopDockWidgetArea - - - Text - - - 4 - - - - - 800 - 600 - - - - false - - - true - - - - - - Qt::TopDockWidgetArea - - - Data - - - 4 - - - - false - - - true - - - - - - toolBar - - - TopToolBarArea - - - - - - - - - - - - - - - - - - - - - :/icons/LoadFile.png:/icons/LoadFile.png - - - &Load File - - - - - - :/icons/SaveLog.png:/icons/SaveLog.png - - - &Save Log File - - - - - &Exit - - - - - - :/icons/ClearRegs.png:/icons/ClearRegs.png - - - &Clear Registers - - - - - - :/icons/Reinit.png:/icons/Reinit.png - - - Re&initialize Simulator - - - - - - :/icons/ReloadFile.png:/icons/ReloadFile.png - - - Re&initialize and Load File - - - - - Run &Parameters - - - - - - :/icons/Run.png:/icons/Run.png - - - &Run/Continue - - - F5 - - - - - - :/icons/Pause.png:/icons/Pause.png - - - &Pause - - - - - - :/icons/Stop.png:/icons/Pause.png - - - &Stop - - - Shift-F5 - - - - - - :/icons/SingleStep.png:/icons/SingleStep.png - - - &Single Step - - - F10 - - - - - &Display Symbols - - - - - - :/icons/Settings.png:/icons/Settings.png - - - Settings - - - - - true - - - Binary - - - - - true - - - Hex - - - - - true - - - Decimal - - - - - true - - - User Text - - - - - true - - - Kernel Text - - - - - true - - - Comments - - - - - true - - - Instruction Value - - - - - true - - - User Data - - - - - true - - - User Stack - - - - - true - - - Kernel Data - - - - - true - - - Binary - - - - - true - - - Hex - - - - - true - - - Decimal - - - - - true - - - Integer Registers - - - - - true - - - FP Registers - - - - - true - - - Text Segment - - - - - true - - - Data Segment - - - - - true - - - Console - - - - - Tile - - - - - Restore to default - - - - - - :/icons/Help.png:/icons/Help.png - - - View Help - - - - - About QtSpim - - - - - - :/icons/Print.png:/icons/Print.png - - - Print - - - - - - - textTextEdit - QWidget -
    texttextedit.h
    -
    - - dataTextEdit - QWidget -
    datatextedit.h
    -
    -
    - - - - -
    diff --git a/spim-qtbase/QtSpim/state.cpp b/spim-qtbase/QtSpim/state.cpp deleted file mode 100644 index 5d2ae8c..0000000 --- a/spim-qtbase/QtSpim/state.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include -#include - -#include "spimview.h" -#include "ui_spimview.h" - - -// -// Restore program settings and window positions -// - -void SpimView::readSettings() -{ - settings.beginGroup("MainWin"); - restoreGeometry(settings.value("Geometry").toByteArray()); - restoreState(settings.value("WindowState").toByteArray(), 1); - settings.endGroup(); - - // If the size of the restored window exceeds the current screen size, resize the window. - // - const QRect availGeo = App->desktop()->availableGeometry(this); - const QRect& curFGeo = this->frameGeometry(); - if (!availGeo.contains(curFGeo)) - { - this->adjustSize(); - } - - settings.beginGroup("RegWin"); - st_colorChangedRegisters = settings.value("ColorChangedRegs", true).toBool(); - st_changedRegisterColor = settings.value("ChangedRegColor", "red").toString(); - st_regDisplayBase = settings.value("RegisterDisplayBase", 16).toInt(); - st_regDisplayBase = setCheckedRegBase(st_regDisplayBase); - - st_regWinFont = settings.value("Font", QFont("Courier", 10)).value(); - st_regWinFontColor = settings.value("FontColor", QColor("black")).value(); - st_regWinBackgroundColor = settings.value("BackgroundColor", QColor("white")).value(); - - ui->action_Win_IntRegisters->setChecked(!ui->IntRegDockWidget->isHidden()); - ui->action_Win_FPRegisters->setChecked(!ui->FPRegDockWidget->isHidden()); - settings.endGroup(); - - - settings.beginGroup("TextWin"); - st_showUserTextSegment = settings.value("ShowUserTextSeg", true).toBool(); - ui->action_Text_DisplayUserText->setChecked(st_showUserTextSegment); - st_showKernelTextSegment = settings.value("ShowKernelTextSeg", true).toBool(); - ui->action_Text_DisplayKernelText->setChecked(st_showKernelTextSegment); - st_showTextComments = settings.value("ShowTextComments", true).toBool(); - ui->action_Text_DisplayComments->setChecked(st_showTextComments); - st_showTextDisassembly = settings.value("ShowInstDisassembly", true).toBool(); - ui->action_Text_DisplayInstructionValue->setChecked(st_showTextDisassembly); - - st_textWinFont = settings.value("Font", QFont("Courier", 10)).value(); - st_textWinFontColor = settings.value("FontColor", QColor("black")).value(); - st_textWinBackgroundColor = settings.value("BackgroundColor", QColor("white")).value(); - - ui->action_Win_TextSegment->setChecked(!ui->TextSegDockWidget->isHidden()); - settings.endGroup(); - - - settings.beginGroup("DataWin"); - st_showUserDataSegment = settings.value("ShowUserDataSeg", true).toBool(); - ui->action_Data_DisplayUserData->setChecked(st_showUserDataSegment); - st_showUserStackSegment = settings.value("ShowUserStackSeg", true).toBool(); - ui->action_Data_DisplayUserStack->setChecked(st_showUserStackSegment); - st_showKernelDataSegment = settings.value("ShowKernelDataSeg", true).toBool(); - ui->action_Data_DisplayKernelData->setChecked(st_showKernelDataSegment); - st_dataSegmentDisplayBase = settings.value("DataSegmentDisplayBase", 16).toInt(); - st_dataSegmentDisplayBase = setCheckedDataSegmentDisplayBase(st_dataSegmentDisplayBase); - - ui->action_Win_DataSegment->setChecked(!ui->DataSegDockWidget->isHidden()); - settings.endGroup(); - - - settings.beginGroup("FileMenu"); - st_recentFilesLength = settings.value("RecentFilesLength", 4).toInt(); - st_recentFiles.clear(); - int i; - for (i = 0; i < st_recentFilesLength; i++) - { - QString file = settings.value("RecentFile" + QString(i), "").toString(); - st_recentFiles.append(file); - } - rebuildRecentFilesMenu(); - settings.endGroup(); - - - settings.beginGroup("Spim"); - quiet = settings.value("Quiet", false).toBool(); - - bare_machine = settings.value("BareMachine", 0).toBool(); - accept_pseudo_insts = settings.value("AcceptPseudoInsts", 1).toBool(); - delayed_branches = settings.value("DelayedBranches", 0).toBool(); - delayed_loads = settings.value("DelayedLoads", 0).toBool(); - mapped_io = settings.value("MappedIO", 0).toBool(); - - st_loadExceptionHandler = settings.value("LoadExceptionHandler", true).toBool(); - st_exceptionHandlerFileName = settings.value("ExceptionHandlerFileName", - stdExceptionHandler).toString(); - st_startAddress = settings.value("StartingAddress", starting_address()).toInt(); - st_commandLine = settings.value("CommandLineArguments", "").toString(); - settings.endGroup(); -} - - -void SpimView::writeSettings(bool omitWindowState) -{ - if (!omitWindowState){ - settings.beginGroup("MainWin"); - settings.setValue("Geometry", saveGeometry()); - settings.setValue("WindowState", saveState(1)); - settings.endGroup(); - } - - - settings.beginGroup("RegWin"); - settings.setValue("ColorChangedRegs", st_colorChangedRegisters); - settings.setValue("ChangedRegColor", st_changedRegisterColor); - settings.setValue("RegisterDisplayBase", st_regDisplayBase); - - settings.setValue("Font", st_regWinFont); - settings.setValue("FontColor", st_regWinFontColor); - settings.setValue("BackgroundColor", st_regWinBackgroundColor); - settings.endGroup(); - - - settings.beginGroup("TextWin"); - settings.setValue("ShowUserTextSeg", st_showUserTextSegment); - settings.setValue("ShowKernelTextSeg", st_showKernelTextSegment); - settings.setValue("ShowTextComments", st_showTextComments); - settings.setValue("ShowInstDisassembly", st_showTextDisassembly); - - settings.setValue("Font", st_textWinFont); - settings.setValue("FontColor", st_textWinFontColor); - settings.setValue("BackgroundColor", st_textWinBackgroundColor); - settings.endGroup(); - - - settings.beginGroup("DataWin"); - settings.setValue("ShowUserDataSeg", st_showUserDataSegment); - settings.setValue("ShowUserStackSeg", st_showUserStackSegment); - settings.setValue("ShowKernelDataSeg", st_showKernelDataSegment); - settings.setValue("DataSegmentDisplayBase", st_dataSegmentDisplayBase); - settings.endGroup(); - - settings.beginGroup("FileMenu"); - settings.setValue("RecentFilesLength", st_recentFilesLength); - int i; - for (i = 0; i < st_recentFilesLength; i++) - { - if (i < st_recentFiles.length()) - { - settings.setValue("RecentFile" + QString(i), st_recentFiles[i]); - } - else - { - settings.setValue("RecentFile" + QString(i), ""); - } - } - settings.endGroup(); - - - settings.beginGroup("Spim"); - settings.setValue("Quiet", quiet); - - settings.setValue("BareMachine", bare_machine); - settings.setValue("AcceptPseudoInsts", accept_pseudo_insts); - settings.setValue("DelayedBranches", delayed_branches); - settings.setValue("DelayedLoads", delayed_loads); - settings.setValue("MappedIO", mapped_io); - - settings.setValue("LoadExceptionHandler", st_loadExceptionHandler); - settings.setValue("ExceptionHandlerFileName", st_exceptionHandlerFileName); - settings.setValue("StartingAddress", st_startAddress); - settings.setValue("CommandLine", st_commandLine); - settings.endGroup(); - - settings.sync(); -} - - -// Restore windows to initial, default configuration. -// - -void SpimView::win_Restore() -{ - QMessageBox msgBox; - msgBox.setText("QtSpim will now exit. Restart QtSpim and the windows will be restored to default configuration."); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Abort); - msgBox.setDefaultButton(QMessageBox::Ok); - if (msgBox.exec() == QMessageBox::Ok) { - settings.beginGroup("MainWin"); - settings.remove("Geometry"); // Remove current window configuration - settings.remove("WindowState"); - settings.endGroup(); - - writeSettings(true); // Write settings without window config, so next startup will revert to default configuration - exit(1); - } -} diff --git a/spim-qtbase/QtSpim/texttextedit.h b/spim-qtbase/QtSpim/texttextedit.h deleted file mode 100644 index 492ea81..0000000 --- a/spim-qtbase/QtSpim/texttextedit.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include - -class textTextEdit : public QTextEdit -{ - Q_OBJECT - -public: - textTextEdit(); - void contextMenuEvent(QContextMenuEvent* event); - QAction* action_Context_SetBreakpoint; - QAction* action_Context_ClearBreakpoint; - -protected: - virtual void closeEvent(QCloseEvent* event); - virtual void hideEvent(QHideEvent* event); - virtual void showEvent(QShowEvent* event); - -private: - QPoint contextGlobalPos; - -public slots: - void setBreakpoint(); - void clearBreakpoint(); - int pcFromPos(QTextCursor* cursor); -}; diff --git a/spim-qtbase/QtSpim/textwin.cpp b/spim-qtbase/QtSpim/textwin.cpp deleted file mode 100644 index 7939db2..0000000 --- a/spim-qtbase/QtSpim/textwin.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spimview.h" -#include "ui_spimview.h" -# - -#include -#include -#include -#define QT_USE_FAST_CONCATENATION - - -// -// Text segment window -// - -void SpimView::DisplayTextSegments(bool force) -{ - if (force || text_modified) - { - textTextEdit* te = ui->TextSegDockWidget->findChild("TextSegmentTextEdit"); - - te->clear(); - QString windowContents = windowFormattingStart(st_textWinFont, st_textWinFontColor, st_textWinBackgroundColor) - % formatUserTextSeg() - % formatKernelTextSeg() - % windowFormattingEnd(); - te->insertHtml(windowContents); - highlightInstruction(PC); - } - text_modified = false; -} - - -QString SpimView::formatUserTextSeg() -{ - if (st_showUserTextSegment) - { - return formatSegLabel("User Text Segment", TEXT_BOT, text_top) - % formatInstructions(TEXT_BOT, text_top); - } - else - { - return QString(""); - } -} - - -QString SpimView::formatKernelTextSeg() -{ - if (st_showKernelTextSegment) - { - return formatSegLabel("Kernel Text Segment", K_TEXT_BOT, k_text_top) - % formatInstructions(K_TEXT_BOT, k_text_top); - } - else - { - return QString(""); - } -} - - -QString breakpointMark() -{ - return QString("N "); -} - - -QString SpimView::formatInstructions(mem_addr from, mem_addr to) -{ - str_stream ss; - mem_addr a; - QString windowContents; - - ss_init(&ss); - for (a = from; a < to; a += 4) - { - instruction *inst = read_mem_inst(a); - if (inst != NULL) - { - format_an_inst(&ss, inst, a); - - char* pc = ss_to_string(&ss); - char* binInst = pc + 14; - char* disassembly = binInst + 11; - char* comment = NULL; - - pc += 3; - pc[8] = '\0'; - binInst += 1; - binInst[8] = '\0'; - comment = strstr(disassembly, ";"); - if (comment != NULL) - { - char* s; - for (s = comment - 1; *s == ' '; s--) - ; - *(s + 1) = '\0'; - } - if (inst_is_breakpoint(a)) - { - windowContents += QString(breakpointMark()); - } - windowContents += QString("[") % QString(pc) % QString("] ") - % (st_showTextDisassembly ? QString(binInst) : QString("")) - % nnbsp(2) % QString("") % QString(disassembly) % QString("") - % nnbsp(25 - strlen(disassembly)) - % (comment != NULL && st_showTextComments - ? QString("") % QString(comment) % QString("") - : QString("")) - % QString("
    "); - ss_clear(&ss); - } - } - - return windowContents; -} - - -void SpimView::highlightInstruction(mem_addr pc) -{ - QTextEdit* te = ui->TextSegDockWidget->findChild("TextSegmentTextEdit"); - QTextCursor cursor(te->document()); - - QRegExp rx("\\[" + formatAddress(pc) + "\\]"); // Start of specific line - cursor = te->document()->find(rx, cursor); - if (!cursor.isNull()) - { - cursor.select(QTextCursor::LineUnderCursor); - QString l = cursor.selectedText(); - - QTextCharFormat format; - format.setBackground(QBrush(Qt::cyan)); - - QTextEdit::ExtraSelection es; - es.cursor = cursor; - es.format = format; - QList ess; - ess << es; - te->setExtraSelections(ess); - - te->setTextCursor(cursor); - te->ensureCursorVisible(); - } -} - - -// -// Breakpoint -// - -textTextEdit::textTextEdit() -{ - action_Context_SetBreakpoint = new QAction(this); - action_Context_SetBreakpoint->setObjectName("action_SetBreakpoint"); - action_Context_SetBreakpoint->setText("Set Breakpoint"); - - action_Context_ClearBreakpoint = new QAction(this); - action_Context_ClearBreakpoint->setObjectName("action_ClearBreakpoint"); - action_Context_ClearBreakpoint->setText("Clear Breakpoint"); -} - - -void textTextEdit::contextMenuEvent(QContextMenuEvent* event) -{ - QMenu *menu = createStandardContextMenu(); - menu->addSeparator(); - menu->addAction(action_Context_SetBreakpoint); - menu->addAction(action_Context_ClearBreakpoint); - contextGlobalPos = event->globalPos(); - - menu->exec(event->globalPos()); -} - - -void textTextEdit::setBreakpoint() -{ - QTextCursor cursor; - mem_addr pc = pcFromPos(&cursor); - if (pc != 0 && !inst_is_breakpoint(pc)) - { - add_breakpoint(pc); - - cursor.setPosition(cursor.anchor()); - cursor.insertHtml(breakpointMark()); - update(); - } -} - - -void textTextEdit::clearBreakpoint() -{ - QTextCursor cursor; - mem_addr pc = pcFromPos(&cursor); - if (pc != 0 && inst_is_breakpoint(pc)) - { - delete_breakpoint(pc); - - cursor.setPosition(cursor.anchor()); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 2); - cursor.removeSelectedText(); - update(); - } -} - - -int textTextEdit::pcFromPos(QTextCursor* cursor) -{ - // Position of context menu is location user right-click. Find the line at this point - // extract the pc. - // - QPoint mouseViewportPos = this->viewport()->mapFromGlobal(contextGlobalPos); - - *cursor = this->cursorForPosition(mouseViewportPos); - cursor->select(QTextCursor::LineUnderCursor); - QString line = cursor->selectedText(); - - QRegExp rx("\\[([0-9a-fA-F]{8})\\]"); // Address of instruction - - rx.indexIn(line); - QString pcStr = rx.cap(1); - if (pcStr != "") - { - bool ok; - mem_addr pc = pcStr.toUInt(&ok, 16); - return (ok ? pc : 0); - } - return 0; -} - - -void textTextEdit::closeEvent(QCloseEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - Window->ui->action_Win_TextSegment->setChecked(false); - } - event->accept(); -} - - -void textTextEdit::hideEvent(QHideEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - Window->ui->action_Win_TextSegment->setChecked(false); - } - event->accept(); -} - - -void textTextEdit::showEvent(QShowEvent* event) -{ - if (Window != NULL) // Event can occur while window is being constructed; ignore in that case - { - Window->ui->action_Win_TextSegment->setChecked(true); - } - event->accept(); -} diff --git a/spim-qtbase/QtSpim/windows_images.qrc b/spim-qtbase/QtSpim/windows_images.qrc deleted file mode 100644 index 9f31b58..0000000 --- a/spim-qtbase/QtSpim/windows_images.qrc +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - windows_images/ClearRegs.png - windows_images/Help.png - windows_images/LoadFile.png - windows_images/Pause.png - windows_images/Print.png - windows_images/Reinit.png - windows_images/ReloadFile.png - windows_images/Run.png - windows_images/SaveLog.png - windows_images/Settings.png - windows_images/SingleStep.png - windows_images/Stop.png - windows_images/qtspim.png - - diff --git a/spim-qtbase/README b/spim-qtbase/README deleted file mode 100644 index 645e645..0000000 --- a/spim-qtbase/README +++ /dev/null @@ -1,49 +0,0 @@ - README FILE FOR SPIM - ==================== - -This directory contains part of SPIM--an assembly language MIPS R2000/R3000 -simulator. It contains the terminal interface to SPIM. - -SPIM is covered by a BSD license. - -Copyright (c) 1990-2010, James R. Larus. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -Neither the name of the James R. Larus nor the names of its contributors may be -used to endorse or promote products derived from this software without specific -prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -The files in this directory are: - -README - This file. - -Makefile - Makefile to build the terminal version of spim. This Makefile works - for Unix and on Microsoft Windows under Cygwin. - -spim.c - Terminal interface to spim. diff --git a/spim-qtbase/Tests/read.s b/spim-qtbase/Tests/read.s deleted file mode 100644 index d5d4e6b..0000000 --- a/spim-qtbase/Tests/read.s +++ /dev/null @@ -1,50 +0,0 @@ -# Read a string -# -# -# Copyright (c) 1990-2011, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - .data -m1: .asciiz "Read next line\n" - .text - .globl main -main: - - li $v0 4 # syscall 4 (print_str) - la $a0 m1 - syscall - - li $v0 8 # syscall 8 (read_string) - syscall - - li $v0 4 # syscall 4 (print_str) - syscall - - jr $ra - diff --git a/spim-qtbase/Tests/time.s b/spim-qtbase/Tests/time.s deleted file mode 100644 index e3962c9..0000000 --- a/spim-qtbase/Tests/time.s +++ /dev/null @@ -1,57 +0,0 @@ -# Simple loop to test execution speed -# -# -# Copyright (c) 1990-2011, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - .data -m1: .asciiz "Hit return to start timing\n" -m2: .asciiz "Done with timing\n" - .text - .globl main -main: - - li $v0 4 # syscall 4 (print_str) - la $a0 m1 - syscall - - li $v0 5 # syscall 5 (read_int) - syscall - - li $t0 10000000 -loop: xor $t1 $t1 $t1 - sub $t0 1 - bnez $t0 loop - - li $v0 4 # syscall 4 (print_str) - la $a0 m2 - syscall - - jr $ra - diff --git a/spim-qtbase/Tests/timer.s b/spim-qtbase/Tests/timer.s deleted file mode 100644 index f1a3982..0000000 --- a/spim-qtbase/Tests/timer.s +++ /dev/null @@ -1,50 +0,0 @@ - .text - .globl main -main: - # allow hardware interrupts - mfc0 $t0, $12 # get status register - ori $t0, $t0, 0xff01 - mtc0 $t0, $12 - - # set up a timer - li $t0, 5 # get a timer interrupt every second - mtc0 $t0, $11 # set up compare register - mtc0 $zero, $9 - -forever: - addi $s0, $s0, 1 # 1,2,3,4,... - j forever - - jr $ra - -#--- END MAIN - - - .kdata -save0: .word 0 -save1: .word 0 - -msg: .asciiz "\nGot a timer interrupt\n" - - .ktext 0x80000180 -timer_handler: - sw $a0 save0 - sw $v0 save1 - - li $v0, 4 # print a message - la $a0, msg - syscall - - # reset timer - li $t0, 100 # get a timer interrupt every second - mtc0 $t0, $11 # set up compare register - mtc0 $zero, $9 - - lw $a0 save0 - lw $v0 save1 - - mtc0 $zero $13 # Clear Cause register - mfc0 $k0 $12 # Set Status register - ori $k0 0x1 # Interrupts enabled - mtc0 $k0 $12 - eret diff --git a/spim-qtbase/Tests/tt.alu.bare.s b/spim-qtbase/Tests/tt.alu.bare.s deleted file mode 100755 index 30bb78d..0000000 --- a/spim-qtbase/Tests/tt.alu.bare.s +++ /dev/null @@ -1,1852 +0,0 @@ -# SPIM S20 MIPS simulator. -# A torture test for the ALU instructions in the bare SPIM simulator. -# Copyright (c) 1990-2010, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -# Adapted by Anne Rogers from tt.le.s. -# Run -bare -notrap. - -# IMPORTANT!!! -# This file only works on little-endian machines. -# - -# Test ALU instructions. - -# WARNING: This code is not relocatable. DO NOT add instructions without -# changing test code for JAL, JALR, BGEZAL, BLTZAL. Add new "data" statements -# only at after "Passed all tests\n". - - - .data -saved_ret_pc: .word 0 # Holds PC to return from main -sm: .asciiz "Failed " - .text -# Standard startup code. Invoke the routine main with no arguments. - .globl __start -__start: jal main - addu $0 $0 $0 # Nop - addiu $2 $0 10 - syscall # syscall 10 (exit) - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - - .globl main -main: - lui $4 0x1000 - sw $31 0($4) - -# -# Try modifying R0 -# - addi $0 $0 1 - -# -# Now, test each instruction -# - - .data -add_: .asciiz "Testing ADD\n" - .text - addi $2 $0 4 # syscall 4 (print_str) -# la $a0 add_ - lui $a0, 0x1000 - ori $a0 $a0 0xd - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - add $4 $0 $0 - bne $4 $0 fail - addu $0 $0 $0 # Nop - add $4 $0 $2 - bne $4 $2 fail - addu $0 $0 $0 # Nop - add $4 $4 $3 - bne $4 $0 fail - addu $0 $0 $0 # Nop - - .data -addi_: .asciiz "Testing ADDI\n" - .text - addi $2 $0 4 # syscall 4 (print_str) -# la $a0 addi_ - lui $a0, 0x1000 - ori $a0 $a0 0x1a - syscall - - addi $2 $0 1 - - addi $4 $0 0 - bne $4 $0 fail - addu $0 $0 $0 # Nop - addi $4 $0 1 - bne $4 $2 fail - addu $0 $0 $0 # Nop - addi $4 $4 -1 - bne $4 $0 fail - - - .data -addiu_: .asciiz "Testing ADDIU\n" - .text - addi $2 $0 4 # syscall 4 (print_str) -# la $a0 addiu_ - lui $a0, 0x1000 - ori $a0 $a0 0x28 - syscall - - addi $2 $0 1 - addiu $4 $0 0 - bne $4 $0 fail - addu $0 $0 $0 # Nop - addiu $4 $0 1 - bne $4 $2 fail - addu $0 $0 $0 # Nop - addiu $4 $4 -1 - bne $4 $0 fail - addu $0 $0 $0 # Nop - - lui $2 0x3fff - ori $2 $2 0xffff - addiu $2 $2 101 - - - .data -addu_: .asciiz "Testing ADDU\n" - .text - addi $2 $0 4 # syscall 4 (print_str) -# la $a0 addu_ - lui $a0, 0x1000 - ori $a0 $a0 0x37 - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - addu $4 $0 $0 - bne $4 $0 fail - addu $0 $0 $0 # Nop - addu $4 $0 $2 - bne $4 $2 fail - addu $0 $0 $0 # Nop - addu $4 $4 $3 - bne $4 $0 fail - addu $0 $0 $0 # Nop - - - lui $2 0x3fff - ori $2 $2 0xffff - addu $2 $2 $2 - - - .data -and_: .asciiz "Testing AND\n" - .text - addi $2 $0 4 # syscall 4 (print_str) -# la $a0 and_ - lui $a0, 0x1000 - ori $a0 $a0 0x37 - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - and $4 $0 $0 - bne $4 $0 fail - addu $0 $0 $0 # Nop - and $4 $2 $2 - beq $4 $0 fail - addu $0 $0 $0 # Nop - and $4 $2 $3 - bne $4 $2 fail - - - .data -andi_: .asciiz "Testing ANDI\n" - .text - addi $2 $0 4 # syscall 4 (print_str) -# la $a0 andi_ - lui $a0, 0x1000 - ori $a0 $a0 0x52 - syscall - - addi $2 $0 1 - addi $3 $0 -1 - addi $5 $0 -1 - - andi $4 $0 0 - bne $4 $0 fail - addu $0 $0 $0 # Nop - and $4 $2 1 - beq $4 $0 fail - addu $0 $0 $0 # Nop - and $4 $2 $5 - bne $4 $2 fail - addu $0 $0 $0 # Nop - and $4 $3 $5 - bne $4 $3 fail - addu $0 $0 $0 # Nop - - - .data -beq_: .asciiz "Testing BEQ\n" - .text - add $v0 $0 4 # syscall 4 (print_str) -# la $a0 beq_ - lui $a0, 0x1000 - ori $a0 $a0 0x60 - syscall - - add $2 $0 -1 - add $3 $0 1 - - beq $0 $0 l1 -# j fail - addu $0 $0 $0 # Nop -l1: beq $2 $2 l2 -# j fail - addu $0 $0 $0 # Nop -l2: beq $3 $2 fail - addu $0 $0 $0 # Nop - - addi $2 $0 3 -l2_1: sub $2 $2 $3 - bne $2 $0 l2_1 - addu $0 $0 $0 # Nop - - - .data -bgez_: .asciiz "Testing BGEZ\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 bgez_ - lui $a0, 0x1000 - ori $a0 $a0 0x6d - - syscall - - addi $2 $0 -1 - addi $3 $0 1 - - bgez $0 l3 - addu $0 $0 $0 # Nop - j fail -l3: bgez $3 l4 - addu $0 $0 $0 # Nop - j fail -l4: bgez $2 fail - addu $0 $0 $0 # Nop - - .data -bgtz_: .asciiz "Testing BGTZ\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 bgtz_ - lui $a0, 0x1000 - ori $a0 $a0 0x7b - syscall - - addi $2 $0 -1 - addi $3 $0 1 - - bgtz $0 fail - addu $0 $0 $0 # Nop -l7: bgtz $3 l8 - addu $0 $0 $0 # Nop - j fail -l8: bgtz $2 fail - addu $0 $0 $0 # Nop - - .data -blez_: .asciiz "Testing BLEZ\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 blez_ - lui $a0, 0x1000 - ori $a0 $a0 0x89 - syscall - - addi $2 $0 -1 - addi $3 $0 1 - - blez $0 l9 - addu $0 $0 $0 # Nop - j fail -l9: blez $2 l10 - addu $0 $0 $0 # Nop - j fail -l10: blez $3 fail - addu $0 $0 $0 # Nop - - .data -bltz_: .asciiz "Testing BLTZ\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 bltz_ - lui $a0, 0x1000 - ori $a0 $a0 0x97 - - syscall - - addi $2 $0 -1 - addi $3 $0 1 - - bltz $0 fail - addu $0 $0 $0 # Nop -l11: bltz $2 l12 - addu $0 $0 $0 # Nop - j fail -l12: bltz $3 fail - addu $0 $0 $0 # Nop - - .data -bne_: .asciiz "Testing BNE\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 bne_ - lui $a0, 0x1000 - ori $a0 $a0 0xa5 - syscall - - addi $2 $0 -1 - addi $3 $0 1 - - bne $0 $0 fail - addu $0 $0 $0 # Nop - bne $2 $2 fail - addu $0 $0 $0 # Nop - bne $3 $2 l16 - addu $0 $0 $0 # Nop -l16: - addu $0 $0 $0 # Nop - - .data -j_: .asciiz "Testing J\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 j_ - lui $a0, 0x1000 - ori $a0 $a0 0xb2 - syscall - - j l17 - j fail -l17: addu $0 $0 $0 # Nop - - - .data -lb_: .asciiz "Testing LB\n" -# lb2_: .asciiz "Expect a address error exceptions:\n " -lbd_: .byte 1, -1, 0, 128 -lbd1_: .word 0x76543210, 0xfedcba98 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lb_ - lui $a0, 0x1000 - ori $a0 $a0 0xbd - - syscall - -# la $2 lbd_ - lui $2, 0x1000 - ori $2 $2 0xc9 - lb $3 0($2) - addu $4 $0 1 - bne $3 $4 fail - lb $3 1($2) - addi $4 $0 -1 - bne $3 $4 fail - lb $3 2($2) - addu $0 $0 $0 # Nop - bne $3 $0 fail - lb $3 3($2) - lui $4 0xffff - ori $4 0xff80 - bne $3 $4 fail - -# la $t0 lbd1_ - lui $t0, 0x1000 - ori $t0 $t0 0xd0 - lb $t1 0($t0) - addi $4 $0 0x10 - bne $t1 $4 fail - lb $t1 1($t0) - addi $4 $0 0x32 - bne $t1 $4 fail - lb $t1 2($t0) - addi $4 $0 0x54 - bne $t1 $4 fail - lb $t1 3($t0) - addi $4 $0 0x76 - bne $t1 $4 fail - lb $t1 4($t0) - lui $4 0xffff - addi $4 $0 0xff98 - bne $t1 $4 fail - lb $t1 5($t0) - lui $4 0xffff - addi $4 $0 0xffba - bne $t1 $4 fail - lb $t1 6($t0) - lui $4 0xffff - addi $4 $0 0xffdc - bne $t1 $4 fail - lb $t1 7($t0) - lui $4 0xffff - addi $4 $0 0xfffe - bne $t1 $4 fail - -# li $v0 4 # syscall 4 (print_str) -# la $a0 lb2_ -# syscall -# -# lb $3 1000000($sp) - - - .data -lbu_: .asciiz "Testing LBU\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lbu_ - lui $a0, 0x1000 - ori $a0 $a0 0xd8 - syscall - -# la $2 lbd_ - lui $2, 0x1000 - ori $2 $2 0xc9 - - lbu $3 0($2) - addi $4 $0 1 - bne $3 $4 fail - lbu $3 1($2) - addi $4 $0 0xff - bne $3 $4 fail - lbu $3 2($2) - addu $0 $0 $0 # Nop - bne $3 $0 fail - lbu $3 3($2) - addu $4 $0 128 - bne $3 $4 fail - -# la $t0 lbd1_ - lui $t0, 0x1000 - ori $t0 $t0 0xd0 - - lbu $t1 0($t0) - addi $4 $0 0x10 - bne $t1 $4 fail - lbu $t1 1($t0) - addi $4 $0 0x32 - bne $t1 $4 fail - lbu $t1 2($t0) - addi $4 $0 0x54 - bne $t1 $4 fail - lbu $t1 3($t0) - addi $4 $0 0x76 - bne $t1 $4 fail - lbu $t1 4($t0) - addi $4 $0 0x98 - bne $t1 $4 fail - lbu $t1 5($t0) - addi $4 $0 0xba - bne $t1 $4 fail - lbu $t1 6($t0) - addi $4 $0 0xdc - bne $t1 $4 fail - lbu $t1 7($t0) - addi $4 $0 0xfe - bne $t1 $4 fail - addu $0 $0 $0 # Nop - -# Causes an exception -- do later. -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lb2_ -# syscall -# -# lbu $3 1000000($sp) - - - .data -lh_: .asciiz "Testing LH\n" -#lh2_: .asciiz "Expect two address error exceptions:\n " -lhd_: .half 1, -1, 0, 0x8000 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lh_ - lui $a0, 0x1000 - ori $a0 $a0 0xe5 - syscall - -# la $2 lhd_ - lui $2, 0x1000 - ori $2 $2 0xf2 - lh $3 0($2) - addi $4 $0 1 - bne $3 $4 fail - lh $3 2($2) - addi $4 $0 -1 - bne $3 $4 fail - lh $3 4($2) - addi $4 $0 0 - bne $3 $4 fail - lh $3 6($2) - lui $4 0xffff - ori $4 $4 0x8000 - bne $3 $4 fail - addu $0 $0 $0 # Nop - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lh2_ -# syscall -# -# lh $3 1000000($sp) -# lh $3 1000001($sp) - - .data -lhu_: .asciiz "Testing LHU\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lhu_ - lui $a0, 0x1000 - ori $a0 $a0 0xfa - syscall - -# la $2 lhd_ - lui $2, 0x1000 - ori $2 $2 0xf2 - lhu $3 0($2) - addi $4 $0 1 - bne $3 $4 fail - lhu $3 2($2) - ori $4 $0 0xffff - bne $3 $4 fail - lhu $3 4($2) - addi $4 $0 0 - bne $3 $4 fail - lhu $3 6($2) - ori $4 $0 0x8000 - bne $3 $4 fail - addu $0 $0 $0 #Nop - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lh2_ -# syscall -# -# lhu $3 1000000($sp) -# lhu $3 1000001($sp) - - - .data -lui_: .asciiz "Testing LUI\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lui_ - lui $a0, 0x1000 - ori $a0 $a0 0x107 - syscall - - lui $2 0 - bne $2 $0 fail - lui $2 1 - srl $2 $2 16 - addiu $2 $2 -1 # Don't do compare directly since it uses LUI - bne $2 $0 fail - lui $2 1 - andi $2 $2 0xffff - bne $2 $0 fail - lui $2 -1 - srl $2 $2 16 - addiu $2 $2 1 - andi $2 $2 0xffff - bne $2 $0 fail - addu $0 $0 $0 #Nop - - .data -lw_: .asciiz "Testing LW\n" -lwd_: .word 1, -1, 0, 0x8000000 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lw_ - lui $a0, 0x1000 - ori $a0 $a0 0x114 - syscall - -# la $2 lwd_ - lui $2, 0x1000 - ori $2 $2 0x120 - lw $3 0($2) - addi $4 $0 1 - bne $3 $4 fail - lw $3 4($2) - addi $4 $0 -1 - bne $3 $4 fail - lw $3 8($2) - addi $4 $0 0 - bne $3 $4 fail - lw $3 12($2) - lui $4 0x800 - ori $4 $4 0x0000 - bne $3 $4 fail - - add $2 $2 12 - lw $3 -12($2) - addi $4 $0 1 - bne $3 $4 fail - lw $3 -8($2) - addi $4 $0 -1 - bne $3 $4 fail - lw $3 -4($2) - addi $4 $0 0 - bne $3 $4 fail - lw $3 0($2) - lui $4 0x800 - ori $4 $4 0x0000 - bne $3 $4 fail - addu $0 $0 $0 #Nop - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lh2_ -# syscall -# -# lw $3 1000000($sp) -# lw $3 1000001($sp) - - .data -lwl_: .asciiz "Testing LWL\n" - .align 2 -lwld_: .byte 0 1 2 3 4 5 6 7 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lwl_ - lui $a0, 0x1000 - ori $a0 $a0 0x130 - syscall - -# la $2 lwld_ - lui $2, 0x1000 - ori $2 $2 0x140 - addu $3 $0 $0 # Move $3 $0 - lwl $3 0($2) - addi $4 $0 0 - bne $3 $4 fail - addu $3 $0 $0 # Move $3 $0 - lwl $3 1($2) - lui $4 0x0100 - ori $4 $4 0x0000 - bne $3 $4 fail - addi $3 $0 5 - lwl $3 1($2) - lui $4 0x0100 - ori $4 $4 0x0005 - bne $3 $4 fail - addu $3 $0 $0 # Move $3 $0 - lwl $3 2($2) - lui $4 0x0201 - ori $4 $4 0x0000 - bne $3 $4 fail - addi $3 $0 5 - lwl $3 2($2) - lui $4 0x0201 - ori $4 $4 0x0005 - bne $3 $4 fail - addu $3 $0 $0 # Move $3 $0 - lwl $3 3($2) - lui $4 0x0302 - ori $4 $4 0x0100 - bne $3 $4 fail - addi $3 $0 5 - lwl $3 3($2) - lui $4 0x0302 - ori $4 $4 0x0100 - bne $3 $4 fail - addu $0 $0 $0 # Nop - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lh2_ -# syscall -# -# lwl $3 1000000($sp) -# lwl $3 1000001($sp) - - - - .data -lwr_: .asciiz "Testing LWR\n" - .align 2 -lwrd_: .byte 0 1 2 3 4 5 6 7 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lwr_ - lui $a0, 0x1000 - ori $a0 $a0 0x148 - syscall - -# la $2 lwrd_ - lui $2, 0x1000 - ori $2 $2 0x158 - - lui $3 0x0000 - ori $3 $3 0x0500 - lwr $3 0($2) - lui $4 0x0302 - ori $4 $4 0x0100 - bne $3 $4 fail - addu $3 $0 $0 # Move $3 $0 - lwr $3 1($2) - lui $4 0x0003 - ori $4 $4 0x0201 - bne $3 $4 fail - lui $3 0x5000 - ori $3 $3 0x0000 - lwr $3 1($2) - lui $4 0x5003 - ori $4 $4 0x0201 - bne $3 $4 fail - addu $3 $0 $0 # Move $3 $0 - lwr $3 2($2) - ori $4 $0 0x0302 - bne $3 $4 fail - lui $3 0x5000 - ori $3 $3 0x0000 - lwr $3 2($2) - lui $4 0x5000 - ori $4 $4 0x0302 - bne $3 $4 fail - addu $0 $0 $0 # Nop - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lh2_ -# syscall -# -# lwr $3 1000000($sp) -# lwr $3 1000001($sp) - - .data -nor_: .asciiz "Testing NOR\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 nor_ - lui $a0, 0x1000 - ori $a0 $a0 0x160 - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - nor $4 $0 $0 - addi $5 $0 -1 - bne $4 $5 fail - nor $4 $2 $2 - lui $5 0xffff - ori $5 $5 0xfffe - bne $4 $5 fail - nor $4 $2 $3 - bne $4 $0 fail - addu $0 $0 $0 #Nop - - .data -or_: .asciiz "Testing OR\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 or_ - lui $a0, 0x1000 - ori $a0 $a0 0x16d - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - or $4 $0 $0 - bne $4 $0 fail - or $4 $2 $2 - addi $5 $0 1 - bne $4 $5 fail - or $4 $2 $3 - addi $5 $0 -1 - bne $4 $5 fail - addu $0 $0 $0 #Nop - - - .data -ori_: .asciiz "Testing ORI\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 ori_ - lui $a0, 0x1000 - ori $a0 $a0 0x179 - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - ori $4 $0 0 - bne $4 $0 fail - ori $4 $2 1 - addi $5 $0 1 - bne $4 $5 fail - ori $4 $3 -1 - lui $5 0xffff - ori $5 $5 0xffff - bne $4 $5 fail - addu $0 $0 $0 #Nop - - .data -sb_: .asciiz "Testing SB\n" -#sb2_: .asciiz "Expect a address error exceptions:\n " - .align 2 -sbd_: .byte 0, 0, 0, 0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sb_ - lui $a0, 0x1000 - ori $a0 $a0 0x186 - syscall - - addi $3 $0, 1 -# la $2 sbd_ - lui $2, 0x1000 - ori $2 $2 0x194 - sb $3 0($2) - lw $4 0($2) - ori $5 $0 0x1 - bne $4 $5 fail - addi $3 $0 2 - sb $3 1($2) - lw $4 0($2) - ori $5 $0 0x201 - bne $4 $5 fail - addi $3 $0 3 - sb $3 2($2) - lw $4 0($2) - lui $5 0x3 - ori $5 $5 0x0201 - bne $4 $5 fail - addi $3 $0 4 - sb $3 3($2) - lw $4 0($2) - lui $5 0x0403 - ori $5 $5 0x0201 - bne $4 $5 fail - addu $0 $0 $0 #Nop - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sb2_ -# syscall -# -# sb $3 1000000($sp) - - -# RFE tested previously - - .data -sh_: .asciiz "Testing SH\n" -#sh2_: .asciiz "Expect two address error exceptions:\n " - .align 2 -shd_: .byte 0, 0, 0, 0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sh_ - lui $a0, 0x1000 - ori $a0 $a0 0x198 - syscall - - addi $3 $0, 1 -# la $2 shd_ - lui $2, 0x1000 - ori $2 $2 0x1a4 - - sh $3 0($2) - lw $4 0($2) - ori $5 $0 0x1 - bne $4 $5 fail - addi $3 $0 2 - sh $3 2($2) - lw $4 0($2) - lui $5 0x2 - ori $5 $5 0x0001 - bne $4 $5 fail - addu $0 $0 $0 #Nop - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sh2_ -# syscall -# -# sh $3 1000000($sp) -# sh $3 1000001($sp) - - .data -sll_: .asciiz "Testing SLL\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sll_ - lui $a0, 0x1000 - ori $a0 $a0 0x1a8 - syscall - - addi $2 $0 1 - - sll $3 $2 0 - ori $4 $0 1 - bne $3 $4 fail - sll $3 $2 1 - ori $4 $0 2 - bne $3 $4 fail - sll $3 $2 16 - lui $4 0x1 - ori $4 $4 0x0000 - bne $3 $4 fail - sll $3 $2 32 - ori $4 $0 1 - bne $3 $4 fail - addu $0 $0 $0 # Nop - - .data -sllv_: .asciiz "Testing SLLV\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sllv_ - lui $a0, 0x1000 - ori $a0 $a0 0x1b5 - syscall - - addi $2 $0 1 - addi $4 $0 0 - sllv $3 $2 $4 - ori $5 $0 1 - bne $3 $5 fail - addi $4 $0 1 - sllv $3 $2 $4 - ori $5 $0 2 - bne $3 $5 fail - addi $4 $0 16 - sllv $3 $2 $4 - lui $5 0x1 - ori $5 $5 0x0000 - bne $3 $5 fail - addi $4 $0 32 - sllv $3 $2 $4 - ori $5 $0 1 - bne $3 $5 fail - addu $0 $0 $0 # Nop - - .data -slt_: .asciiz "Testing SLT\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 slt_ - lui $a0, 0x1000 - ori $a0 $a0 0x1c3 - syscall - - ori $5 $0 1 - - slt $3 $0 $0 - bne $3 $0 fail - addi $2 $0 1 - slt $3 $2 $0 - bne $3 $0 fail - slt $3 $0 $2 - bne $3 $5 fail - addi $2 $0 -1 - slt $3 $2 $0 - bne $3 $5 fail - slt $3 $0 $2 - bne $3 $0 fail - addi $2 $0 -1 - addi $4 $0 1 - slt $3 $2 $4 - bne $3 $5 fail - addu $0 $0 $0 # Nop - - .data -slti_: .asciiz "Testing SLTI\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 slti_ - lui $a0, 0x1000 - ori $a0 $a0 0x1d0 - syscall - - ori $5 $0 1 - - slti $3 $0 0 - bne $3 $0 fail - addi $2 $0 1 - slti $3 $2 0 - bne $3 $0 fail - slti $3 $0 1 - bne $3 $5 fail - addi $2 $0 -1 - slti $3 $2 0 - bne $3 $5 fail - slti $3 $0 -1 - bne $3 $0 fail - addi $2 $0 -1 - addi $4 $0 1 - slti $3 $2 1 - bne $3 $5 fail - slti $3 $4 -1 - bne $3 $0 fail - addu $0 $0 $0 # Nop - - - .data -sltiu_: .asciiz "Testing SLTIU\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sltiu_ - lui $a0, 0x1000 - ori $a0 $a0 0x1de - syscall - - ori $5 $0 1 - - sltiu $3 $0 0 - bne $3 $0 fail - addi $2 $0 1 - sltiu $3 $2 0 - bne $3 $0 fail - sltiu $3 $0 1 - bne $3 $5 fail - addi $2 $0 -1 - sltiu $3 $2 0 - bne $3 $0 fail - sltiu $3 $0 -1 - bne $3 $5 fail - addi $2 $0 -1 - addi $4 $0 1 - sltiu $3 $2 1 - bne $3 $0 fail - sltiu $3 $4 -1 - bne $3 $5 fail - addu $0 $0 $0 # Nop - - - .data -sltu_: .asciiz "Testing SLTU\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sltu_ - lui $a0, 0x1000 - ori $a0 $a0 0x1ed - syscall - - ori $5 $0 1 - - sltu $3 $0 $0 - bne $3 $0 fail - addi $2 $0 1 - sltu $3 $2 $0 - bne $3 $0 fail - sltu $3 $0 $2 - bne $3 $5 fail - addi $2 $0 -1 - sltu $3 $2 $0 - bne $3 $0 fail - sltu $3 $0 $2 - bne $3 $5 fail - addi $2 $0 -1 - addi $4 $0 1 - sltu $3 $2 $4 - bne $3 $0 fail - addu $0 $0 $0 # Nop - - .data -sra_: .asciiz "Testing SRA\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sra_ - lui $a0, 0x1000 - ori $a0 $a0 0x1fb - syscall - - addi $2 $0 1 - sra $3 $2 0 - ori $5 $0 1 - bne $3 $5 fail - sra $3 $2 1 - bne $3 $0 fail - addi $2 $0 0x1000 - sra $3 $2 4 - ori $5 $0 0x100 - bne $3 $5 fail - lui $5 0x8000 - ori $5 $5 0x0000 - add $2 $0 $5 - sra $3 $2 4 - lui $5 0xf800 - ori $5 $5 0x0000 - bne $3 $5 fail - addu $0 $0 $0 # Nop - - .data -srav_: .asciiz "Testing SRAV\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 srav_ - lui $a0, 0x1000 - ori $a0 $a0 0x208 - syscall - - addi $2 $0 1 - addi $4 $0 0 - srav $3 $2 $4 - ori $5 $0 1 - bne $3 $5 fail - addi $4 $0 1 - srav $3 $2 $4 - bne $3 $0 fail - addi $2 $0 0x1000 - addi $4 $0 4 - srav $3 $2 $4 - ori $5 $0 0x100 - bne $3 $5 fail - lui $5 0x8000 - ori $5 $5 0x0000 - add $2 $0 $5 - addi $4 $0 4 - srav $3 $2 $4 - lui $5 0xf800 - ori $5 $5 0x0000 - bne $3 $5 fail - addu $0 $0 $0 # Nop - - - - .data -srl_: .asciiz "Testing SRL\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 srl_ - lui $a0, 0x1000 - ori $a0 $a0 0x216 - syscall - - addi $2 $0 1 - srl $3 $2 0 - ori $5 $0 1 - bne $3 $5 fail - srl $3 $2 1 - bne $3 $0 fail - addi $2 $0 0x1000 - srl $3 $2 4 - ori $5 $0 0x100 - bne $3 $5 fail - lui $5 0x8000 - ori $5 $0 0x0000 - add $2 $0 $5 - srl $3 $2 4 - lui $5 0x0800 - ori $5 $0 0x0000 - bne $3 $5 fail - addu $0 $0 $0 #Nop - - - .data -srlv_: .asciiz "Testing SRLV\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 srlv_ - lui $a0, 0x1000 - ori $a0 $a0 0x223 - syscall - - addi $2 $0 1 - addi $4 $0 0 - srlv $3 $2 $4 - ori $5 $0 1 - bne $3 $5 fail - addi $4 $0 1 - srlv $3 $2 $4 - bne $3 $0 fail - addi $2 $0 0x1000 - addi $4 $0 4 - srlv $3 $2 $4 - ori $5 $0 0x100 - bne $3 $5 fail - lui $5 0x8000 - ori $5 $5 0x0000 - add $2 $0 $5 - addi $4 $0 4 - srlv $3 $2 $4 - lui $5 0x0800 - ori $5 $5 0x0000 - bne $3 $5 fail - addu $0 $0 $0 # Nop - - - .data -sub_: .asciiz "Testing SUB\n" -# sub1_: .asciiz "Expect an overflow exceptions:\n " - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sub_ - lui $a0, 0x1000 - ori $a0 $a0 0x231 - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - sub $4, $0, $0 - bne $4 $0 fail - sub $4, $0, $2 - addi $5 $0 -1 - bne $4 $5 fail - sub $4, $2, $0 - ori $5 $0 1 - bne $4, $5 fail - sub $4, $2, $3 - ori $5 $0 2 - bne $4, $5 fail - sub $4, $3, $2 - addi $5 $0 -2 - bne $4, $5 fail - addu $0 $0 $0 # Nop - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sub1_ -# syscall -# addi $2 $0 0x80000000 -# addi $3 $0 1 -# sub $4, $3, $2 - - .data -subu_: .asciiz "Testing SUBU\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 subu_ - lui $a0, 0x1000 - ori $a0 $a0 0x23e - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - subu $4, $0, $0 - bne $4 $0 fail - subu $4, $0, $2 - addi $5 $0 -1 - bne $4 $5 fail - subu $4, $2, $0 - addi $5 $0 1 - bne $4, $5 fail - subu $4, $2, $3 - addi $5 $0 2 - bne $4, $5 fail - subu $4, $3, $2 - addi $5 $0 -2 - bne $4, $5 fail - - lui $5 0x8000 - ori $5 $5 0x0000 - add $2 $0 $5 - addi $3 $0 1 - subu $4, $3, $2 - - .data -sw_: .asciiz "Testing SW\n" -#sw2_: .asciiz "Expect two address error exceptions:\n " - .align 2 -swd_: .byte 0, 0, 0, 0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sw_ - lui $a0, 0x1000 - ori $a0 $a0 0x24c - syscall - -# addi $3 $0, 0x7f7f7f7f - lui $3 0x7f7f - ori $3 $3 0x7f7f -# la $2 swd_ - lui $2, 0x1000 - ori $2 $2 0x258 - sw $3 0($2) - lw $4 0($2) - lui $5 0x7f7f - ori $5 $5 0x7f7f - bne $4 $5 fail - -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sw2_ -# syscall -# -# sw $3 1000000($sp) -# sw $3 1000001($sp) - - - .data -swl_: .asciiz "Testing SWL\n" - .align 2 -swld_: .word 0 0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 swl_ - lui $a0, 0x1000 - ori $a0 $a0 0x25c - syscall - -# la $2 swld_ - lui $2, 0x1000 - ori $2 $2 0x26c -# addi $3 $0 0x01000000 - lui $3 0x0100 - ori $3 $3 0x0000 - swl $3 0($2) - lw $4 0($2) - ori $5 $0 0x1 - bne $4 $5 fail - -# addi $3 $0 0x01020000 - lui $3 0x0102 - ori $3 $3 0x0000 - swl $3 1($2) - lw $4 0($2) - ori $5 $0 0x0102 - bne $4 $5 fail - -# addi $3 $0 0x01020300 - lui $3 0x0102 - ori $3 $3 0x0300 - swl $3 2($2) - lw $4 0($2) - lui $5 0x01 - ori $5 $5 0x0203 - bne $4 $5 fail - -# addi $3 $0 0x01020304 - lui $3 0x0102 - ori $3 $3 0x0304 - swl $3 3($2) - lw $4 0($2) - lui $5 0x0102 - ori $5 $5 0x0304 - bne $4 $5 fail - addu $0 $0 $0 # Nop - - - .data -swr_: .asciiz "Testing SWR\n" - .align 2 -swrd_: .word 0 0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 swr_ - lui $a0, 0x1000 - ori $a0 $a0 0x274 - syscall - -# la $2 swrd_ - lui $2, 0x1000 - ori $2 $2 0x284 - addi $3 $0 1 - swr $3 0($2) - lw $4 0($2) - ori $5 $0 1 - bne $4 $5 fail - - addi $3 $0 0x0102 - swr $3 1($2) - lw $4 0($2) - lui $5 0x1 - ori $5 $5 0x0201 - bne $4 $5 fail - -# addi $3 $0 0x010203 - lui $3 0x01 - ori $3 $3 0x0203 - swr $3 2($2) - lw $4 0($2) - lui $5 0x203 - ori $5 $5 0x0201 - bne $4 $5 fail - -# addi $3 $0 0x01020304 - lui $3 0x0102 - ori $3 $3 0x0304 - swr $3 3($2) - lw $4 0($2) - lui $5 0x403 - ori $5 $5 0x0201 - bne $4 $5 fail - addu $0 $0 $0 #Nop - - - .data -xor_: .asciiz "Testing XOR\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 xor_ - lui $a0, 0x1000 - ori $a0 $a0 0x28c - syscall - - addi $2 $0 1 - addi $3 $0 -1 - - xor $4 $0 $0 - bne $4 $0 fail - xor $4 $3 $3 - bne $4 $0 fail - xor $4 $2 $3 - lui $5 0xffff - ori $5 $5 0xfffe - bne $4 $5 fail - addu $0 $0 $0 #Nop - - .data -xori_: .asciiz "Testing XORI\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 xori_ - lui $a0, 0x1000 - ori $a0 $a0 0x299 - syscall - - addi $2 $0 1 - ori $3 $0 -1 - - xori $4 $0 0 - bne $4 $0 fail - xori $4 $3 -1 - bne $4 $0 fail - xori $4 $2 -1 -# lui $5 0xffff - ori $5 $0 0xfffe - bne $4 $5 fail - - .data -jal_: .asciiz "Testing JAL\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 jal_ - lui $a0, 0x1000 - ori $a0 $a0 0x2a7 - syscall - - jal l18 - addu $0 $0 $0 # Nop -l19: j l20 # 0x00400ea0 - addu $0 $0 $0 # Nop -l18: lui $4 0x0040 # to replace la $4 l19 - ori $4 $4 0x0eb0 # bare machine has a delay slot. - bne $31 $4 fail - addu $0 $0 $0 #Nop - jr $31 - addu $0 $0 $0 #Nop -l20: addu $0 $0 $0 #Nop -- 0x00400ebc - - - .data -jalr_: .asciiz "Testing JALR\n" -#jalr2_: .asciiz "Expect an non-word boundary exception:\n " - .text - addi $v0 $0 4 # syscall 4 (print_str) 0x00400ec0 -# la $a0 jalr_ - lui $a0, 0x1000 - ori $a0 $a0 0x2b4 - syscall - -# la $2 l21 - lui $2 0x0040 # 0x00400ed0 - ori $2 $2 0x0ef4 - addu $4 $0 $2 - jalr $3, $2 - addu $0 $0 $0 #Nop -- 00400ee0 -l23: j l22 -l21: addu $0 $0 $0 # la $4 l21 -- delay slot. - bne $3 $4 fail - addu $0 $0 $0 # Nop -- 00400ef0 - jr $3 -l22: addu $0 $0 $0 # Nop - -# li $v0 4 # syscall 4 (print_str) -# la $a0 jalr2_ -# syscall -# la $2 l24 -# add $2 $2 2 -# l24: jalr $3 $2 - - - .data -bgezal_:.asciiz "Testing BGEZAL\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 bgezal_ - lui $a0, 0x1000 # 00400f00 - ori $a0 $a0 0x2c2 - syscall - - addi $2 $0 -1 - addi $3 $0 1 # 00400f10 - - bgezal $0 l5 - addu $0 $0 $0 # Nop - j fail - addu $0 $0 $0 # Nop -- 00400f20 -l5: bgezal $2 fail - addu $0 $0 $0 # Nop - bgezal $3 l6 - addu $0 $0 $0 # Nop -- 00400f30 -l55: j fail - addu $0 $0 $0 # Nop -l6: lui $4 0x0040 # la $4 l55 - ori $4 $4 0x0f48 # 00400f40 - bne $31 $4 fail - addu $0 $0 $0 # Nop - - .data -bltzal_:.asciiz "Testing BLTZAL\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 bltzal_ - lui $a0, 0x1000 # 00400f50 - ori $a0 $a0 0x2d2 - syscall - - addi $2 $0 -1 - addi $3 $0 1 # 00400f60 - - bltzal $0 fail - addu $0 $0 $0 # Nop - bltzal $3 fail - addu $0 $0 $0 # Nop -- 00400f70 -l13: bltzal $2 l15 - addu $0 $0 $0 # Nop -l14: j fail - addu $0 $0 $0 # Nop -- 00400f80 -l15: lui $4 0x0040 # la $4 l14 - ori $4 $4 0x0f90 - bne $31 $4 fail - addu $0 $0 $0 # Nop -- 00400f90 - -# Testing the exceptions - - .data -break_: .asciiz "Testing BREAK\nExpect an exception message:\n " -# .text -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 break_ -# lui $a0, 0x1000 -# ori $a0 $a0 0x2e2 -# syscall - -# break 3 - - - .data -ccp_: .asciiz "Testing move to/from coprocessor control z\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 ccp_ - lui $a0, 0x1000 - ori $a0 $a0 0x310 - syscall - -# li $2 0x7f7f - addi $2 $0 0x7f7f - ctc0 $2 $3 - addu $0 $0 $0 #Nop - cfc0 $4 $3 - addu $0 $0 $0 #Nop - bne $2 $4 fail -# li $2 0x7f7f -# Skip floating point stuff for now. -# addi $2 $0 0x7f7f -# ctc1 $2 $3 -# addu $0 $0 $0 #Nop -# cfc1 $4 $3 -# addu $0 $0 $0 #Nop -# bne $2 $4 fail -# li $2 0x7f7f - addi $2 $0 0x7f7f - ctc2 $2 $3 - addu $0 $0 $0 #Nop - cfc2 $4 $3 - addu $0 $0 $0 #Nop - bne $2 $4 fail -# li $2 0x7f7f - addi $2 $0 0x7f7f - ctc3 $2 $3 - addu $0 $0 $0 #Nop - cfc3 $4 $3 - addu $0 $0 $0 #Nop - bne $2 $4 fail - addu $0 $0 $0 # Nop - - - .data -mcp_: .asciiz "Testing move to/from coprocessor z\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 mcp_ - lui $a0, 0x1000 - ori $a0 $a0 0x33c - syscall - -# li $2 0x7f7f - addi $2 $0 0x7f7f - mtc0 $2 $3 - addu $0 $0 $0 # Nop - mfc0 $4 $3 - addu $0 $0 $0 # Nop - bne $2 $4 fail -# Skip FP for now. -# li $2 0x7f7f -# addi $2 $0 0x7f7f -# mtc1 $2 $3 -# addu $0 $0 $0 # Nop -# mfc1 $4 $f3 -# addu $0 $0 $0 # Nop -# bne $2 $4 fail - -# li $2 0x7f7f -# addi $2 $0 0x7f7f -# li $3 0xf7f7 -# addi $3 $0 0x7f7f -# mtc1.d $2 $4 -# mfc1.d $6 $4 -# bne $2 $6 fail -# bne $3 $7 fail - -# li $2 0x7f7f - addi $2 $0 0x7f7f - mtc2 $2 $3 - addu $0 $0 $0 # Nop - mfc2 $4 $3 - addu $0 $0 $0 # Nop - bne $2 $4 fail -# li $2 0x7f7f - addi $2 $0 0x7f7f - mtc3 $2 $3 - addu $0 $0 $0 # Nop - mfc3 $4 $3 - addu $0 $0 $0 # Nop - bne $2 $4 fail - addu $0 $0 $0 # Nop - - - .data -hilo_: .asciiz "Testing move to/from HI/LO\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 hilo_ - lui $a0, 0x1000 - ori $a0 $a0 0x360 - syscall - - mthi $0 - mfhi $2 - bne $2 $0 fail - mtlo $0 - mflo $2 - bne $2 $0 fail -# li $2 1 - addi $2 $0 1 - mthi $2 - mfhi $3 - bne $3 $2 fail -# li $2 1 - addi $2 $0 1 - mtlo $2 - mflo $3 - bne $3 $2 fail -# li $2 -1 - addi $2 $0 -1 - mthi $2 - mfhi $3 - bne $3 $2 fail -# li $2 -1 - addi $2 $0 1 - mtlo $2 - mflo $3 - bne $3 $2 fail - addu $0 $0 $0 # Nop - - .data -lswc_: .asciiz "Testing load/store word coprocessor z\n" - .align 2 -lswcd_: .byte 0, 0, 0, 0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 lswc_ - lui $a0, 0x1000 - ori $a0 $a0 0x37c - syscall - -# li $3, 0x7f7f7f7f - lui $3 0x7f7f - ori $3 $3 0x7f7f -# la $2 lswcd_ - lui $2, 0x1000 - ori $2 $2 0x3a4 - mtc0 $3, $0 - addu $0 $0 $0 #Nop - swc0 $0 0($2) - lw $4 0($2) - addu $0 $0 $0 #Nop - bne $4 $3 fail - lwc0 $1 0($2) - addu $0 $0 $0 #Nop - mfc0 $5, $1 - addu $0 $0 $0 #Nop - bne $5 $3 fail - addu $0 $0 $0 #Nop - -# li $3, 0x7f7f7f7f -# lui $3 0x7f7f -# ori $3 $3 0x7f7f -# la $2 lswcd_ -# lui $2, 0x1000 -# ori $2 $2 0x3a4 -# mtc1 $3, $0 -# addu $0 $0 $0 #Nop -# swc1 $f0 0($2) -# lw $4 0($2) -# addu $0 $0 $0 #Nop -# bne $4 $3 fail -# lwc1 $f1 0($2) -# addu $0 $0 $0 #Nop -# mfc1 $5, $f1 -# addu $0 $0 $0 #Nop -# bne $5 $3 fail - -# li $3, 0x7f7f7f7f - lui $3 0x7f7f - ori $3 $3 0x7f7f -# la $2 lswcd_ - lui $2, 0x1000 - ori $2 $2 0x3a4 - mtc2 $3, $0 - addu $0 $0 $0 #Nop - swc2 $0 0($2) - lw $4 0($2) - addu $0 $0 $0 #Nop - bne $4 $3 fail - lwc2 $1 0($2) - addu $0 $0 $0 #Nop - mfc2 $5, $1 - addu $0 $0 $0 #Nop - bne $5 $3 fail - addu $0 $0 $0 #Nop - -# li $3, 0x7f7f7f7f - lui $3 0x7f7f - ori $3 $3 0x7f7f -# la $2 lswcd_ - lui $2, 0x1000 - ori $2 $2 0x3a4 - mtc3 $3, $0 - addu $0 $0 $0 #Nop - swc3 $0 0($2) - lw $4 0($2) - addu $0 $0 $0 #Nop - bne $4 $3 fail - addu $0 $0 $0 #Nop - lwc3 $1 0($2) - addu $0 $0 $0 #Nop - mfc3 $5, $1 - addu $0 $0 $0 #Nop - bne $5 $3 fail - addu $0 $0 $0 #Nop - - -# Done !!! - .data -pt: .asciiz "Passed all tests\n" - .text - addi $2 $0 4 # syscall 4 (print_str) -# la $a0 sm - lui $a0, 0x1000 - ori $a0 $a0 0x3a8 - syscall - lui $4 0x1000 - lw $31 0($4) - addu $0 $0 $0 # Nop - jr $31 # Return from main - - - - -# .data -#fm: .asciiz "Failed test\n" - .text -fail: addi $2 $0 4 # syscall 4 (print_str) -# la $a0 fm - lui $a0, 0x1000 - ori $a0 $a0 0x4 - syscall - addi $2 $0 10 # syscall 10 (exit) - syscall - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - - - - - -# Define the exception handling code. This must go first! -# Duplicate of standard trap handler. - - .data - .globl __m1_ -__m1_: .asciiz " Exception " - .globl __m2_ -__m2_: .asciiz " occurred\n" - .ktext 0x80000080 - mfc0 $26 $13 # Cause - mfc0 $27 $14 # EPC - addiu $v0, $0, 4 # syscall 4 (print_str) -# la $a0 __m1_ - lui $a0, 0x1000 - ori $a0 $a0 0x03e5 - syscall - addiu $v0, $0, 1 # syscall 1 (print_int) - addu $a0 $0 $26 - syscall - addiu $v0, $0, 4 # syscall 4 (print_str) -# la $a0 __m2_ - lui $a0, 0x1000 - ori $a0, $a0, 0x03f1 - syscall - mtc0 $0, $13 # Clear Cause register - rfe # Return from exception handler - addiu $27 $27 4 # Return to next instruction - jr $27 - - - - diff --git a/spim-qtbase/Tests/tt.bare.s b/spim-qtbase/Tests/tt.bare.s deleted file mode 100755 index 0567507..0000000 --- a/spim-qtbase/Tests/tt.bare.s +++ /dev/null @@ -1,519 +0,0 @@ -# SPIM S20 MIPS simulator. -# A simple torture test for the bare SPIM simulator. -# Run with -notrap -delayed_branches -delayed_load flags (not -bare, -# as file uses pseudo ops). -# -# Copyright (c) 1990-2020, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - -# Define the exception handling code. This must go first! -# Duplicate of standard trap handler. - - .data - .globl __m1_ -__m1_: .asciiz " Exception " - .globl __m2_ -__m2_: .asciiz " occurred\n" - .ktext 0x80000080 - mfc0 $26 $13 # Cause - mfc0 $27 $14 # EPC - addiu $v0 $0 4 # syscall 4 (print_str) - la $a0 __m1_ - syscall - addiu $v0 $0 1 # syscall 1 (print_int) - addu $a0 $0 $26 - syscall - addiu $v0 $0 4 # syscall 4 (print_str) - la $a0 __m2_ - syscall - mtc0 $0 $13 # Clear Cause register - rfe # Return from exception handler - addiu $27 $27 4 # Return to next instruction - jr $27 - nop - -# Standard startup code. Invoke the routine main with no arguments. - - .text - .globl __start -__start: jal main - nop - addiu $v0 $0 10 - syscall # syscall 10 (exit) - - - .globl main -main: - addu $20 $0 $31 # Save return PC - -# Test delayed branches: - - .data -bc1fl_: .asciiz "Testing BC1FL and BC1TL\n" -fp_s1: .float 1.0 -fp_s1p5:.float 1.5 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bc1fl_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.eq.s $f0 $f2 - bc1fl fail - nop - c.eq.s $f0 $f2 - bc1fl fail - j fail - - c.eq.s $f0 $f4 - bc1tl fail - nop - c.eq.s $f0 $f4 - bc1tl fail - j fail - bc1fl l010 - j fail - nop -l010: - - -# BC2FL BC2TL should be tested if CoProcessor 2 exists - - - .data -beq_: .asciiz "Testing BEQ and BEQL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 beq_ - syscall - - addiu $2 $0 0 - beq $0 $0 l020 - addiu $2 $0 1 # Delayed instruction -l020: addiu $3 $0 1 - bne $2 $3 fail - nop - - li $2 1 - li $3 1 - li $4 2 - li $5 0 - - beq $2 $4 fail - nop - - beq $2 $4 l021 - addu $5 $0 5 # Delay slot -l021: bne $5 5 fail - nop - - beql $2 $3 l022 - j fail - nop - -l022: li $5 0 - beql $2 $3 l023 - addu $5 $0 5 # Delay slot -l023: bne $5 5 fail - nop - - -# BGEZAL and BGEZALL should be tested - - - .data -bgez_: .asciiz "Testing BGEZ and BGEZL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bgez_ - syscall - - addiu $2 $0 0 - bgez $0 l030 - addiu $2 $0 1 # Delayed instruction -l030: addiu $3 $0 1 - bne $2 $3 fail - nop - - li $2 1 - li $3 -1 - li $4 2 - li $5 0 - - bgez $3 fail - nop - - bgez $2 l031 - addu $5 $0 5 # Delay slot -l031: bne $5 5 fail - nop - - bgezl $2 l032 - j fail - nop - -l032: li $5 0 - bgezl $2 l033 - addu $5 $0 5 # Delay slot -l033: bne $5 5 fail - nop - - - .data -bgtz_: .asciiz "Testing BGTZ and BGTZL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bgtz_ - syscall - - addiu $2 $0 0 - bgtz $0 l040 - addiu $2 $0 1 # Delayed instruction - addiu $2 $0 2 -l040: addiu $3 $0 2 - bne $2 $3 fail - nop - - li $2 1 - li $3 -1 - li $4 2 - li $5 0 - - bgtz $3 fail - nop - - bgtz $2 l041 - addu $5 $0 5 # Delay slot -l041: bne $5 5 fail - nop - - bgtzl $2 l042 - j fail - nop - -l042: li $5 0 - bgtzl $2 l043 - addu $5 $0 5 # Delay slot -l043: bne $5 5 fail - nop - - - .data -blez_: .asciiz "Testing BLEZ and BLEZL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 blez_ - syscall - - addiu $2 $0 0 - blez $0 l050 - addiu $2 $0 1 # Delayed instruction -l050: addiu $3 $0 1 - bne $2 $3 fail - nop - - li $2 1 - li $3 -1 - li $4 2 - li $5 0 - - blez $2 fail - nop - - blez $3 l051 - addu $5 $0 5 # Delay slot -l051: bne $5 5 fail - nop - - blezl $3 l052 - j fail - nop - -l052: li $5 0 - blezl $3 l053 - addu $5 $0 5 # Delay slot -l053: bne $5 5 fail - nop - - - .data -bltz_: .asciiz "Testing BLTZ and BLTZL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bltz_ - syscall - - addiu $2 $0 0 - bltz $0 l060 - addiu $2 $0 1 # Delayed instruction - addiu $2 $0 2 -l060: addiu $3 $0 2 - bne $2 $3 fail - nop - - li $2 1 - li $3 -1 - li $4 2 - li $5 0 - - bltz $2 fail - nop - - bltz $3 l061 - addu $5 $0 5 # Delay slot -l061: bne $5 5 fail - nop - - bltzl $3 l062 - j fail - nop - -l062: li $5 0 - bltzl $3 l063 - addu $5 $0 5 # Delay slot -l063: bne $5 5 fail - nop - - -# BLTZAL and BLTZALL should be tested - - - .data -bne_: .asciiz "Testing BNE and BNEL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bne_ - syscall - - addiu $2 $0 0 - bne $0 $0 l070 - addiu $2 $0 1 # Delayed instruction -l070: addiu $3 $0 1 - bne $2 $3 fail - nop - - li $2 1 - li $3 1 - li $4 2 - li $5 0 - - bne $2 $3 fail - nop - - bne $2 $4 l071 - addu $5 $0 5 # Delay slot -l071: bne $5 5 fail - nop - - bnel $2 $3 l072 - j fail - nop - -l072: li $5 0 - bnel $2 $3 l073 - addu $5 $0 5 # Delay slot -l073: bne $5 0 fail - nop - - -# Test delayed loads: - - .data - .globl d -d: .word 101 -ld_: .asciiz "Testing LD\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ld_ - syscall - - addiu $3 $0 0 - la $4 d - lw $3 d - addu $3 $0 5 # Delayed instruction - bne $3 101 fail - nop - - -# Test ABS pseduo instruction: - - .data -abs_: .asciiz "Testing ABS\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 abs_ - syscall - - li $8 5 - abs $9 $8 - bne $9 5 fail - nop - li $8 -5 - abs $9 $8 - bne $9 5 fail - nop - - -# Test DIV pseduo instruction: - - .data -div_: .asciiz "Testing DIV\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 div_ - syscall - - li $8 5 - li $9 7 - div $10 $9 $8 - bne $10 1 fail - nop - - -# Test MUL pseduo instruction: - - .data -mul_: .asciiz "Testing MUL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 mul_ - syscall - - li $8 5 - li $9 7 - mul $10 $9 $8 - bne $10 35 fail - nop - li $8 0x80000000 - li $9 0x80000000 - mul $10 $9 $8 - bne $10 0 fail - nop - li $8 0x80000001 - li $9 0x80000001 - mul $10 $9 $8 - bne $10 1 fail - nop - - -# Test SLE pseduo instruction: - - .data -sle_: .asciiz "Testing SLE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sle_ - syscall - - li $8 5 - li $9 7 - sle $10 $9 $8 - bne $10 0 fail - nop - li $8 7 - li $9 5 - sle $10 $9 $8 - bne $10 1 fail - nop - li $8 7 - sle $10 $8 $8 - bne $10 1 fail - nop - - -# Test SGE pseduo instruction: - - .data -sge_: .asciiz "Testing SGE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sge_ - syscall - - li $8 5 - li $9 7 - sge $10 $9 $8 - bne $10 1 fail - nop - li $8 7 - li $9 5 - sge $10 $9 $8 - bne $10 0 fail - nop - li $8 7 - sge $10 $8 $8 - bne $10 1 fail - nop - - -# Test SEQ pseduo instruction: - - .data -seq_: .asciiz "Testing SEQ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 seq_ - syscall - - li $8 5 - li $9 7 - seq $10 $9 $8 - bne $10 0 fail - nop - li $8 7 - sge $10 $8 $8 - bne $10 1 fail - nop - - -# Done !!! - .data - .globl sm -sm: .asciiz "\nPassed all tests\n" - .text - addiu $v0 $0 4 # syscall 4 (print_str) - la $a0 sm - syscall - addu $31 $0 $20 # Return PC - jr $31 # Return from main - nop - - - .data - .globl fm -fm: .asciiz "Failed test\n" - .text -fail: addiu $v0 $0 4 # syscall 4 (print_str) - la $a0 fm - syscall - addiu $v0 $0 10 # syscall 10 (exit) - syscall diff --git a/spim-qtbase/Tests/tt.be.s b/spim-qtbase/Tests/tt.be.s deleted file mode 100755 index 26a6f60..0000000 --- a/spim-qtbase/Tests/tt.be.s +++ /dev/null @@ -1,556 +0,0 @@ -# SPIM S20 MIPS simulator. -# A torture test for the SPIM simulator. -# Tests for big-endian systems. -# Run in conjunction with tt.core.s -# -# Copyright (c) 1990-2010, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - - .data -saved_ret_pc: .word 0 # Holds PC to return from main -m3: .asciiz "The next few lines should contain exception error messages\n" -m4: .asciiz "Done with exceptions\n\n" -m5: .asciiz "Expect an address error exception:\n " -m6: .asciiz "Expect two address error exceptions:\n" - .text - .globl main - -main: - sw $31 saved_ret_pc - - .data -lb_: .asciiz "Testing LB\n" -lbd_: .byte 1, -1, 0, 128 -lbd1_: .word 0x76543210, 0xfedcba98 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lb_ - syscall - - la $2 lbd_ - lb $3 0($2) - bne $3 1 fail - lb $3 1($2) - bne $3 -1 fail - lb $3 2($2) - bne $3 0 fail - lb $3 3($2) - bne $3 0xffffff80 fail - - la $t0 lbd1_ - lb $t1 0($t0) - bne $t1 0x76 fail - lb $t1 1($t0) - bne $t1 0x54 fail - lb $t1 2($t0) - bne $t1 0x32 fail - lb $t1 3($t0) - bne $t1 0x10 fail - lb $t1 4($t0) - bne $t1 0xfffffffe fail - lb $t1 5($t0) - bne $t1 0xffffffdc fail - lb $t1 6($t0) - bne $t1 0xffffffba fail - lb $t1 7($t0) - bne $t1 0xffffff98 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 m5 - syscall - - li $t5 0x7fffffff - lb $3 1000($t5) - - - .data -lbu_: .asciiz "Testing LBU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lbu_ - syscall - - la $2 lbd_ - lbu $3 0($2) - bne $3 1 fail - lbu $3 1($2) - bne $3 0xff fail - lbu $3 2($2) - bne $3 0 fail - lbu $3 3($2) - bne $3 128 fail - - la $t0 lbd1_ - lbu $t1 0($t0) - bne $t1 0x76 fail - lbu $t1 1($t0) - bne $t1 0x54 fail - lbu $t1 2($t0) - bne $t1 0x32 fail - lbu $t1 3($t0) - bne $t1 0x10 fail - lbu $t1 4($t0) - bne $t1 0xfe fail - lbu $t1 5($t0) - bne $t1 0xdc fail - lbu $t1 6($t0) - bne $t1 0xba fail - lbu $t1 7($t0) - bne $t1 0x98 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 m5 - syscall - - li $t5 0x7fffffff - lbu $3 1000($t5) - - - .data -lwl_: .asciiz "Testing LWL\n" - .align 2 -lwld_: .byte 0 1 2 3 4 5 6 7 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lwl_ - syscall - - la $2 lwld_ - move $3 $0 - lwl $3 0($2) - bne $3 0x10203 fail - move $3 $0 - lwl $3 1($2) - bne $3 0x1020300 fail - li $3 5 - lwl $3 1($2) - bne $3 0x1020305 fail - move $3 $0 - lwl $3 2($2) - bne $3 0x2030000 fail - li $3 5 - lwl $3 2($2) - bne $3 0x2030005 fail - move $3 $0 - lwl $3 3($2) - bne $3 0x3000000 fail - li $3 5 - lwl $3 3($2) - bne $3 0x3000005 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 m6 - syscall - - li $t5 0x7fffffff - lwl $3 1000($t5) - lwl $3 1001($t5) - - - .data -lwr_: .asciiz "Testing LWR\n" - .align 2 -lwrd_: .byte 0 1 2 3 4 5 6 7 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lwr_ - syscall - - la $2 lwrd_ - li $3 0x0505 - lwr $3 0($2) - bne $3 0x0500 fail - move $3 $0 - lwr $3 1($2) - bne $3 0x01 fail - li $3 0x505 - lwr $3 1($2) - bne $3 0x01 fail - move $3 $0 - lwr $3 2($2) - bne $3 0x0102 fail - li $3 0x050505 - lwr $3 2($2) - bne $3 0x0102 fail - move $3 $0 - lwr $3 3($2) - bne $3 0x010203 fail - li $3 0x05050505 - lwr $3 3($2) - bne $3 0x010203 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 m6 - syscall - - li $t5 0x7fffffff - lwr $3 1000($t5) - lwr $3 1001($t5) - - - .data -sb_: .asciiz "Testing SB\n" - .align 2 -sbd_: .byte 0, 0, 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sb_ - syscall - - li $3, 1 - la $2 sbd_ - sb $3 0($2) - lw $4 0($2) - bne $4 0x1000000 fail - li $3 2 - sb $3 1($2) - lw $4 0($2) - bne $4 0x1020000 fail - li $3 3 - sb $3 2($2) - lw $4 0($2) - bne $4 0x1020300 fail - li $3 4 - sb $3 3($2) - lw $4 0($2) - bne $4 0x1020304 fail - - - li $v0 4 # syscall 4 (print_str) - la $a0 m5 - syscall - - li $t5 0x7fffffff - sb $3 1000($t5) - - - .data -sh_: .asciiz "Testing SH\n" -sh2_: .asciiz "Expect two address error exceptions:\n" - .align 2 -shd_: .byte 0, 0, 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sh_ - syscall - - li $3, 1 - la $2 shd_ - sh $3 0($2) - lw $4 0($2) - bne $4 0x10000 fail - li $3 2 - sh $3 2($2) - lw $4 0($2) - bne $4 0x10002 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 sh2_ - syscall - - li $t5 0x7fffffff - sh $3 1000($t5) - sh $3 1001($t5) - - - .data -swl_: .asciiz "Testing SWL\n" - .align 2 -swld_: .word 0 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 swl_ - syscall - - la $2 swld_ - - li $3 0x01020304 - swl $3 0($2) - lw $4 0($2) - bne $4 0x01020304 fail - - li $3 0x01020300 - swl $3 1($2) - lw $4 0($2) - bne $4 0x1010203 fail - - li $3 0x01020000 - swl $3 2($2) - lw $4 0($2) - bne $4 0x1010102 fail - - li $3 0x01000000 - swl $3 3($2) - lw $4 0($2) - bne $4 0x1010101 fail - - - .data -swr_: .asciiz "Testing SWR\n" - .align 2 -swrd_: .word 0 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 swr_ - syscall - - la $2 swrd_ - - li $3 0x01020304 - swr $3 0($2) - lw $4 0($2) - bne $4 0x4000000 fail - - li $3 0x01020304 - swr $3 1($2) - lw $4 0($2) - bne $4 0x3040000 fail - - li $3 0x01020304 - swr $3 2($2) - lw $4 0($2) - bne $4 0x2030400 fail - - li $3 0x01020304 - swr $3 3($2) - lw $4 0($2) - bne $4 0x1020304 fail - - - - .data -ulh_: .asciiz "Testing ULH\n" -ulh1_: .byte 1 2 3 4 5 6 7 8 -ulh2_: .byte 0xff 0xff - .text - - li $v0 4 # syscall 4 (print_str) - la $a0 ulh_ - syscall - la $2 ulh1_ - ulh $3 0($2) - bne $3 0x0102 fail - ulh $3 1($2) - bne $3 0x0203 fail - ulh $3 2($2) - bne $3 0x0304 fail - ulh $3 3($2) - bne $3 0x0405 fail - ulh $3 4($2) - bne $3 0x0506 fail - la $2 ulh2_ - ulh $3 0($2) - bne $3 -1 fail - - - .data -ulhu_: .asciiz "Testing ULHU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ulhu_ - syscall - - li $v0 4 # syscall 4 (print_str) - la $a0 ulhu_ - syscall - la $2 ulh1_ - ulhu $3 0($2) - bne $3 0x0102 fail - ulhu $3 1($2) - bne $3 0x0203 fail - ulhu $3 2($2) - bne $3 0x0304 fail - ulhu $3 3($2) - bne $3 0x0405 fail - ulhu $3 4($2) - bne $3 0x0506 fail - la $2 ulh2_ - ulhu $3 0($2) - bne $3 0xffff fail - - - .data -ulw_: .asciiz "Testing ULW\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ulw_ - syscall - - la $2 ulh1_ - ulw $3 0($2) - bne $3 0x1020304 fail - ulw $3 1($2) - bne $3 0x2030405 fail - ulw $3 2($2) - bne $3 0x3040506 fail - ulw $3 3($2) - bne $3 0x4050607 fail - - - .data -ush_: .asciiz "Testing USH\n" -ushd: .word 0 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ush_ - syscall - - la $2 ushd - sw $0 0($2) - sw $0 4($2) - li $3 -1 - ush $3 0($2) - lw $4 0($2) - bne $4 0xffff0000 fail - lw $4 4($2) - bne $4 0 fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - ush $3 1($2) - lw $4 0($2) - bne $4 0xffff00 fail - lw $4 4($2) - bne $4 0 fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - ush $3 2($2) - lw $4 0($2) - bne $4 0xffff fail - lw $4 4($2) - bne $4 0 fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - ush $3 3($2) - lw $4 0($2) - bne $4 0xff fail - lw $4 4($2) - bne $4 0xff000000 fail - - - .data -usw_: .asciiz "Testing USW\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 usw_ - syscall - - la $2 ushd - sw $0 0($2) - sw $0 4($2) - li $3 -1 - usw $3 0($2) - lw $4 0($2) - bne $4 -1 fail - lw $4 4($2) - bne $4 0 fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - usw $3 1($2) - lw $4 0($2) - bne $4 0xffffff fail - lw $4 4($2) - bne $4 0xff000000 fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - usw $3 2($2) - lw $4 0($2) - bne $4 0xffff fail - lw $4 4($2) - bne $4 0xffff0000 fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - usw $3 3($2) - lw $4 0($2) - bne $4 0xff fail - lw $4 4($2) - bne $4 0xffffff00 fail - - .data -word_: .asciiz "Testing .WORD\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 word_ - syscall - - .data - .align 0 -wordd: .byte 0x1 - .word 0x87654320 - .word 0xfedcba90 - .text - la $2 wordd - lwr $3 1($2) - lwl $3 0($2) - bne $3 0x01876543 fail - lwr $3 5($2) - lwl $3 4($2) - bne $3 0x20fedcba fail - - .data - .byte 0 -x: .word OK # Forward reference in unaligned data! - .text - lw $8 x - beq $8 $0 fail -OK: - - -# Done !!! - .data -sm: .asciiz "\nPassed all tests\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sm - syscall - lw $31 saved_ret_pc - jr $31 # Return from main - - - .data -fm: .asciiz "Failed test\n" - .text -fail: li $v0 4 # syscall 4 (print_str) - la $a0 fm - syscall - li $v0, 10 # syscall 10 (exit) - syscall - diff --git a/spim-qtbase/Tests/tt.core.s b/spim-qtbase/Tests/tt.core.s deleted file mode 100755 index cc3c1f7..0000000 --- a/spim-qtbase/Tests/tt.core.s +++ /dev/null @@ -1,4862 +0,0 @@ -# SPIM S20 MIPS simulator. -# A torture test for the SPIM simulator. -# Core tests for instructions that do not differ on big and little endian systems. -# -# Copyright (c) 1990-2020, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - - .data -saved_ret_pc: .word 0 # Holds PC to return from main -m3: .asciiz "The next few lines should contain exception error messages\n" -m4: .asciiz "Done with exceptions\n\n" - .text - .globl main -main: - sw $31 saved_ret_pc - -# -# The first thing to do is to test the exceptions: -# - li $v0 4 # syscall 4 (print_str) - la $a0 m3 - syscall - -# Exception 1 (INT) -- Not implemented yet -# Exception 4 (ADEL) - li $t0 0x400000 - lw $3 1($t0) -# Exception 5 (ADES) - sw $3 1($t0) -# Exception 6 (IBUS) -- Can't test and continue -# Exception 7 (DBUS) - lw $3 10000000($t0) -# Exception 8 (SYSCALL) -- Not implemented -# Exception 9 (BKPT) - break 0 -# Exception 10 (RI) -- Not implemented (can't enter bad instructions) -# Exception 12 (overflow) - li $t0 0x7fffffff - add $t0 $t0 $t0 - li $v0 4 # syscall 4 (print_str) - la $a0 m4 - syscall - -# -# Try modifying R0 -# - add $0, $0, 1 - bnez $0 fail - - -# -# Test the timer: -# - .data -timer_: .asciiz "Testing timer\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 timer_ - syscall - - mtc0 $0 $9 # Clear count register -timer1_: - mfc0 $9 $9 - bne $9 10 timer1_# Count up to 10 - - -# -# Test .ASCIIZ -# - .data -asciiz_:.asciiz "Testing .asciiz\n" -str0: .asciiz "" -str1: .asciiz "a" -str2: .asciiz "bb" -str3: .asciiz "ccc" -str4: .asciiz "dddd" -str5: .asciiz "eeeee" -str06: .asciiz "", "a", "bb", "ccc", "dddd", "eeeee" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 asciiz_ - syscall - - la $a0 str0 - li $a1 6 - jal ck_strings - - la $a0 str06 - li $a1 6 - jal ck_strings - - j over_strlen - - -ck_strings: - move $s0 $a0 - move $s1 $ra - li $s2 0 - -l_asciiz1: - move $a0 $s0 - jal strlen - - bne $v0 $s2 fail - - add $s0 $s0 $v0 # skip string - add $s0 $s0 1 # skip null byte - - add $s2 1 - blt $s2 $a1 l_asciiz1 - - move $ra $s1 - jal $ra - - -strlen: - li $v0 0 # num chars - move $t0 $a0 # str pointer - -l_strlen1: - lb $t1 0($t0) - add $t0 1 - add $v0 1 - bnez $t1 l_strlen1 - - sub $v0 $v0 1 # don't count null byte - jr $31 - -over_strlen: - -# -# Now, test each instruction -# - - .data -add_: .asciiz "Testing ADD\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 add_ - syscall - - li $2 1 - li $3 -1 - - add $4, $0, $0 - bnez $4 fail - add $4, $0, $2 - bne $4 1 fail - add $4, $4, $3 - bnez $4 fail - - - .data -addi_: .asciiz "Testing ADDI\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 addi_ - syscall - - addi $4, $0, 0 - bnez $4 fail - addi $4, $0, 1 - bne $4 1 fail - addi $4, $4, -1 - bnez $4 fail - - - .data -addiu_: .asciiz "Testing ADDIU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 addiu_ - syscall - - addiu $4, $0, 0 - bnez $4 fail - addiu $4, $0, 1 - bne $4 1 fail - addiu $4, $4, -1 - bnez $4 fail - - li $2 0x7fffffff - addiu $2 $2 2 # should not trap - bne $2 0x80000001 fail - - - .data -addu_: .asciiz "Testing ADDU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 addu_ - syscall - - li $2 1 - li $3 -1 - - addu $4, $0, $0 - bnez $4 fail - addu $4, $0, $2 - bne $4 1 fail - addu $4, $4, $3 - bnez $4 fail - - li $2 0x7fffffff - addu $2 $2 $2 # should not trap - bne $2 -2 fail - - - .data -and_: .asciiz "Testing AND\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 and_ - syscall - - li $2 1 - li $3 -1 - - and $4 $0 $0 - bnez $4 fail - and $4 $2 $2 - beqz $4 fail - and $4 $2 $3 - bne $4 1 fail - - - .data -andi_: .asciiz "Testing ANDI\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 andi_ - syscall - - li $2 1 - li $3 -1 - - andi $4 $0 0 - bnez $4 fail - and $4 $2 1 - beqz $4 fail - and $4 $2 -1 - bne $4 1 fail - and $4 $3 -1 - bne $4 $3 fail - - - .data -beq_: .asciiz "Testing BEQ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 beq_ - syscall - - li $2 -1 - li $3 1 - - beq $0 $0 l1 - j fail -l1: beq $2 $2 l2 - j fail -l2: beq $3 $2 fail - - beq $2 $2 far_away # Check long branch - j fail -come_back: - - li $2 3 -l2_1: sub $2 $2 1 - bnez $2, l2_1 - - - .data -bgez_: .asciiz "Testing BGEZ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bgez_ - syscall - - li $2 -1 - li $3 1 - - bgez $0 l3 - j fail -l3: bgez $3 l4 - j fail -l4: bgez $2 fail - - - .data -bgezal_:.asciiz "Testing BGEZAL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bgezal_ - syscall - - li $2 -1 - li $3 1 - - bgezal $0 l5 - j fail - bgezal $2 fail -l5: bgezal $3 l6 -l55: j fail -l6: la $4 l55 - bne $31 $4 fail - - - .data -bgtz_: .asciiz "Testing BGTZ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bgtz_ - syscall - - li $2 -1 - li $3 1 - - bgtz $0 fail -l7: bgtz $3 l8 - j fail -l8: bgtz $2 fail - - - .data -blez_: .asciiz "Testing BLEZ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 blez_ - syscall - - li $2 -1 - li $3 1 - - blez $0 l9 - j fail -l9: blez $2 l10 - j fail -l10: blez $3 fail - - - .data -bltz_: .asciiz "Testing BLTZ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bltz_ - syscall - - li $2 -1 - li $3 1 - - bltz $0 fail -l11: bltz $2 l12 - j fail -l12: bltz $3 fail - - - .data -bltzal_:.asciiz "Testing BLTZAL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bltzal_ - syscall - - li $2 -1 - li $3 1 - - bltzal $0 fail - bltzal $3 fail -l13: bltzal $2 l15 -l14: j fail -l15: la $4 l14 - bne $31 $4 fail - - - .data -bne_: .asciiz "Testing BNE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bne_ - syscall - - li $2 -1 - li $3 1 - - bne $0 $0 fail - bne $2 $2 fail - bne $3 $2 l16 -l16: - - - .data -break_: .asciiz "Testing BREAK\nExpect a exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 break_ - syscall - - break 3 - - -# COPz is not checked - - - .data -ccp_: .asciiz "Testing move to/from coprocessor control 0/1\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ccp_ - syscall - - li $2 0x7f7f - ctc0 $2 $3 - cfc0 $4 $3 - bne $2 $4 fail - li $2 0x7f7f - ctc1 $2 $3 - cfc1 $4 $3 - bne $2 $4 fail - - - .data -clo_: .asciiz "Testing CLO\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 clo_ - syscall - - li $2 0 - clo $3 $2 - bne $3 0 fail - - li $2 0xffffffff - clo $3 $2 - bne $3 32 fail - - li $2 0xf0000000 - clo $3 $2 - bne $3 4 fail - - - .data -clz_: .asciiz "Testing CLZ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 clz_ - syscall - - li $2 0 - clz $3 $2 - bne $3 32 fail - - li $2 0xffffffff - clz $3 $2 - bne $3 0 fail - - li $2 0x0fff0000 - clz $3 $2 - bne $3 4 fail - - - .data -div_: .asciiz "Testing DIV\n" -div2_: .asciiz "Expect exception caused by divide by 0:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 div_ - syscall - - li $2 4 - li $3 2 - li $4 -2 - - div $5 $2 $3 - bne $5 2 fail - mfhi $5 - bne $5 0 fail - - div $5 $2 $4 - bne $5 -2 fail - mfhi $5 - bne $5 0 fail - - li $2 0x80000000 - li $4 0xffffffff - div $5 $2 $4 # Overflows, but should not cause overflow - - li $2 1 - li $4 0xffffffff - div $5 $2 $4 - bne $5 -1 fail - mfhi $5 - bne $5 0 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 div2_ - syscall - div $5 $2 $0 - - - .data -divu_: .asciiz "Testing DIVU\n" -divu2_: .asciiz "Expect exception caused by divide by 0:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 divu_ - syscall - - li $2 4 - li $3 2 - li $4 -2 - - divu $5 $2 $3 - bne $5 2 fail - mfhi $5 - bne $5 0 fail - - divu $0 $2 $3 - mflo $5 - bne $5 2 fail - mfhi $5 - bne $5 0 fail - - divu $5 $2 $4 - bne $5 0 fail - mfhi $5 - bne $5 4 fail - - li $2 0x80000000 - li $4 0xffffffff - divu $5 $2 $4 # Overflows, but should not cause overflow - - li $2 1 - li $4 0xffffffff - divu $5 $2 $4 - bne $5 0 fail - mfhi $5 - bne $5 1 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 divu2_ - syscall - divu $5 $2 $0 - - - .data -j_: .asciiz "Testing J\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 j_ - syscall - - j l17 - j fail - - .ktext - nop # These instructions aren't executed, but - j l17a # cause parser errors since high 4 bits -l17a: # don't match - j l17b - - .text -l17b: nop - j l17a # Correctly flagged as error here. - -l17: - - - .data -jal_: .asciiz "Testing JAL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 jal_ - syscall - - jal l18 -l19: j l20 -l18: la $4 l19 - bne $31 $4 fail - jr $31 -l20: - - - .data -jalr_: .asciiz "Testing JALR\n" -jalr2_: .asciiz "Expect an non-word boundary exception:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 jalr_ - syscall - - la $2 l21 - jalr $3, $2 -l23: j l22 -l21: la $4 l23 - bne $3 $4 fail - jr $3 - -l22: la $2 l21a - jalr $2 -l23a: j l22a -l21a: la $4 l23a - bne $31 $4 fail - jr $31 - -l22a: li $v0 4 # syscall 4 (print_str) - la $a0 jalr2_ - syscall - la $2 l24 - add $2 $2 2 -l24: jalr $3 $2 - - - .data -jr_: .asciiz "Testing JR\n" -jr2_: .asciiz "Expect an non-word boundary exception:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 jr_ - syscall - - la $2 l25 - jr $2 - j fail -l25: li $v0 4 # syscall 4 (print_str) - la $a0 jr2_ - syscall - la $2 l27 - add $2 $2 2 -l27: jr $2 - - - .data -la_: .asciiz "Testing LA\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 la_ - syscall - - # Simple cases already tested - li $4 101 - la $5 10($4) - bne $5 111 fail - - -# LB is endian-specific - - -# LBU is endian-specific - - - .data -ld_: .asciiz "Testing LD\n" -ld2_: .asciiz "Expect four address error exceptions:\n" -ldd_: .word 1, -1, 0, 0x8000000 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ld_ - syscall - - la $2 ldd_ - ld $3 0($2) - bne $3 1 fail - bne $4 -1 fail - ld $3 8($2) - bne $3 0 fail - bne $4 0x8000000 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 ld2_ - syscall - - li $t5 0x7fffffff - ld $3 1000($t5) - ld $3 1001($t5) - - -# LDC2 not tested - -# LWC2 not tested - - .data -lh_: .asciiz "Testing LH\n" -lh2_: .asciiz "Expect two address error exceptions:\n" -lhd_: .half 1, -1, 0, 0x8000 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lh_ - syscall - - la $2 lhd_ - lh $3 0($2) - bne $3 1 fail - lh $3 2($2) - bne $3 -1 fail - lh $3 4($2) - bne $3 0 fail - lh $3 6($2) - bne $3 0xffff8000 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 lh2_ - syscall - - li $t5 0x7fffffff - lh $3 1000($t5) - lh $3 1001($t5) - - .data -lhu_: .asciiz "Testing LHU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lhu_ - syscall - - la $2 lhd_ - lhu $3 0($2) - bne $3 1 fail - lhu $3 2($2) - bne $3 0xffff fail - lhu $3 4($2) - bne $3 0 fail - lhu $3 6($2) - bne $3 0x8000 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 lh2_ - syscall - - li $t5 0x7fffffff - lhu $3 1000($t5) - lhu $3 1001($t5) - - - .data -ll_: .asciiz "Testing LL\n" -ll1: .word 10 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ll_ - syscall - - ll $2 ll1 - bne $2 10 fail - add $2 $2 1 - sc $2 ll1 - lw $3 ll1 - bne $2 $3 fail - - .data -lui_: .asciiz "Testing LUI\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lui_ - syscall - - lui $2 0 - bne $2 $0 fail - lui $2 1 - srl $2 $2 16 - addiu $2 $2 -1 # Don't do compare directly since it uses LUI - bne $2 $0 fail - lui $2 1 - andi $2 $2 0xffff - bne $2 $0 fail - lui $2 0xffff - srl $2 $2 16 - addiu $2 $2 1 - andi $2 $2 0xffff - bne $2 $0 fail - - - .data -lw_: .asciiz "Testing LW\n" -lwd_: .word 1, -1, 0, 0x8000000 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lw_ - syscall - - la $2 lwd_ - lw $3 0($2) - bne $3 1 fail - lw $3 4($2) - bne $3 -1 fail - lw $3 8($2) - bne $3 0 fail - lw $3 12($2) - bne $3 0x8000000 fail - - li $2, 0 - lw $3 lwd_($2) - bne $3 1 fail - addi $2, $2, 4 - lw $3 lwd_($2) - bne $3 -1 fail - addi $2, $2, 4 - lw $3 lwd_($2) - bne $3 0 fail - addi $2, $2, 4 - lw $3 lwd_($2) - bne $3 0x8000000 fail - - la $2 lwd_ - add $2 $2 12 - lw $3 -12($2) - bne $3 1 fail - lw $3 -8($2) - bne $3 -1 fail - lw $3 -4($2) - bne $3 0 fail - lw $3 0($2) - bne $3 0x8000000 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 lh2_ - syscall - - li $t5 0x7fffffff - lw $3 1000($t5) - lw $3 1001($t5) - - -# LWL is endian-specific - - -# LWR is endian-specific - - - .data -madd_: .asciiz "Testing MADD\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 madd_ - syscall - - mthi $0 - mtlo $0 - madd $0, $0 - mfhi $3 - bnez $3 fail - mflo $3 - bnez $3 fail - - mtlo $0 - mthi $0 - li $4, 1 - madd $4, $4 - mfhi $3 - bnez $3 fail - mflo $3 - bne $3 1 fail - - li $3, 1 - mtlo $3 - mthi $0 - li $4, -1 - madd $3, $4 - mfhi $3 - bnez $3 fail - mflo $3 - bnez $3 fail - - mtlo $0 - mthi $0 - li $3, 1 - li $4, -1 - madd $3, $4 - mfhi $3 - bne $3 0xffffffff fail - mflo $3 - bne $3 0xffffffff fail - - li $t0 1 - mtlo $t0 - mthi $0 - li $t0 2 - li $t1 -1 - madd $t0, $t1 - mfhi $3 - bne $3 0xffffffff fail - mflo $3 - bne $3 0xffffffff fail - - mtlo $0 - mthi $0 - li $4, 0x10000 - madd $4, $4 - mfhi $3 - bne $3 1 fail - mflo $3 - bne $3 0 fail - - li $4, 0x10000 - madd $4 $4 - mfhi $3 - bne $3 2 fail - mflo $3 - bne $3 0 fail - - .data -maddu_: .asciiz "Testing MADDU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 maddu_ - syscall - - mthi $0 - mtlo $0 - - maddu $0 $0 - mfhi $3 - bnez $3 fail - mflo $3 - bnez $3 fail - - li $4, 1 - maddu $4 $4 - mfhi $3 - bnez $3 fail - mflo $3 - bne $3 1 fail - - li $4, -1 - maddu $4 $4 - mfhi $3 - bne $3 0xfffffffe fail - mflo $3 - bne $3 2 fail - - .data -mcp_: .asciiz "Testing move to/from coprocessor z\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 mcp_ - syscall - - li $2 0x7f7f - mtc0 $2 $3 - mfc0 $4 $3 - bne $2 $4 fail - li $2 0x7f7f - mtc1 $2 $3 - mfc1 $4 $f3 - bne $2 $4 fail - li $2 0x7f7f - li $3 0xf7f7 - mtc1.d $2 $4 - mfc1.d $6 $4 - bne $2 $6 fail - bne $3 $7 fail - - - .data -hilo_: .asciiz "Testing move to/from HI/LO\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 hilo_ - syscall - - mthi $0 - mfhi $2 - bnez $2 fail - mtlo $0 - mflo $2 - bnez $2 fail - li $2 1 - mthi $2 - mfhi $3 - bne $3 $2 fail - li $2 1 - mtlo $2 - mflo $3 - bne $3 $2 fail - li $2 -1 - mthi $2 - mfhi $3 - bne $3 $2 fail - li $2 -1 - mtlo $2 - mflo $3 - bne $3 $2 fail - - - .data -movf_: .asciiz "Testing MOVF\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movf_ - syscall - - ctc1 $0, $31 # clear cc's - - li $2 1 - li $3 0 - li $4 2 - movf $3 $2 1 - bne $3 1 fail - movf $3 $4 6 - bne $3 2 fail - - - .data -movn_: .asciiz "Testing MOVN\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movn_ - syscall - - li $2 2 - li $3 3 - li $4 4 - movn $4 $3 $0 - bne $4 4 fail - movn $4 $3 $2 - bne $4 3 fail - - - .data -movt_: .asciiz "Testing MOVT\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movt_ - syscall - - li $2 0xfe800000 - ctc1 $2 $31 # set ccs - - li $2 1 - li $3 0 - li $4 2 - movt $3 $2 1 - bne $3 1 fail - movt $3 $4 6 - bne $3 2 fail - - - .data -movz_: .asciiz "Testing MOVZ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movz_ - syscall - - li $2 2 - li $3 3 - li $4 4 - movz $4 $3 $2 - bne $4 4 fail - movz $4 $3 $0 - bne $4 3 fail - - - .data -msub_: .asciiz "Testing MSUB\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 msub_ - syscall - - mthi $0 - mtlo $0 - msub $0 $0 - mfhi $3 - bnez $3 fail - mflo $3 - bnez $3 fail - - mthi $0 - mtlo $0 - li $4, 1 - msub $4 $4 - mfhi $3 - bne $3 0xffffffff fail - mflo $3 - bne $3 0xffffffff fail - - li $4, 1 - msub $3 $4 - mfhi $3 - bnez $3 fail - mflo $3 - bnez $3 fail - - mthi $0 - mtlo $0 - li $4, 0x10000 - msub $4 $4 - mfhi $3 - bne $3 0xffffffff fail - mflo $3 - bne $3 0 fail - - mtlo $0 - mthi $0 - li $4, 1 - li $5, -1 - msub $5, $4 - mfhi $3 - bne $3 0 fail - mflo $3 - bne $3 1 fail - - .data -msubu_: .asciiz "Testing MSUBU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 msubu_ - syscall - - mthi $0 - mtlo $0 - msubu $0 $0 - mfhi $3 - bnez $3 fail - mflo $3 - bnez $3 fail - - mthi $0 - mtlo $0 - li $4, 1 - msubu $4 $4 - mfhi $3 - bne $3 0xffffffff fail - mflo $3 - bne $3 0xffffffff fail - - mtlo $0 - mthi $0 - li $4, 1 - li $5, -1 - msubu $5, $4 - mfhi $3 - bne $3 0xffffffff fail - mflo $3 - bne $3 1 fail - - .data -mul_: .asciiz "Testing MUL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 mul_ - syscall - - li $2, 1 - mul $3, $2, 0 - bnez $3 fail - mul $3, $2, 1 - bne $3 1 fail - mul $3, $2, 10 - bne $3 10 fail - - mul $2 $0 $0 - bnez $2 fail - mfhi $3 - bnez $3 fail - mflo $3 - bnez $3 fail - - li $4, 1 - mul $2 $4 $4 - bne $2 1 fail - mfhi $3 - bnez $3 fail - mflo $3 - bne $3 1 fail - - li $4, -1 - mul $2 $4 $4 - bne $2 1 fail - mfhi $3 - bnez $3 fail - mflo $3 - bne $3 1 fail - - li $4, -1 - li $5, 1 - mul $2 $4 $5 - bne $2 -1 fail - mfhi $3 - bne $3 -1 fail - mflo $3 - bne $3 -1 fail - - li $4, 0x10000 - mul $2 $4 $4 - bne $2 0 fail - mfhi $3 - bne $3 1 fail - mflo $3 - bne $3 0 fail - - li $4, 0x80000000 - mul $2 $4 $4 - bne $2 0 fail - mfhi $3 - bne $3 0x40000000 fail - mflo $3 - bne $3 0 fail - - - .data -multu_: .asciiz "Testing MULTU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 multu_ - syscall - - multu $0 $0 - mfhi $3 - bnez $3 fail - mflo $3 - bnez $3 fail - - li $4, 1 - multu $4 $4 - mfhi $3 - bnez $3 fail - mflo $3 - bne $3 1 fail - - li $4, -1 - multu $4 $4 - mfhi $3 - bne $3 0xfffffffe fail - mflo $3 - bne $3 1 fail - - li $4, -1 - li $5, 0 - multu $4 $5 - mfhi $3 - bne $3 0 fail - mflo $3 - bne $3 0 fail - - li $4, -1 - li $5, 1 - multu $4 $5 - mfhi $3 - bne $3 0 fail - mflo $3 - bne $3 -1 fail - - li $4, 0x10000 - multu $4 $4 - mfhi $3 - bne $3 1 fail - mflo $3 - bne $3 0 fail - - li $4, 0x80000000 - multu $4 $4 - mfhi $3 - bne $3 0x40000000 fail - mflo $3 - bne $3 0 fail - - li $3, 0xcecb8f27 - li $4, 0xfd87b5f2 - multu $3 $4 - mfhi $3 - bne $3 0xcccccccb fail - mflo $3 - bne $3 0x7134e5de fail - - - .data -mulo_: .asciiz "Testing MULO\n" -mulo1_: .asciiz "Expect an exception:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 mulo_ - syscall - - mulo $2 $0 $0 - bne $2 0 fail - - li $4, 1 - mulo $2 $4 $4 - bne $2 1 fail - - li $4, -1 - mulo $2 $4 $4 - bne $2 1 fail - - li $4, -1 - li $5, 1 - mulo $2 $4 $5 - bne $2 -1 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 mulo1_ - syscall - - li $4, 0x10000 - mulo $2 $4 $4 - bne $2 0 fail - - - .data -nor_: .asciiz "Testing NOR\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 nor_ - syscall - - li $2 1 - li $3 -1 - - nor $4 $0 $0 - bne $4 -1 fail - nor $4 $2 $2 - bne $4 0xfffffffe fail - nor $4 $2 $3 - bne $4 0 fail - - - .data -or_: .asciiz "Testing OR\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 or_ - syscall - - li $2 1 - li $3 -1 - - or $4 $0 $0 - bne $4 0 fail - or $4 $2 $2 - bne $4 1 fail - or $4 $2 $3 - bne $4 -1 fail - - - .data -ori_: .asciiz "Testing ORI\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ori_ - syscall - - li $2 1 - li $3 -1 - - ori $4 $0 0 - bne $4 0 fail - ori $4 $2 1 - bne $4 1 fail - ori $4 $2 0xffff - bne $4 0x0000ffff fail - - -# RFE tested previously - - - .data -sp_: .asciiz "Testing .space\n" -spd_: .space 100000 -spde_: .word 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sd_ - syscall - - la $2 spde_ - sub $2 $2 4 - lw $3 0($2) # look for exception - - -# SB is endian-specific - - - .data -sd_: .asciiz "Testing SD\n" -sd2_: .asciiz "Expect two address error exceptions:\n" - .align 2 -sdd_: .word 0, 0, 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sd_ - syscall - - li $3, 0x7f7f7f7f - li $4, 0xf7f7f7f7 - la $2 sdd_ - sd $3 0($2) - ld $5 0($2) - bne $3 $5 fail - bne $4 $4 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 sd2_ - syscall - - li $t5 0x7fffffff - sd $3 1000($t5) - sd $3 1001($t5) - - - .data -swc1_: .asciiz "Testing SWC1\n" - .align 2 -swc1d_: .word 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 swc1_ - syscall - - li $3, 0x7f7f7f7f - la $2 swc1d_ - mtc1 $3, $0 - swc1 $f0 0($2) - lw $5 0($2) - bne $5 $3 fail - - - .data -s.s_: .asciiz "Testing S.S\n" - .align 2 -s.sd_: .word 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 s.s_ - syscall - - li $3, 0x7f7f7f7f - la $2 s.sd_ - mtc1 $3, $0 - s.s $f0 0($2) - lw $5 0($2) - bne $5 $3 fail - - - .data -sdc1_: .asciiz "Testing SDC1\n" - .align 2 -sdc1d_: .word 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sdc1_ - syscall - - li $3, 0x7f7f7f7f - li $4, 0xf7f7f7f7 - la $2 sdc1d_ - mtc1 $3, $0 - mtc1 $4, $1 - sdc1 $f0 0($2) - lw $5 0($2) - bne $5 $3 fail - lw $5 4($2) - bne $5 $4 fail - - - .data -s.d_: .asciiz "Testing S.D\n" - .align 2 -s.dd_: .word 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 s.d_ - syscall - - li $3, 0x7f7f7f7f - li $4, 0xf7f7f7f7 - la $2 s.dd_ - mtc1 $3, $0 - mtc1 $4, $1 - s.d $f0 0($2) - lw $5 0($2) - bne $5 $3 fail - lw $5 4($2) - bne $5 $4 fail - - -# SDC2 not tested - - .data -sll_: .asciiz "Testing SLL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sll_ - syscall - - li $2 1 - - sll $3 $2 0 - bne $3 1 fail - sll $3 $2 1 - bne $3 2 fail - sll $3 $2 16 - bne $3 0x10000 fail - sll $3 $2 31 - bne $3 0x80000000 fail - - - .data -sllv_: .asciiz "Testing SLLV\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sllv_ - syscall - - li $2 1 - li $4 0 - sllv $3 $2 $4 - bne $3 1 fail - li $4 1 - sllv $3 $2 $4 - bne $3 2 fail - li $4 16 - sllv $3 $2 $4 - bne $3 0x10000 fail - li $4 32 - sllv $3 $2 $4 - bne $3 1 fail - - - .data -slt_: .asciiz "Testing SLT\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 slt_ - syscall - - slt $3 $0 $0 - bne $3 0 fail - li $2 1 - slt $3 $2 $0 - bne $3 0 fail - slt $3 $0 $2 - bne $3 1 fail - li $2 -1 - slt $3 $2 $0 - bne $3 1 fail - slt $3 $0 $2 - bne $3 0 fail - li $2 -1 - li $4 1 - slt $3 $2 $4 - bne $3 1 fail - - - .data -slti_: .asciiz "Testing SLTI\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 slti_ - syscall - - slti $3 $0 0 - bne $3 0 fail - li $2 1 - slti $3 $2 0 - bne $3 0 fail - slti $3 $0 1 - bne $3 1 fail - li $2 -1 - slti $3 $2 0 - bne $3 1 fail - slti $3 $0 -1 - bne $3 0 fail - li $2 -1 - li $4 1 - slti $3 $2 1 - bne $3 1 fail - slti $3 $4 -1 - bne $3 0 fail - - - .data -sltiu_: .asciiz "Testing SLTIU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sltiu_ - syscall - - sltiu $3 $0 0 - bne $3 0 fail - li $2 1 - sltiu $3 $2 0 - bne $3 0 fail - sltiu $3 $0 1 - bne $3 1 fail - li $2 -1 - sltiu $3 $2 0 - bne $3 0 fail - sltiu $3 $0 -1 - bne $3 1 fail - li $2 -1 - li $4 1 - sltiu $3 $2 1 - bne $3 0 fail - sltiu $3 $4 -1 - bne $3 1 fail - - - .data -sltu_: .asciiz "Testing SLTU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sltu_ - syscall - - sltu $3 $0 $0 - bne $3 0 fail - li $2 1 - sltu $3 $2 $0 - bne $3 0 fail - sltu $3 $0 $2 - bne $3 1 fail - li $2 -1 - sltu $3 $2 $0 - bne $3 0 fail - sltu $3 $0 $2 - bne $3 1 fail - li $2 -1 - li $4 1 - sltu $3 $2 $4 - bne $3 0 fail - - - .data -sra_: .asciiz "Testing SRA\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sra_ - syscall - - li $2 1 - sra $3 $2 0 - bne $3 1 fail - sra $3 $2 1 - bne $3 0 fail - li $2 0x1000 - sra $3 $2 4 - bne $3 0x100 fail - li $2 0x80000000 - sra $3 $2 4 - bne $3 0xf8000000 fail - - - .data -srav_: .asciiz "Testing SRAV\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 srav_ - syscall - - li $2 1 - li $4 0 - srav $3 $2 $4 - bne $3 1 fail - li $4 1 - srav $3 $2 $4 - bne $3 0 fail - li $2 0x1000 - li $4 4 - srav $3 $2 $4 - bne $3 0x100 fail - li $2 0x80000000 - li $4 4 - srav $3 $2 $4 - bne $3 0xf8000000 fail - - - .data -srl_: .asciiz "Testing SRL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 srl_ - syscall - - li $2 1 - srl $3 $2 0 - bne $3 1 fail - srl $3 $2 1 - bne $3 0 fail - li $2 0x1000 - srl $3 $2 4 - bne $3 0x100 fail - li $2 0x80000000 - srl $3 $2 4 - bne $3 0x08000000 fail - - - .data -srlv_: .asciiz "Testing SRLV\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 srlv_ - syscall - - li $2 1 - li $4 0 - srlv $3 $2 $4 - bne $3 1 fail - li $4 1 - srlv $3 $2 $4 - bne $3 0 fail - li $2 0x1000 - li $4 4 - srlv $3 $2 $4 - bne $3 0x100 fail - li $2 0x80000000 - li $4 4 - srlv $3 $2 $4 - bne $3 0x08000000 fail - - - .data -ssnop_: .asciiz "Testing SSNOP\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 nop_ - syscall - - ssnop # How do we test it?? - - - .data -sub_: .asciiz "Testing SUB\n" -sub1_: .asciiz "Expect an overflow exceptions:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sub_ - syscall - - li $2 1 - li $3 -1 - - sub $4, $0, $0 - bnez $4 fail - sub $4, $0, $2 - bne $4 -1 fail - sub $4, $2, $0 - bne $4, 1 fail - sub $4, $2, $3 - bne $4, 2 fail - sub $4, $3, $2 - bne $4, -2 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 sub1_ - syscall - li $2 0x80000000 - li $3 1 - sub $4, $3, $2 - - - .data -subu_: .asciiz "Testing SUBU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 subu_ - syscall - - li $2 1 - li $3 -1 - - subu $4, $0, $0 - bnez $4 fail - subu $4, $0, $2 - bne $4 -1 fail - subu $4, $2, $0 - bne $4, 1 fail - subu $4, $2, $3 - bne $4, 2 fail - subu $4, $3, $2 - bne $4, -2 fail - - li $2 0x80000000 - li $3 1 - subu $4, $3, $2 - - - .data -sw_: .asciiz "Testing SW\n" -sw2_: .asciiz "Expect two address error exceptions:\n" - .align 2 -swd_: .byte 0, 0, 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sw_ - syscall - - li $3, 0x7f7f7f7f - la $2 swd_ - sw $3 0($2) - lw $4 0($2) - bne $4 0x7f7f7f7f fail - - li $2, 4 - sw $3 swd_($2) - lw $4 swd_($2) - bne $4 0x7f7f7f7f fail - - li $v0 4 # syscall 4 (print_str) - la $a0 sw2_ - syscall - - li $t5 0x7fffffff - sw $3 1000($t5) - sw $3 1001($t5) - - lw $t0 far_away - sw $0 far_away - lw $t1 far_away - bne $t1 $0 fail - - -# SWL is endian-specific - - -# SWR is endian-specific - - - .data -sync_: .asciiz "Testing SYNC\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 nop_ - syscall - - sync - - - .data -syscall_:.asciiz "Testing SYSCALL\n" -syscall1_:.asciiz "The next line should contain: -1, -1.000000, -2.000000\n" -syscall2_:.asciiz ", " -fp_sm1: .float -1.0 -fp_dm2: .double -2.0 -fp_c1: .float 17.18 -fp_c2: .float 1700.18 -fp_c3: .double 17.18e10 -fp_c4: .double 1700.18e10 -syscall5_:.asciiz "\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 syscall_ - syscall - - li $v0 4 # syscall 4 (print_str) - la $a0 syscall1_ - syscall - - li $v0 1 # syscall 1 (print_int) - li $a0 -1 - syscall - - li $v0 4 # syscall 4 (print_str) - la $a0 syscall2_ - syscall - - lwc1 $f12 fp_sm1# syscall 2 (print_float) - li $v0 2 - syscall - - li $v0 4 # syscall 4 (print_str) - la $a0 syscall2_ - syscall - - lwc1 $f12 fp_dm2# syscall 3 (print_double) - lwc1 $f13 fp_dm2+4 - li $v0 3 - syscall - - li $v0 4 # syscall 4 (print_str) - la $a0 syscall5_ - syscall - - li $v0 5 # syscall 5 (read_int) - syscall - bne $v0 17 fail - - li $v0 5 # syscall 5 (read_int) - syscall - bne $v0 1717 fail - - li $v0 6 # syscall 6 (read_float) - syscall - lwc1 $f2 fp_c1 - c.eq.s $f0, $f2 - bc1f fail - - li $v0 6 # syscall 6 (read_float) - syscall - lwc1 $f2 fp_c2 - c.eq.s $f0, $f2 - bc1f fail - - li $v0 7 # syscall 7 (read_double) - syscall - lwc1 $f2 fp_c3 - lwc1 $f3 fp_c3+4 - c.eq.d $f0, $f2 - bc1f fail - - li $v0 7 # syscall 7 (read_double) - syscall - lwc1 $f2 fp_c4 - lwc1 $f3 fp_c4+4 - c.eq.d $f0, $f2 - bc1f fail - - - .data -teq_: .asciiz "Testing TEQ\nExpect one exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 teq_ - syscall - - li $2 1 - teq $0 $2 - teq $0 $0 - - - .data -teqi_: .asciiz "Testing TEQI\nExpect one exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 teqi_ - syscall - - teqi $0 4 - teqi $0 0 - - - .data -tge_: .asciiz "Testing TGE\nExpect two exception messages:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tge_ - syscall - - li $2 1 - li $3 2 - tge $2 $3 - tge $0 $0 - tge $3 $2 - - - .data -tgei_: .asciiz "Testing TGEI\nExpect two exception messages:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tgei_ - syscall - - li $2 8 - tgei $0 4 - tgei $0 0 - tgei $2 1 - - - .data -tgeiu_: .asciiz "Testing TGEIU\nExpect two exception messages:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tgeiu_ - syscall - - li $2 -4 - tgeiu $0 4 - tgeiu $0 0 - tgeiu $2 1 - - - .data -tgeu_: .asciiz "Testing TGEU\nExpect two exception messages:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tgeu_ - syscall - - li $2 1 - li $3 -4 - tgeu $2 $3 - tgeu $0 $0 - tgeu $3 $2 - - - .data -tlb_: .asciiz "Testing TLB operations:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tlb_ - syscall - tlbp - tlbr - tlbwi - tlbr - - - .data -tlt_: .asciiz "Testing TLT\nExpect one exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tlt_ - syscall - - li $2 1 - li $3 2 - tlt $2 $3 - tlt $0 $0 - tlt $3 $2 - - - .data -tlti_: .asciiz "Testing TLTI\nExpect one exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tlti_ - syscall - - li $2 8 - tlti $0 4 - tlti $0 0 - tlti $2 1 - - - .data -tltiu_: .asciiz "Testing TLTIU\nExpect one exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tltiu_ - syscall - - li $2 -4 - tltiu $0 4 - tltiu $0 0 - tltiu $2 1 - - - .data -tltu_: .asciiz "Testing TLTU\nExpect one exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tltu_ - syscall - - li $2 1 - li $3 -4 - tltu $2 $3 - tltu $0 $0 - tltu $3 $2 - - - .data -tne_: .asciiz "Testing TNE\nExpect one exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tne_ - syscall - - li $2 1 - tne $0 $2 - tne $0 $0 - - - .data -tnei_: .asciiz "Testing TNEI\nExpect one exception message:\n " - .text - li $v0 4 # syscall 4 (print_str) - la $a0 tnei_ - syscall - - tnei $0 4 - tnei $0 0 - - - .data -xor_: .asciiz "Testing XOR\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 xor_ - syscall - - li $2 1 - li $3 -1 - - xor $4 $0 $0 - bne $4 0 fail - xor $4 $3 $3 - bne $4 0 fail - xor $4 $2 $3 - bne $4 0xfffffffe fail - - .data -xori_: .asciiz "Testing XORI\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 xori_ - syscall - - li $2 1 - li $3 -1 - - xori $4 $0 0 - bne $4 0 fail - xori $4 $3 0xffff - bne $4 0xffff0000 fail - xori $4 $2 0xffff - bne $4 0x0000fffe fail - - -# -# Testing Floating Point Ops -# - - .data -abs.s_:.asciiz "Testing ABS.S\n" -fp_s100:.float 100.0 -fp_sm100:.float -100.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 abs.s_ - syscall - - lw $4 fp_s100 - lwc1 $f0 fp_s100 - abs.s $f2 $f0 - mfc1 $5 $f2 - bne $4 $5 fail - - lwc1 $f0 fp_sm100 - abs.s $f2 $f0 - mfc1 $5 $f2 - bne $4 $5 fail - - - .data -abs.d_:.asciiz "Testing ABS.D\n" -fp_d100:.double 100.0 -fp_dm100:.double -100.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 abs.d_ - syscall - - lw $4 fp_d100 - lw $5 fp_d100+4 - lwc1 $f0 fp_d100 - lwc1 $f1 fp_d100+4 - abs.d $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lwc1 $f0 fp_dm100 - lwc1 $f1 fp_dm100+4 - abs.d $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - - .data -add.s_: .asciiz "Testing ADD.S\n" -fp_s0: .float 0.0 -fp_s1: .float 1.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 add.s_ - syscall - - lw $4 fp_s0 - lwc1 $f0 fp_s0 - add.s $f2 $f0 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_s1 - lwc1 $f0 fp_s0 - lwc1 $f2 fp_s1 - add.s $f4 $f0 $f2 - mfc1 $6 $f4 - bne $4 $6 fail - - lw $4 fp_s0 - lwc1 $f0 fp_s1 - lwc1 $f2 fp_sm1 - add.s $f4 $f0 $f2 - mfc1 $6 $f4 - bne $4 $6 fail - - - .data -add.d_: .asciiz "Testing ADD.D\n" -fp_d0: .double 0.0 -fp_d1: .double 1.0 -fp_dm1: .double -1.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 add.d_ - syscall - - lw $4 fp_d0 - lw $5 fp_d0+4 - lwc1 $f0 fp_d0 - lwc1 $f1 fp_d0+4 - add.d $f2 $f0 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_d1 - lw $5 fp_d1+4 - lwc1 $f0 fp_d0 - lwc1 $f1 fp_d0+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - add.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_d0 - lw $5 fp_d0+4 - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_dm1 - lwc1 $f3 fp_dm1+4 - add.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - bne $5 $7 fail - - - .data -bc1f_: .asciiz "Testing BC1F and BC1T\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bc1f_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.eq.s $f0 $f2 - bc1f fail - bc1t l205 - j fail -l205: c.eq.s $f0 $f4 - bc1t fail - bc1f l206 - j fail -l206: - - - - -# ToDo: Check order/unordered exception in floating point comparison. - - .data -c.eq.d_: .asciiz "Testing C.EQ.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.eq.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d1p5 - lwc1 $f5 fp_d1p5+4 - c.eq.d $f0 $f2 - bc1f fail - bc1t l200 - j fail -l200: c.eq.d $f0 $f4 - bc1t fail - bc1f l201 - j fail -l201: - - - .data -c.eq.s_: .asciiz "Testing C.EQ.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.eq.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.eq.s $f0 $f2 - bc1f fail - bc1t l210 - j fail -l210: c.eq.s $f0 $f4 - bc1t fail - bc1f l211 - j fail -l211: - - - .data -c.f.d_: .asciiz "Testing C.F.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.f.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d1p5 - lwc1 $f5 fp_d1p5+4 - c.f.d $f0 $f2 - bc1t fail - bc1f l220 - j fail -l220: c.f.d $f0 $f4 - bc1t fail - bc1f l221 - j fail -l221: - - - .data -c.f.s_: .asciiz "Testing C.F.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.f.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.f.s $f0 $f2 - bc1t fail - bc1f l230 - j fail -l230: c.f.s $f0 $f4 - bc1t fail - bc1f l231 - j fail -l231: - - - .data -c.le.d_: .asciiz "Testing C.LE.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.le.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - lwc1 $f4 fp_dm2 - lwc1 $f5 fp_dm2+4 - c.le.d $f0 $f2 - bc1f fail - bc1t l240 - j fail -l240: c.le.d $f2 $f0 - bc1t fail - bc1f l241 - j fail -l241: c.le.d $f0 $f0 - bc1f fail - bc1t l242 - j fail -l242: c.le.d $f4 $f0 - bc1f fail - bc1t l243 - j fail -l243: - - - .data -c.le.s_: .asciiz "Testing C.LE.S\n" -fp_sm2: .float -2.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.le.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1p5 - lwc1 $f4 fp_sm2 - c.le.s $f0 $f2 - bc1f fail - bc1t l250 - j fail -l250: c.le.s $f2 $f0 - bc1t fail - bc1f l251 - j fail -l251: c.le.s $f0 $f0 - bc1f fail - bc1t l252 - j fail -l252: c.le.s $f4 $f0 - bc1f fail - bc1t l253 - j fail -l253: - - .data -c.le.s_1_: .asciiz "Testing C.LE.S CC=1\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.le.s_1_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1p5 - lwc1 $f4 fp_sm2 - c.le.s 1 $f0 $f2 - bc1f 1 fail - bc1t 1 l250_1 - j fail -l250_1: c.le.s 1 $f2 $f0 - bc1t 1 fail - bc1f 1 l251_1 - j fail -l251_1: c.le.s 1 $f0 $f0 - bc1f 1 fail - bc1t 1 l252_1 - j fail -l252_1: c.le.s 1 $f4 $f0 - bc1f 1 fail - bc1t 1 l253_1 - j fail -l253_1: - - .data -c.lt.d_: .asciiz "Testing C.LT.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.lt.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - lwc1 $f4 fp_dm2 - lwc1 $f5 fp_dm2+4 - c.lt.d $f0 $f2 - bc1f fail - bc1t l260 - j fail -l260: c.lt.d $f2 $f0 - bc1t fail - bc1f l261 - j fail -l261: c.lt.d $f0 $f0 - bc1t fail - bc1f l262 - j fail -l262: c.lt.d $f4 $f0 - bc1f fail - bc1t l263 - j fail -l263: - - .data -c.lt.d_7_: .asciiz "Testing C.LT.D CC=7\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.lt.d_7_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - lwc1 $f4 fp_dm2 - lwc1 $f5 fp_dm2+4 - c.lt.d 7 $f0 $f2 - bc1f 7 fail - bc1t 7 l260_7 - j fail -l260_7: c.lt.d 7 $f2 $f0 - bc1t 7 fail - bc1f 7 l261_7 - j fail -l261_7: c.lt.d 7 $f0 $f0 - bc1t 7 fail - bc1f 7 l262_7 - j fail -l262_7: c.lt.d 7 $f4 $f0 - bc1f 7 fail - bc1t 7 l263_7 - j fail -l263_7: - - .data -c.lt.s_: .asciiz "Testing C.LT.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.lt.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1p5 - lwc1 $f4 fp_sm2 - c.lt.s $f0 $f2 - bc1f fail - bc1t l270 - j fail -l270: c.lt.s $f2 $f0 - bc1t fail - bc1f l271 - j fail -l271: c.lt.s $f0 $f0 - bc1t fail - bc1f l272 - j fail -l272: c.lt.s $f4 $f0 - bc1f fail - bc1t l273 - j fail -l273: - - - .data -c.nge.d_: .asciiz "Testing C.NGE.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.nge.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - lwc1 $f4 fp_dm2 - lwc1 $f5 fp_dm2+4 - c.nge.d $f0 $f2 - bc1f fail - bc1t l280 - j fail -l280: c.nge.d $f2 $f0 - bc1t fail - bc1f l281 - j fail -l281: c.nge.d $f0 $f0 - bc1t fail - bc1f l282 - j fail -l282: c.nge.d $f4 $f0 - bc1f fail - bc1t l283 - j fail -l283: - - - .data -c.nge.s_: .asciiz "Testing C.NGE.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.nge.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1p5 - lwc1 $f4 fp_sm2 - c.nge.s $f0 $f2 - bc1f fail - bc1t l290 - j fail -l290: c.nge.s $f2 $f0 - bc1t fail - bc1f l291 - j fail -l291: c.nge.s $f0 $f0 - bc1t fail - bc1f l292 - j fail -l292: c.nge.s $f4 $f0 - bc1f fail - bc1t l293 - j fail -l293: - - - .data -c.ngle.d_: .asciiz "Testing C.NGLE.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ngle.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d1p5 - lwc1 $f5 fp_d1p5+4 - c.ngle.d $f0 $f2 - bc1t fail -l300: c.ngle.d $f0 $f4 - bc1t fail -l301: - - - .data -c.ngle.s_: .asciiz "Testing C.NGLE.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ngle.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.ngle.s $f0 $f2 - bc1t fail -l310: c.ngle.s $f0 $f4 - bc1t fail -l311: - - - .data -c.ngl.d_: .asciiz "Testing C.NGL.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ngl.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d1p5 - lwc1 $f5 fp_d1p5+4 - c.ngl.d $f0 $f2 - bc1f fail - bc1t l320 - j fail -l320: c.ngl.d $f0 $f4 - bc1t fail - bc1f l321 - j fail -l321: - - - .data -c.ngl.s_: .asciiz "Testing C.NGL.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ngl.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.ngl.s $f0 $f2 - bc1f fail - bc1t l330 - j fail -l330: c.ngl.s $f0 $f4 - bc1t fail - bc1f l331 - j fail -l331: - - - .data -c.ngt.d_: .asciiz "Testing C.NGT.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ngt.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - lwc1 $f4 fp_dm2 - lwc1 $f5 fp_dm2+4 - c.ngt.d $f0 $f2 - bc1f fail - bc1t l340 - j fail -l340: c.ngt.d $f2 $f0 - bc1t fail - bc1f l341 - j fail -l341: c.ngt.d $f0 $f0 - bc1f fail - bc1t l342 - j fail -l342: c.ngt.d $f4 $f0 - bc1f fail - bc1t l343 - j fail -l343: - - - .data -c.ngt.s_: .asciiz "Testing C.NGT.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ngt.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1p5 - lwc1 $f4 fp_sm2 - c.ngt.s $f0 $f2 - bc1f fail - bc1t l350 - j fail -l350: c.ngt.s $f2 $f0 - bc1t fail - bc1f l351 - j fail -l351: c.ngt.s $f0 $f0 - bc1f fail - bc1t l352 - j fail -l352: c.ngt.s $f4 $f0 - bc1f fail - bc1t l353 - j fail -l353: - - - .data -c.ole.d_: .asciiz "Testing C.OLE.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ole.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - lwc1 $f4 fp_dm2 - lwc1 $f5 fp_dm2+4 - c.ole.d $f0 $f2 - bc1f fail - bc1t l360 - j fail -l360: c.ole.d $f2 $f0 - bc1t fail - bc1f l361 - j fail -l361: c.ole.d $f0 $f0 - bc1f fail - bc1t l362 - j fail -l362: c.ole.d $f4 $f0 - bc1f fail - bc1t l363 - j fail -l363: - - - .data -c.ole.s_: .asciiz "Testing C.OLE.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ole.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1p5 - lwc1 $f4 fp_sm2 - c.ole.s $f0 $f2 - bc1f fail - bc1t l370 - j fail -l370: c.ole.s $f2 $f0 - bc1t fail - bc1f l371 - j fail -l371: c.ole.s $f0 $f0 - bc1f fail - bc1t l372 - j fail -l372: c.ole.s $f4 $f0 - bc1f fail - bc1t l373 - j fail -l373: - - - .data -c.seq.d_: .asciiz "Testing C.SEQ.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.seq.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d1p5 - lwc1 $f5 fp_d1p5+4 - c.seq.d $f0 $f2 - bc1f fail - bc1t l380 - j fail -l380: c.seq.d $f0 $f4 - bc1t fail - bc1f l381 - j fail -l381: - - - .data -c.seq.s_: .asciiz "Testing C.SEQ.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.seq.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.seq.s $f0 $f2 - bc1f fail - bc1t l390 - j fail -l390: c.seq.s $f0 $f4 - bc1t fail - bc1f l391 - j fail -l391: - - - .data -c.sf.d_: .asciiz "Testing C.SF.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.sf.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d1p5 - lwc1 $f5 fp_d1p5+4 - c.sf.d $f0 $f2 - bc1t fail -l400: c.sf.d $f0 $f4 - bc1t fail -l401: - - - .data -c.sf.s_: .asciiz "Testing C.SF.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.sf.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.sf.s $f0 $f2 - bc1t fail -l410: c.sf.s $f0 $f4 - bc1t fail -l411: - - - .data -c.ueq.d_: .asciiz "Testing C.UEQ.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ueq.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d1p5 - lwc1 $f5 fp_d1p5+4 - c.ueq.d $f0 $f2 - bc1f fail - bc1t l420 - j fail -l420: c.ueq.d $f0 $f4 - bc1t fail - bc1f l421 - j fail -l421: - - - .data -c.ueq.s_: .asciiz "Testing C.UEQ.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ueq.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.ueq.s $f0 $f2 - bc1f fail - bc1t l430 - j fail -l430: c.ueq.s $f0 $f4 - bc1t fail - bc1f l431 - j fail -l431: - - - .data -c.ule.d_: .asciiz "Testing C.ULE.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ule.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - lwc1 $f4 fp_dm2 - lwc1 $f5 fp_dm2+4 - c.ule.d $f0 $f2 - bc1f fail - bc1t l440 - j fail -l440: c.ule.d $f2 $f0 - bc1t fail - bc1f l441 - j fail -l441: c.ule.d $f0 $f0 - bc1f fail - bc1t l442 - j fail -l442: c.ule.d $f4 $f0 - bc1f fail - bc1t l443 - j fail -l443: - - - .data -c.ule.s_: .asciiz "Testing C.ULE.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.ule.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1p5 - lwc1 $f4 fp_sm2 - c.ule.s $f0 $f2 - bc1f fail - bc1t l450 - j fail -l450: c.ule.s $f2 $f0 - bc1t fail - bc1f l451 - j fail -l451: c.ule.s $f0 $f0 - bc1f fail - bc1t l452 - j fail -l452: c.ule.s $f4 $f0 - bc1f fail - bc1t l453 - j fail -l453: - - - .data -c.un.d_: .asciiz "Testing C.UN.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.un.d_ - syscall - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d1p5 - lwc1 $f5 fp_d1p5+4 - c.un.d $f0 $f2 - bc1t fail - bc1f l460 - j fail -l460: c.un.d $f0 $f4 - bc1t fail - bc1f l461 - j fail -l461: - - - .data -c.un.s_: .asciiz "Testing C.UN.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 c.un.s_ - syscall - - lwc1 $f0 fp_s1 - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s1p5 - c.un.s $f0 $f2 - bc1t fail - bc1f l470 - j fail -l470: c.un.s $f0 $f4 - bc1t fail - bc1f l471 - j fail -l471: - - -# CFC1 and CTC1 tested previously - - - .data -ceil.w.d_: .asciiz "Testing CEIL.W.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ceil.w.d_ - syscall - - lwc1 $f2 fp_d0 - lwc1 $f3 fp_d0+4 - ceil.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 0 fail - - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - ceil.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - ceil.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 2 fail - - - .data -ceil.w.s_: .asciiz "Testing CEIL.W.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ceil.w.s_ - syscall - - lwc1 $f2 fp_s0 - ceil.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 0 fail - - lwc1 $f2 fp_s1 - ceil.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - lwc1 $f2 fp_s1p5 - ceil.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 2 fail - - - .data -cvt.d.s_: .asciiz "Testing CVT.D.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 cvt.d.s_ - syscall - - lw $4 fp_d0 - lw $5 fp_d0+4 - lwc1 $f0 fp_s0 - cvt.d.s $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_d1 - lw $5 fp_d1+4 - lwc1 $f0 fp_s1 - cvt.d.s $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_dm1 - lw $5 fp_dm1+4 - lwc1 $f0 fp_sm1 - cvt.d.s $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - - .data -cvt.d.w_: .asciiz "Testing CVT.D.W\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 cvt.d.w_ - syscall - - lw $4 fp_d0 - lw $5 fp_d0+4 - mtc1 $0 $0 - cvt.d.w $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_d1 - lw $5 fp_d1+4 - li $t1 1 - mtc1 $t1 $0 - cvt.d.w $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_dm1 - lw $5 fp_dm1+4 - li $t1 -1 - mtc1 $t1 $0 - cvt.d.w $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - - .data -cvt.s.d_: .asciiz "Testing CVT.S.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 cvt.s.d_ - syscall - - lw $4 fp_s0 - lwc1 $f0 fp_d0 - lwc1 $f1 fp_d0+4 - cvt.s.d $f2 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_s1 - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - cvt.s.d $f2 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_sm1 - lwc1 $f0 fp_dm1 - lwc1 $f1 fp_dm1+4 - cvt.s.d $f2 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - - .data -cvt.s.w_: .asciiz "Testing CVT.S.W\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 cvt.s.w_ - syscall - - lw $4 fp_s0 - mtc1 $0 $0 - cvt.s.w $f2 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_s1 - li $t1 1 - mtc1 $t1 $0 - cvt.s.w $f2 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_sm1 - li $t1 -1 - mtc1 $t1 $0 - cvt.s.w $f2 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - - .data -cvt.w.d_: .asciiz "Testing CVT.W.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 cvt.w.d_ - syscall - - lwc1 $f0 fp_d0 - lwc1 $f1 fp_d0+4 - cvt.w.d $f2 $f0 - mfc1 $6 $f2 - bne $0 $6 fail - - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - cvt.w.d $f2 $f0 - mfc1 $6 $f2 - li $4 1 - bne $4 $6 fail - - lwc1 $f0 fp_dm1 - lwc1 $f1 fp_dm1+4 - cvt.w.d $f2 $f0 - mfc1 $6 $f2 - li $4 -1 - bne $4 $6 fail - - - .data -cvt.w.s_: .asciiz "Testing CVT.W.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 cvt.w.s_ - syscall - - lwc1 $f0 fp_s0 - cvt.w.s $f2 $f0 - mfc1 $6 $f2 - bne $0 $6 fail - - lwc1 $f0 fp_s1 - cvt.w.s $f2 $f0 - mfc1 $6 $f2 - li $4 1 - bne $4 $6 fail - - lwc1 $f0 fp_sm1 - cvt.w.s $f2 $f0 - mfc1 $6 $f2 - li $4 -1 - bne $4 $6 fail - - - .data -div.s_: .asciiz "Testing DIV.S\n" -fp_s2: .float 2.0 -fp_s3: .float 3.0 -fp_s1p5:.float 1.5 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 div.s_ - syscall - - lw $4 fp_s1 - lwc1 $f0 fp_s1 - div.s $f2 $f0 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_s1p5 - lwc1 $f0 fp_s3 - lwc1 $f2 fp_s2 - div.s $f4 $f0 $f2 - mfc1 $6 $f4 - bne $4 $6 fail - - - .data -div.d_: .asciiz "Testing DIV.D\n" -fp_d2: .double 2.0 -fp_d3: .double 3.0 -fp_d1p5:.double 1.5 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 div.d_ - syscall - - lw $4 fp_d1 - lw $5 fp_d1+4 - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - div.d $f2 $f0 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_d1p5 - lw $5 fp_d1p5+4 - lwc1 $f0 fp_d3 - lwc1 $f1 fp_d3+4 - lwc1 $f2 fp_d2 - lwc1 $f3 fp_d2+4 - div.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - bne $5 $7 fail - - - .data -floor.w.d_: .asciiz "Testing FLOOR.W.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 floor.w.d_ - syscall - - lwc1 $f2 fp_d0 - lwc1 $f3 fp_d0+4 - floor.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 0 fail - - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - floor.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - lwc1 $f2 fp_d1p5 - lwc1 $f3 fp_d1p5+4 - floor.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - - .data -floor.w.s_: .asciiz "Testing FLOOR.W.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 floor.w.s_ - syscall - - lwc1 $f2 fp_s0 - floor.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 0 fail - - lwc1 $f2 fp_s1 - floor.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - lwc1 $f2 fp_s1p5 - floor.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - - .data -ldc1_: .asciiz "Testing LDC1\n" - .align 2 -ldc1d_: .word 0x7f7f7f7f, 0xf7f7f7f7 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ldc1_ - syscall - - la $2 ldc1d_ - ldc1 $f0 0($2) - mfc1 $3, $f0 - mfc1 $4, $f1 - lw $5 0($2) - bne $5 $3 fail - lw $5 4($2) - bne $5 $4 fail - - - .data -l.d_: .asciiz "Testing L.D\n" - .align 2 -l.dd_: .word 0x7f7f7f7f, 0xf7f7f7f7 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 l.d_ - syscall - - la $2 l.dd_ - l.d $f0 0($2) - mfc1 $3, $f0 - mfc1 $4, $f1 - lw $5 0($2) - bne $5 $3 fail - lw $5 4($2) - bne $5 $4 fail - - - .data -lwc1_: .asciiz "Testing LWC1\n" - .align 2 -lwc1d_: .word 0x7f7f7f7f - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lwc1_ - syscall - - la $2 lwc1d_ - lwc1 $f0 0($2) - mfc1 $3 $f0 - lw $4 0($2) - bne $4 $3 fail - - - .data -l.s_: .asciiz "Testing L.S\n" - .align 2 -l.sd_: .word 0x7f7f7f7f - .text - li $v0 4 # syscall 4 (print_str) - la $a0 l.s_ - syscall - - la $2 l.sd_ - l.s $f0 0($2) - mfc1 $3 $f0 - lw $4 0($2) - bne $4 $3 fail - - -# MFC1 tested previously - - - .data -mov.s_: .asciiz "Testing MOV.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 mov.s_ - syscall - - lw $4 fp_s1 - lwc1 $f2 fp_s1 - mov.s $f4 $f2 - mov.s $f6 $f4 - mfc1 $6 $f6 - bne $4 $6 fail - - .data -mov.d_: .asciiz "Testing MOV.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 mov.d_ - syscall - - lw $4 fp_d1 - lw $5 fp_d1+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - mov.d $f4 $f2 - mov.d $f6 $f4 - mfc1 $6 $f6 - mfc1 $7 $f7 - bne $4 $6 fail - bne $5 $7 fail - - .data -movf.d_:.asciiz "Testing MOVF.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movf.d_ - syscall - - li $2 0xfe000000 - ctc1 $2 $31 # clear cc0, set others - - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d2 - lwc1 $f5 fp_d2+4 - lwc1 $f6 fp_d1 - lwc1 $f7 fp_d1+4 - movf.d $f4 $f2 0 - movf.d $f6 $f4 7 - c.eq.d $f2 $f4 - bc1f fail - c.eq.d $f2 $f6 - bc1f fail - - .data -movf.s_:.asciiz "Testing MOVF.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movf.s_ - syscall - - li $2 0xfe000000 - ctc1 $2 $31 # clear cc0, set others - - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s2 - lwc1 $f6 fp_s1 - movf.s $f4 $f2 0 - movf.s $f6 $f4 7 - c.eq.s $f2 $f4 - bc1f fail - c.eq.s $f2 $f6 - bc1f fail - - .data -movn.d_:.asciiz "Testing MOVN.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movn.d_ - syscall - - li $2 2 - lw $4 fp_d1 - lw $5 fp_d1+4 - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - movn.d $f2 $f0 $2 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $6 $4 fail - bne $7 $5 fail - - lwc1 $f0 fp_d1p5 - lwc1 $f1 fp_d1p5+4 - movn.d $f2 $f0 $0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $6 $4 fail - bne $7 $5 fail - - - .data -movn.s_:.asciiz "Testing MOVN.s\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movn.s_ - syscall - - li $2 2 - lw $4 fp_s1 - lwc1 $f0 fp_s1 - movn.s $f2 $f0 $2 - mfc1 $6 $f2 - bne $6 $4 fail - - lwc1 $f0 fp_s1p5 - movn.s $f2 $f0 $0 - mfc1 $6 $f2 - bne $6 $4 fail - - - .data -movt.d_:.asciiz "Testing MOVT.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movt.d_ - syscall - - li $2 0xfe000000 - ctc1 $2 $31 # clear cc0, set others - - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - lwc1 $f4 fp_d2 - lwc1 $f5 fp_d2+4 - lwc1 $f6 fp_d1 - lwc1 $f7 fp_d1+4 - movt.d $f4 $f2 0 - movt.d $f6 $f4 7 - c.eq.d $f2 $f4 - bc1t fail - c.eq.d $f2 $f6 - bc1t fail - - .data -movt.s_:.asciiz "Testing MOVT.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movt.s_ - syscall - - li $2 0xfe000000 - ctc1 $2 $31 # clear cc0, set others - - lwc1 $f2 fp_s1 - lwc1 $f4 fp_s2 - lwc1 $f6 fp_s1 - movt.s $f4 $f2 0 - movt.s $f6 $f4 7 - c.eq.s $f2 $f4 - bc1t fail - c.eq.s $f2 $f6 - bc1t fail - - - .data -movz.d_:.asciiz "Testing MOVZ.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movz.d_ - syscall - - li $2 2 - lw $4 fp_d1 - lw $5 fp_d1+4 - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - movz.d $f2 $f0 $0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $6 $4 fail - bne $7 $5 fail - - lwc1 $f0 fp_d1p5 - lwc1 $f1 fp_d1p5+4 - movz.d $f2 $f0 $2 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $6 $4 fail - bne $7 $5 fail - - - .data -movz.s_:.asciiz "Testing MOVZ.s\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 movz.s_ - syscall - - li $2 2 - lw $4 fp_s1 - lwc1 $f0 fp_s1 - movz.s $f2 $f0 $0 - mfc1 $6 $f2 - bne $6 $4 fail - - lwc1 $f0 fp_s1p5 - movz.s $f2 $f0 $2 - mfc1 $6 $f2 - bne $6 $4 fail - - -# MTC1 tested previously - - .data -mul.s_: .asciiz "Testing MUL.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 mul.s_ - syscall - - lw $4 fp_s1 - lwc1 $f0 fp_s1 - mul.s $f2 $f0 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_s3 - lwc1 $f0 fp_s1p5 - lwc1 $f2 fp_s2 - mul.s $f4 $f0 $f2 - mfc1 $6 $f4 - bne $4 $6 fail - - - .data -mul.d_: .asciiz "Testing MUL.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 mul.d_ - syscall - - lw $4 fp_d1 - lw $5 fp_d1+4 - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - mul.d $f2 $f0 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_d3 - lw $5 fp_d3+4 - lwc1 $f0 fp_d1p5 - lwc1 $f1 fp_d1p5+4 - lwc1 $f2 fp_d2 - lwc1 $f3 fp_d2+4 - mul.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - bne $5 $7 fail - - - .data -neg.s_: .asciiz "Testing NEG.S\n" -fp_sm3: .float -3.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 neg.s_ - syscall - - lw $4 fp_sm1 - lwc1 $f0 fp_s1 - neg.s $f2 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_s3 - lwc1 $f0 fp_sm3 - neg.s $f2 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - - .data -neg.d_: .asciiz "Testing NEG.D\n" -fp_dm3: .double -3.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 neg.d_ - syscall - - lw $4 fp_dm1 - lw $5 fp_dm1+4 - lwc1 $f0 fp_d1 - lwc1 $f1 fp_d1+4 - neg.d $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_d3 - lw $5 fp_d3+4 - lwc1 $f0 fp_dm3 - lwc1 $f1 fp_dm3+4 - neg.d $f4 $f0 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - bne $5 $7 fail - - - .data -round.w.d_: .asciiz "Testing ROUND.W.D\n" -fp_d1p6:.double 1.6 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 round.w.d_ - syscall - - lwc1 $f2 fp_d0 - lwc1 $f3 fp_d0+4 - round.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 0 fail - - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - round.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - lwc1 $f2 fp_d1p6 - lwc1 $f3 fp_d1p6+4 - round.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 2 fail - - - .data -round.w.s_: .asciiz "Testing ROUND.W.S\n" -fp_s1p6:.float 1.6 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 round.w.s_ - syscall - - lwc1 $f2 fp_s0 - round.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 0 fail - - lwc1 $f2 fp_s1 - round.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - lwc1 $f2 fp_s1p6 - round.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 2 fail - - - .data -sqrt.d_:.asciiz "Testing SQRT.D\n" -fp_d9: .double 9.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sqrt.d_ - syscall - - ldc1 $f2 fp_d9 - sqrt.d $f0 $f2 - mul.d $f4 $f0 $f0 - c.eq.d $f2 $f4 - bc1f 0 fail - - - .data -sqrt.s_:.asciiz "Testing SQRT.S\n" -fp_s9: .float 9.0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sqrt.s_ - syscall - - ldc1 $f2 fp_s9 - sqrt.s $f0 $f2 - mul.s $f4 $f0 $f0 - c.eq.s $f2 $f4 - bc1f 0 fail - - - .data -sub.s_: .asciiz "Testing SUB.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sub.s_ - syscall - - lw $4 fp_s0 - lwc1 $f0 fp_s0 - sub.s $f2 $f0 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 fp_sm1 - lw $5 fp_s1 - lwc1 $f0 fp_s0 - lwc1 $f2 fp_s1 - sub.s $f4 $f0 $f2 - mfc1 $6 $f4 - bne $4 $6 fail - sub.s $f4 $f2 $f0 - mfc1 $6 $f4 - bne $5 $6 fail - - lw $4 fp_s1p5 - lwc1 $f0 fp_s1p5 - lwc1 $f2 fp_s3 - sub.s $f4 $f2 $f0 - mfc1 $6 $f4 - bne $4 $6 fail - - - .data -sub.d_: .asciiz "Testing SUB.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sub.d_ - syscall - - lw $4 fp_d0 - lw $5 fp_d0+4 - lwc1 $f0 fp_d0 - lwc1 $f1 fp_d0+4 - sub.d $f2 $f0 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_dm1 - lw $5 fp_dm1+4 - lwc1 $f0 fp_d0 - lwc1 $f1 fp_d0+4 - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - sub.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - bne $5 $7 fail - lw $4 fp_d1 - lw $5 fp_d1+4 - sub.d $f4 $f2 $f0 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - bne $5 $7 fail - - lw $4 fp_d1p5 - lw $5 fp_d1p5+4 - lwc1 $f0 fp_d1p5 - lwc1 $f1 fp_d1p5+4 - lwc1 $f2 fp_d3 - lwc1 $f3 fp_d3+4 - sub.d $f4 $f2 $f0 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - bne $5 $7 fail - - - .data -trunc.w.d_: .asciiz "Testing TRUNC.W.D\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 trunc.w.d_ - syscall - - lwc1 $f2 fp_d0 - lwc1 $f3 fp_d0+4 - trunc.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 0 fail - - lwc1 $f2 fp_d1 - lwc1 $f3 fp_d1+4 - trunc.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - lwc1 $f2 fp_d1p6 - lwc1 $f3 fp_d1p6+4 - trunc.w.d $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - - .data -trunc.w.s_: .asciiz "Testing TRUNC.W.S\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 trunc.w.s_ - syscall - - lwc1 $f2 fp_s0 - trunc.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 0 fail - - lwc1 $f2 fp_s1 - trunc.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - lwc1 $f2 fp_s1p6 - trunc.w.s $f0 $f2 - mfc1 $6 $f0 - bne $6 1 fail - - -# -# Testing Pseudo Ops -# - - .data -abs_: .asciiz "Testing ABS\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 abs_ - syscall - - li $2 1 - abs $3 $2 - bne $3 1 fail - - li $2 -1 - abs $2 $2 - bne $2 1 fail - - li $2 0 - abs $2 $2 - bne $2 0 fail - - - .data -b_: .asciiz "Testing B\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 b_ - syscall - - - b l101 - b fail -l101: - - - .data -bal_: .asciiz "Testing BAL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bal_ - syscall - - bal l102 -l103: j l104 -l102: la $4 l103 - bne $31 $4 fail - jr $31 -l104: - - - .data -beqz_: .asciiz "Testing BEQZ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 beqz_ - syscall - - beqz $0 l105 - j fail -l105: li $2 1 - beqz $2 fail - - - .data -bge_: .asciiz "Testing BGE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bge_ - syscall - - bge $0 $0 l106 - j fail -l106: li $2 1 - bge $0 $2 fail - bge $2 $0 l107 - j fail -l107: li $3 -1 - bge $3 $2 fail - bge $2 $3 l108 - j fail -l108: - - bge $0 0 l109 - j fail -l109: li $2 1 - bge $0 1 fail - bge $2 0 l110 - j fail -l110: li $3 -1 - bge $3 1 fail - bge $2 -1 l111 - j fail -l111: - - - .data -bgeu_: .asciiz "Testing BGEU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bgeu_ - syscall - - bgeu $0 $0 l112 - j fail -l112: li $2 1 - bgeu $0 $2 fail - bgeu $2 $0 l113 - j fail -l113: li $3 -1 - bgeu $2 $3 fail - bgeu $3 $2 l114 - j fail -l114: - - bgeu $0 0 l115 - j fail -l115: li $2 1 - bgeu $0 1 fail - bgeu $2 0 l116 - j fail -l116: li $3 -1 - bgeu $2 -1 fail - bgeu $3 1 l117 - j fail -l117: - - - .data -bgt_: .asciiz "Testing BGT\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bgt_ - syscall - - bgt $0 $0 fail -l120: li $2 1 - bgt $0 $2 fail - bgt $2 $0 l121 - j fail -l121: li $3 -1 - bgt $3 $2 fail - bgt $2 $3 l122 - j fail -l122: - - bgt $0 0 fail -l123: li $2 1 - bgt $0 1 fail - bgt $2 0 l124 - j fail -l124: li $3 -1 - bgt $3 1 fail - bgt $2 -1 l125 - j fail -l125: - - - .data -bgtu_: .asciiz "Testing BGTU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bgtu_ - syscall - - bgtu $0 $0 fail -l132: li $2 1 - bgtu $0 $2 fail - bgtu $2 $0 l133 - j fail -l133: li $3 -1 - bgtu $2 $3 fail - bgtu $3 $2 l134 - j fail -l134: - - bgtu $0 0 fail -l135: li $2 1 - bgtu $0 1 fail - bgtu $2 0 l136 - j fail -l136: li $3 -1 - bgtu $2 -1 fail - bgtu $3 1 l137 - j fail -l137: - - - .data -ble_: .asciiz "Testing BLE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ble_ - syscall - - ble $0 $0 l140 - j fail -l140: li $2 1 - ble $2 $0 fail - ble $0 $2 l141 - j fail -l141: li $3 -1 - ble $2 $3 fail - ble $3 $2 l142 - j fail -l142: - - ble $0 0 l143 - j fail -l143: li $2 1 - ble $2 0 fail - ble $0 1 l144 - j fail -l144: li $3 -1 - ble $2 -1 fail - ble $3 1 l145 - j fail -l145: - - - .data -bleu_: .asciiz "Testing BLEU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bleu_ - syscall - - bleu $0 $0 l152 - j fail -l152: li $2 1 - bleu $2 $0 fail - bleu $0 $2 l153 - j fail -l153: li $3 -1 - bleu $3 $2 fail - bleu $2 $3 l154 - j fail -l154: - - bleu $0 0 l155 - j fail -l155: li $2 1 - bleu $2 0 fail - bleu $0 1 l156 - j fail -l156: li $3 -1 - bleu $3 1 fail - bleu $2 -1 l157 - j fail -l157: - - - .data -blt_: .asciiz "Testing BLT\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 blt_ - syscall - - blt $0 $0 fail -l160: li $2 1 - blt $2 $0 fail - blt $0 $2 l161 - j fail -l161: li $3 -1 - blt $2 $3 fail - blt $3 $2 l162 - j fail -l162: - - blt $0 0 fail -l163: li $2 1 - blt $2 0 fail - blt $0 1 l164 - j fail -l164: li $3 -1 - blt $2 -1 fail - blt $3 1 l165 - j fail -l165: - - - .data -bltu_: .asciiz "Testing BLTU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bltu_ - syscall - - bltu $0 $0 fail -l172: li $2 1 - bltu $2 $0 fail - bltu $0 $2 l173 - j fail -l173: li $3 -1 - bltu $3 $2 fail - bltu $2 $3 l174 - j fail -l174: - - bltu $0 0 fail -l175: li $2 1 - bltu $2 0 fail - bltu $0 1 l176 - j fail -l176: li $3 -1 - bltu $3 1 fail - bltu $2 -1 l177 - j fail -l177: - - - .data -bnez_: .asciiz "Testing BNEZ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 bnez_ - syscall - - bnez $0 fail - li $2 1 - bnez $2 l180 - j fail -l180: - - -# DIV and DIVU checked previously - - -# LA better work or nothing above will work - - - .data -li_: .asciiz "Testing LI\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 li_ - syscall - - li $2 0xfffffff - bne $2 0xfffffff fail - li $2 0xffffffe - bne $2 0xffffffe fail - li $2 0 - bnez $2 fail - li $2 0x7fffffff - bne $2 0x7fffffff fail - li $2 32767 - bne $2 32767 fail - li $2 32768 - bne $2 32768 fail - li $2 65535 - bne $2 65535 fail - li $2 65536 - bne $2 65536 fail - - - .data -li.d_: .asciiz "Testing LI.d\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 li.d_ - syscall - - li.d $f0 1.0 - mfc1 $2, $f0 - mfc1 $3, $f1 - lw $4, fp_d1 - lw $5, fp_d1+4 - bne $2 $4 fail - bne $3 $5 fail - - li.d $f0 -1.0 - mfc1 $2, $f0 - mfc1 $3, $f1 - lw $4, fp_dm1 - lw $5, fp_dm1+4 - bne $2 $4 fail - bne $3 $5 fail - - - .data -li.s_: .asciiz "Testing LI.s\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 li.s_ - syscall - - li.s $f0 1.0 - mfc1 $2, $f0 - lw $3, fp_s1 - bne $2 $3 fail - - li.s $f0 -1.0 - mfc1 $2, $f0 - lw $3, fp_sm1 - bne $2 $3 fail - - - .data -move_: .asciiz "Testing MOVE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 move_ - syscall - - li $2 0xfffffff - move $3 $2 - bne $2 $3 fail - - -# MUL and MULO and MULOU were tested previously - - - .data -neg_: .asciiz "Testing NEG\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 neg_ - syscall - - li $2 -101 - neg $3 $2 - bne $3 101 fail - li $2 101 - neg $2 $2 - bne $2 -101 fail - neg $2 $0 - bne $2 0 fail - - - .data -negu_: .asciiz "Testing NEGU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 negu_ - syscall - - li $2 -101 - negu $3 $2 - bne $3 101 fail - li $2 101 - negu $2 $2 - bne $2 -101 fail - negu $2 $0 - bne $2 0 fail - - - .data -nop_: .asciiz "Testing NOP\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 nop_ - syscall - - nop # How do we test it?? - - - .data -not_: .asciiz "Testing NOT\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 not_ - syscall - - not $2 $0 - bne $2 0xffffffff fail - li $2 0 - not $3 $2 - bne $3 0xffffffff fail - li $2 0xffffffff - not $3 $2 - bne $3 0 fail - - - .data -rem_: .asciiz "Testing REM\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 rem_ - syscall - - li $2 5 - li $3 2 - li $4 -2 - - rem $5 $2 $3 - bne $5 1 fail - - rem $5 $2 $4 - bne $5 1 fail - - .data -remu_: .asciiz "Testing REMU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 remu_ - syscall - - li $2 5 - li $3 2 - li $4 -2 - - remu $5 $2 $3 - bne $5 1 fail - - remu $5 $2 $4 - bne $5 5 fail - - - .data -rol_: .asciiz "Testing ROL\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 rol_ - syscall - li $2 5 - li $3 5 - rol $4 $2 $3 - bne $4 0xa0 fail - li $2 5 - li $3 -5 - rol $4 $2 $3 - bne $4 0x28000000 fail - li $2 5 - rol $4 $2 5 - bne $4 0xa0 fail - - - .data -ror_: .asciiz "Testing ROR\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ror_ - syscall - li $2 5 - li $3 5 - ror $4 $2 $3 - bne $4 0x28000000 fail - li $2 5 - li $3 -5 - ror $4 $2 $3 - bne $4 0xa0 fail - li $2 5 - ror $4 $2 5 - bne $4 0x28000000 fail - - - .data -seq_: .asciiz "Testing SEQ\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 seq_ - syscall - - li $2 -1 - li $3 1 - - seq $4 $0 $0 - beqz $4 fail - seq $4 $2 $3 - bnez $4 fail - - seq $4 $0 0 - beqz $4 fail - seq $4 $3 2 - bnez $4 fail - - - .data -sge_: .asciiz "Testing SGE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sge_ - syscall - - sge $4 $0 $0 - beqz $4 fail - li $2 1 - sge $4 $0 $2 - bnez $4 fail - sge $4 $2 $0 - beqz $4 fail - li $2 -1 - sge $4 $0 $2 - beqz $4 fail - sge $4 $2 $0 - bnez $4 fail - - li $2 1 - sge $2 $0 $2 - bnez $2 fail - li $2 1 - sge $2 $2 $0 - beqz $2 fail - li $2 -1 - sge $2 $0 $2 - beqz $2 fail - li $2 -1 - sge $2 $2 $0 - bnez $2 fail - - sge $4 $0 0 - beqz $4 fail - li $2 1 - sge $4 $0 1 - bnez $4 fail - sge $4 $2 0 - beqz $4 fail - li $2 -1 - sge $4 $0 -1 - beqz $4 fail - sge $4 $2 0 - bnez $4 fail - - - .data -sgeu_: .asciiz "Testing SGEU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sgeu_ - syscall - - sgeu $4 $0 $0 - beqz $4 fail - li $2 1 - sgeu $4 $0 $2 - bnez $4 fail - sgeu $4 $2 $0 - beqz $4 fail - li $2 -1 - sgeu $4 $0 $2 - bnez $4 fail - sgeu $4 $2 $0 - beqz $4 fail - - sgeu $4 $0 0 - beqz $4 fail - li $2 1 - sgeu $4 $0 1 - bnez $4 fail - sgeu $4 $2 0 - beqz $4 fail - li $2 -1 - sgeu $4 $0 -1 - bnez $4 fail - sgeu $4 $2 0 - beqz $4 fail - - - .data -sgt_: .asciiz "Testing SGT\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sgt_ - syscall - - sgt $4 $0 $0 - bnez $4 fail - li $2 1 - sgt $4 $0 $2 - bnez $4 fail - sgt $4 $2 $0 - beqz $4 fail - li $2 -1 - sgt $4 $0 $2 - beqz $4 fail - sgt $4 $2 $0 - bnez $4 fail - - sgt $4 $0 0 - bnez $4 fail - sgt $4 $0 1 - bnez $4 fail - li $2 1 - sgt $4 $2 0 - beqz $4 fail - sgt $4 $0 -1 - beqz $4 fail - li $2 -1 - sgt $4 $2 0 - bnez $4 fail - - .data -sgtu_: .asciiz "Testing SGTU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sgtu_ - syscall - - sgtu $4 $0 $0 - bnez $4 fail - li $2 1 - sgtu $4 $0 $2 - bnez $4 fail - sgtu $4 $2 $0 - beqz $4 fail - li $2 -1 - sgtu $4 $0 $2 - bnez $4 fail - sgtu $4 $2 $0 - beqz $4 fail - - sgtu $4 $0 0 - bnez $4 fail - sgtu $4 $0 1 - bnez $4 fail - li $2 1 - sgtu $4 $2 0 - beqz $4 fail - sgtu $4 $0 -1 - bnez $4 fail - li $2 -1 - sgtu $4 $2 0 - beqz $4 fail - - - .data -sle_: .asciiz "Testing SLE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sle_ - syscall - - sle $4 $0 $0 - beqz $4 fail - li $2 1 - sle $4 $0 $2 - beqz $4 fail - sle $4 $2 $0 - bnez $4 fail - li $2 -1 - sle $4 $0 $2 - bnez $4 fail - sle $4 $2 $0 - beqz $4 fail - - li $2 1 - sle $2 $0 $2 - beqz $2 fail - li $2 1 - sle $2 $2 $0 - bnez $2 fail - li $2 -1 - sle $2 $0 $2 - bnez $2 fail - li $2 -1 - sle $2 $2 $0 - beqz $2 fail - - sle $4 $0 0 - beqz $4 fail - li $2 1 - sle $4 $0 1 - beqz $4 fail - sle $4 $2 0 - bnez $4 fail - li $2 -1 - sle $4 $0 -1 - bnez $4 fail - sle $4 $2 0 - beqz $4 fail - - - .data -sleu_: .asciiz "Testing SLEU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sleu_ - syscall - - sleu $4 $0 $0 - beqz $4 fail - li $2 1 - sleu $4 $0 $2 - beqz $4 fail - sleu $4 $2 $0 - bnez $4 fail - li $2 -1 - sleu $4 $0 $2 - beqz $4 fail - sleu $4 $2 $0 - bnez $4 fail - - sleu $4 $0 0 - beqz $4 fail - li $2 1 - sleu $4 $0 1 - beqz $4 fail - sleu $4 $2 0 - bnez $4 fail - li $2 -1 - sleu $4 $0 -1 - beqz $4 fail - sleu $4 $2 0 - bnez $4 fail - - - .data -sne_: .asciiz "Testing SNE\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sne_ - syscall - - li $2 -1 - li $3 1 - - sne $4 $0 $0 - bnez $4 fail - sne $4 $2 $3 - beqz $4 fail - - sne $4 $0 0 - bnez $4 fail - sne $4 $3 2 - beqz $4 fail - - -# ULH is endian-specific - - -# ULHU is endian-specific - - -# ULW is endian-specific - - -# USH is endian-specific - - -# USW is endian-specific - - -# .WORD is endian-specific - - -OK: - - -# Done !!! - .data -sm: .asciiz "\nPassed all tests\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sm - syscall - lw $31 saved_ret_pc - jr $31 # Return from main - - - .data -fm: .asciiz "Failed test\n" - .text -fail: li $v0 4 # syscall 4 (print_str) - la $a0 fm - syscall - li $v0, 10 # syscall 10 (exit) - syscall - - - .text 0x408000 -far_away: - beq $0, $0, come_back diff --git a/spim-qtbase/Tests/tt.dir.s b/spim-qtbase/Tests/tt.dir.s deleted file mode 100644 index 592745f..0000000 --- a/spim-qtbase/Tests/tt.dir.s +++ /dev/null @@ -1,167 +0,0 @@ -# SPIM S20 MIPS simulator. -# A torture test for the SPIM simulator. -# Test assembler directives. -# -# Copyright (c) 2021, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - - - .data -saved_ret_pc: .word 0 # Holds PC to return from main -m1: .asciiz "Tests 1\n" - .data - .align 2 -l1: .byte 0xff -l2: .half 0xffff -l3: .word 0xffff -l4: .float 1.0 -l5: .double 1.0 - -m2: .asciiz "Tests 2\n" - .data - .align 2 -l12: .byte 0xff -l22: .half 0xffff - .byte 0xff -l32: .word 0xffff - .byte 0xff -l42: .float 1.0 - .byte 0xff -l52: .double 1.0 - -m3: .asciiz "Tests 3\n" - .data - .align 0 -l13: .byte 0xff -l23: .half 0xffff -l33: .word 0xffff -l43: .float 1.0 -l53: .double 1.0 - - .text - .globl main -main: - sw $31 saved_ret_pc - - - li $v0 4 # syscall 4 (print_str) - la $a0 m1 - syscall - - la $t0 l1 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - la $t0 l2 - and $t0 $t0 0x3 - bne $t0 0x2 fail - - la $t0 l3 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - la $t0 l4 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - la $t0 l5 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - - li $v0 4 # syscall 4 (print_str) - la $a0 m2 - syscall - - la $t0 l12 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - la $t0 l22 - and $t0 $t0 0x3 - bne $t0 0x2 fail - - la $t0 l32 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - la $t0 l42 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - la $t0 l52 - and $t0 $t0 0x7 - bne $t0 0x0 fail - - -li $v0 4 # syscall 4 (print_str) - la $a0 m3 - syscall - - la $t0 l13 - and $t0 $t0 0x3 - bne $t0 0x1 fail - - la $t0 l23 - and $t0 $t0 0x3 - bne $t0 0x2 fail - - la $t0 l33 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - la $t0 l43 - and $t0 $t0 0x3 - bne $t0 0x0 fail - - la $t0 l53 - and $t0 $t0 0x3 - bne $t0 0x0 fail - -# Done !!! - .data -sm: .asciiz "\nPassed all tests\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sm - syscall - lw $31 saved_ret_pc - jr $31 # Return from main - - - .data -fm: .asciiz "Failed test\n" - .text -fail: li $v0 4 # syscall 4 (print_str) - la $a0 fm - syscall - li $v0, 10 # syscall 10 (exit) - syscall - diff --git a/spim-qtbase/Tests/tt.fpu.bare.s b/spim-qtbase/Tests/tt.fpu.bare.s deleted file mode 100755 index b5de6a9..0000000 --- a/spim-qtbase/Tests/tt.fpu.bare.s +++ /dev/null @@ -1,2239 +0,0 @@ -# SPIM S20 MIPS simulator. -# A torture test for the FPU instructions in the bare SPIM simulator. -# Copyright (c) 1990-2010, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - -# Adapted by Anne Rogers from tt.le.s. -# Run -bare -notrap. - - -# Test floating point instructions. Warning: This code is not relocatable. -# New data statements should be added after "Testing C.UN.S\n". - - .data -saved_ret_pc: .word 0 # Holds PC to return from main -sm: .asciiz "Failed " -pt: .asciiz "Passed all tests\n" - - .text -# Standard startup code. Invoke the routine main with no arguments. - .globl __start -__start: jal main - addu $0 $0 $0 # Nop - addiu $2 $0 10 - syscall # syscall 10 (exit) - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - - .globl main -main: - lui $4 0x1000 - sw $31 0($4) - - - .data -abs.s_:.asciiz "Testing ABS.S\n" -fp_s100:.float 100.0 -fp_sm100:.float -100.0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 abs.s_ - lui $a0, 0x1000 - ori $a0 $a0 0x1f - syscall - - lui $2 0x1000 - ori $2 $2 0x30 - lwc1 $f0 0($2) - addu $0 $0 $0 - lw $4 0($2) - addu $0 $0 $0 - mfc1 $5 $f0 - addu $0 $0 $0 - bne $5 $4 fail - addu $0 $0 $0 - abs.s $f2 $f0 - mfc1 $5 $f2 - addu $0 $0 $0 #Nop - bne $4 $5 fail - - lwc1 $f0 4($2) - abs.s $f2 $f0 - mfc1 $5 $f2 - addu $0 $0 $0 #Nop - bne $4 $5 fail - addu $0 $0 $0 #Nop - - .data -abs.d_:.asciiz "Testing ABS.D\n" -fp_d100:.double 100.0 -fp_dm100:.double -100.0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 abs.d_ - lui $a0, 0x1000 - ori $a0 $a0 0x38 - syscall - -# la $2 fp_d100 - lui $2, 0x1000 - ori $2 $2 0x48 - lw $4 0($2) - lw $5 4($2) - lwc1 $f0 0($2) - lwc1 $f1 4($2) - addu $0 $0 $0 #Nop - abs.d $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 #Nop - bne $4 $6 fail - addu $0 $0 $0 #Nop - bne $5 $7 fail - - lwc1 $f0 8($2) - lwc1 $f1 12($2) - addu $0 $0 $0 #Nop - abs.d $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 #Nop - bne $4 $6 fail - addu $0 $0 $0 #Nop - bne $5 $7 fail - - - .data -add.s_: .asciiz "Testing ADD.S\n" -fp_s0: .float 0.0 -fp_s1: .float 1.0 -fp_sm1: .float -1.0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 add.s_ - lui $a0 0x1000 - ori $a0 $a0 0x58 - syscall - - lui $2, 0x1000 - ori $2 $2 0x68 - lw $4 0($2) - lwc1 $f0 0($2) - addu $0 $0 $0 # Nop - add.s $f2 $f0 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - lw $4 4($2) - lwc1 $f0 0($2) - lwc1 $f2 4($2) - addu $0 $0 $0 # Nop - add.s $f4 $f0 $f2 - mfc1 $6 $f4 - addu $0 $0 $0 # Nop - bne $4 $6 fail - - lw $4 0($2) - lwc1 $f0 4($2) - lwc1 $f2 8($2) - addu $0 $0 $0 # Nop - add.s $f4 $f0 $f2 - mfc1 $6 $f4 - addu $0 $0 $0 # Nop - bne $4 $6 fail - - .data -add.d_: .asciiz "Testing ADD.D\n" -fp_d0: .double 0.0 -fp_d1: .double 1.0 -fp_dm1: .double -1.0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 add.d_ - lui $a0 0x1000 - ori $a0 $a0 0x74 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lw $4 0($1) - lw $5 4($1) - lwc1 $f0 0($1) - lwc1 $f1 4($1) - addu $0 $0 $0 # Nop - add.d $f2 $f0 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - - lw $4 8($1) - lw $5 12($1) - lwc1 $f0 0($1) - lwc1 $f1 4($1) - lwc1 $f2 8($1) - lwc1 $f3 12($1) - addu $0 $0 $0 # Nop - add.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - - lw $4 0($1) - lw $5 4($1) - lwc1 $f0 8($1) - lwc1 $f1 12($1) - lwc1 $f2 16($1) - lwc1 $f3 20($1) - addu $0 $0 $0 # Nop - add.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - .data -cvt.d.s_: .asciiz "Testing CVT.D.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 cvt.d.s_ - lui $a0 0x1000 - ori $a0 $a0 0xa0 - syscall - - - lui $1 0x1000 - ori $1 $1 0x88 - lw $4 0($1) #fp_d0 - lw $5 4($1) #fp_d0+4 - lui $2, 0x1000 - ori $2 $2 0x68 - lwc1 $f0 0($2) #fp_s0 - addu $0 $0 $0 # Nop - cvt.d.s $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - lw $4 8($1) # fp_d1 - lw $5 12($1) # fp_d1+4 - lwc1 $f0 4($2) # fp_s1 - addu $0 $0 $0 # Nop - cvt.d.s $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - lw $4 16($1) # fp_dm1 - lw $5 20($1) # fp_dm1+4 - lwc1 $f0 8($2) # fp_sm1 - addu $0 $0 $0 # Nop - cvt.d.s $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - .data -cvt.d.w_: .asciiz "Testing CVT.D.W\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 cvt.d.w_ - lui $a0 0x1000 - ori $a0 $a0 0xb1 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lw $4 0($1) # fp_d0 - lw $5 4($1) # fp_d0+4 - mtc1 $0 $0 - addu $0 $0 $0 # Nop - cvt.d.w $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - lw $4 8($1) # fp_d1 - lw $5 12 ($1) # fp_d1+4 - addi $9 $0 1 - mtc1 $9 $0 - addu $0 $0 $0 # Nop - cvt.d.w $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - lw $4 16($1) # fp_dm1 - lw $5 20($1) # fp_dm1+4 - addi $9 $0 -1 - mtc1 $9 $0 - addu $0 $0 $0 # Nop - cvt.d.w $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - .data -cvt.s.d_: .asciiz "Testing CVT.S.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 cvt.s.d_ - lui $a0 0x1000 - ori $a0 $a0 0xc2 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lw $4 0($1) # fp_s0 - lui $2 0x1000 - ori $2 $2 0x88 - lwc1 $f0 0($2) # fp_d0 - lwc1 $f1 4($2) # fp_d0+4 - addu $0 $0 $0 #Nop - cvt.s.d $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 - bne $4 $6 fail - addu $0 $0 $0 - - lw $4 4($1) # fp_s1 - lwc1 $f0 8($2) # fp_d1 - lwc1 $f1 12($2) # fp_d1+4 - addu $0 $0 $0 #Nop - cvt.s.d $f2 $f0 - addu $0 $0 $0 - mfc1 $6 $f2 - addu $0 $0 $0 - bne $4 $6 fail - addu $0 $0 $0 - - lw $4 8($1) # fp_sm1 - lwc1 $f0 16($2) # fp_dm1 - lwc1 $f1 20 ($2) # fp_dm1+4 - addu $0 $0 $0 #Nop - cvt.s.d $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 - bne $4 $6 fail - addu $0 $0 $0 - - - .data -cvt.s.w_: .asciiz "Testing CVT.S.W\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 cvt.s.w_ - lui $a0 0x1000 - ori $a0 $a0 0xd3 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lw $4 0($1) # fp_s0 - mtc1 $0 $0 - cvt.s.w $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 - bne $4 $6 fail - addu $0 $0 $0 - - lw $4 4($1) # fp_s1 - addi $9 $0 1 - mtc1 $9 $0 - cvt.s.w $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 - bne $4 $6 fail - addu $0 $0 $0 - - lw $4 8($1) # fp_sm1 - addi $9 $0 -1 - mtc1 $9 $0 - cvt.s.w $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 - bne $4 $6 fail - addu $0 $0 $0 - - - .data -cvt.w.d_: .asciiz "Testing CVT.W.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 cvt.w.d_ - lui $a0 0x1000 - ori $a0 $a0 0xe4 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lwc1 $f0 0($1) # fp_d0 - lwc1 $f1 4($1) # fp_d0+4 - addu $0 $0 $0 # Nop - cvt.w.d $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 # Nop - bne $0 $6 fail - addu $0 $0 $0 # Nop - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # fp_d1+4 - addu $0 $0 $0 # Nop - cvt.w.d $f2 $f0 - mfc1 $6 $f2 - addi $4 $0 1 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - lwc1 $f0 16($1) # fp_dm1 - lwc1 $f1 20($1) # fp_dm1+4 - addu $0 $0 $0 #Nop - cvt.w.d $f2 $f0 - mfc1 $6 $f2 - addi $4 $0 -1 - bne $4 $6 fail - addu $0 $0 $0 # Nop - - - .data -cvt.w.s_: .asciiz "Testing CVT.W.S\n" - .text -# addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 cvt.w.s_ - lui $a0 0x1000 - ori $a0 $a0 0xf5 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lwc1 $f0 0($1) # fp_s0 - addu $0 $0 $0 #Nop - cvt.w.s $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 # Nop - bne $0 $6 fail - addu $0 $0 $0 # Nop - - lwc1 $f0 4($1) # fp_s1 - addu $0 $0 $0 #Nop - cvt.w.s $f2 $f0 - mfc1 $6 $f2 - addi $4 $0 1 - bne $4 $6 fail - addu $0 $0 $0 # Nop - - lwc1 $f0 8($1) # fp_sm1 - addu $0 $0 $0 #Nop - cvt.w.s $f2 $f0 - mfc1 $6 $f2 - addi $4 $0 -1 - bne $4 $6 fail - addu $0 $0 $0 # Nop - - - .data -div.s_: .asciiz "Testing DIV.S\n" -fp_s2: .float 2.0 -fp_s3: .float 3.0 -fp_s1p5:.float 1.5 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 div.s_ - lui $a0 0x1000 - ori $a0 $a0 0x106 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lw $4 4($1) # fp_s1 - lwc1 $f0 4($1) # fp_s1 - addu $0 $0 $0 #Nop - div.s $f2 $f0 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - lui $2 0x1000 - ori $2 $2 0x118 - lw $4 8($2) # fp_s1p5 - lwc1 $f0 4($2) # fp_s3 - lwc1 $f2 0($2) # fp_s2 - addu $0 $0 $0 #Nop - div.s $f4 $f0 $f2 - mfc1 $6 $f4 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - - .data -div.d_: .asciiz "Testing DIV.D\n" -# EOS = 132...align to 138 -fp_d2: .double 2.0 -fp_d3: .double 3.0 -fp_d1p5:.double 1.5 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 div.d_ - lui $a0 0x1000 - ori $a0 $a0 0x124 - syscall - - lui $1 0x1000 - ori $1 $1 0x90 - lw $4 0($1) # fp_d1 - lw $5 4($1) # fp_d1+4 - lwc1 $f0 0($1) # fp_d1 - lwc1 $f1 4($1) # fp_d1+4 - addu $0 $0 $0 #Nop - div.d $f2 $f0 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - - lui $2 0x1000 - ori $2 $2 0x138 # Nop - lw $4 16($2) # fp_d1p5 - lw $5 20($2) # fp_d1p5+4 - lwc1 $f0 8($2) # fp_d3 - lwc1 $f1 12($2) # fp_d3+4 - lwc1 $f2 0($2) # fp_d2 - lwc1 $f3 4($2) # fp_d2+4 - addu $0 $0 $0 # Nop - div.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - .data -mov.s_: .asciiz "Testing MOV.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 mov.s_ - lui $a0 0x1000 - ori $a0 $a0 0x150 - syscall - - - lui $1 0x1000 - ori $1 $1 0x68 - lw $4 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - addu $0 $0 $0 # Nop - mov.s $f4 $f2 - mov.s $f6 $f4 - mfc1 $6 $f6 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - .data -mov.d_: .asciiz "Testing MOV.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 mov.d_ - lui $a0 0x1000 - ori $a0 $a0 0x15f - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lw $4 8($1) # fp_d1 - lw $5 12($1) # fp_d1+4 - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # fp_d1+4 - addu $0 $0 $0 # Nop - mov.d $f4 $f2 - mov.d $f6 $f4 - mfc1 $6 $f6 - mfc1 $7 $f7 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - - .data -mul.s_: .asciiz "Testing MUL.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 mul.s_ - lui $a0 0x1000 - ori $a0 $a0 0x16e - - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lw $4 4($1) # fp_s1 - lwc1 $f0 4($1) # fp_s1 - addu $0 $0 $0 #Nop - mul.s $f2 $f0 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - lui $2 0x1000 - ori $2 $2 0x118 - lw $4 4($2) # fp_s3 - lwc1 $f0 8($2) # fp_s1p5 - lwc1 $f2 0($2) # fp_s2 - addu $0 $0 $0 #Nop - mul.s $f4 $f0 $f2 - mfc1 $6 $f4 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - .data -mul.d_: .asciiz "Testing MUL.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 mul.d_ - lui $a0 0x1000 - ori $a0 $a0 0x17d - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lw $4 0($1) # fp_d1 - lw $5 4($1) # fp_d1+4 - lwc1 $f0 0($1) # fp_d1 - lwc1 $f1 4($1) # fp_d1+4 - addu $0 $0 $0 #Nop - mul.d $f2 $f0 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - lui $2 0x1000 - ori $2 $2 0x138 # Nop - lw $4 8($2) # fp_d3 - lw $5 12($2) # fp_d3+4 - lwc1 $f0 16($2) # fp_d1p5 - lwc1 $f1 20($2) # fp_d1p5+4 - lwc1 $f2 0($2) # fp_d2 - lwc1 $f3 4($2) # fp_d2+4 - addu $0 $0 $0 #Nop - mul.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - - .data -neg.s_: .asciiz "Testing NEG.S\n" -# 0x19b..0x19c -fp_sm3: .float -3.0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 neg.s_ - lui $a0 0x1000 - ori $a0 $a0 0x18c - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lw $4 8($1) # fp_sm1 - lwc1 $f0 4($1) # fp_s1 - addu $0 $0 $0 #Nop - neg.s $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - lui $2 0x1000 - ori $2 $2 0x118 - lw $4 4($2) # fp_s3 - lui $1 0x1000 - ori $1 $1 0x19c - lwc1 $f0 0($1) # fp_sm3 - addu $0 $0 $0 #Nop - neg.s $f2 $f0 - mfc1 $6 $f2 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - .data -neg.d_: .asciiz "Testing NEG.D\n" -fp_dm3: .double -3.0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 neg.d_ - lui $a0 0x1000 - ori $a0 $a0 0x1a0 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lw $4 16($1) # fp_dm1 - lw $5 20($1) # fp_dm1+4 - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # fp_d1+4 - addu $0 $0 $0 #Nop - neg.d $f2 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - lui $2 0x1000 - ori $2 $2 0x138 # Nop - lw $4 8($2) # fp_d3 - lw $5 12($2) # fp_d3+4 - lui $1 0x1000 - ori $1 $1 0x1b0 - lwc1 $f0 0($1) # fp_dm3 - lwc1 $f1 4($1) # fp_dm3+4 - addu $0 $0 $0 #Nop - neg.d $f4 $f0 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - - .data -sub.s_: .asciiz "Testing SUB.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sub.s_ - lui $a0 0x1000 - ori $a0 $a0 0x1b8 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lw $4 0($1) # fp_s0 - lwc1 $f0 0($1) # fp_s0 - addu $0 $0 $0 #Nop - sub.s $f2 $f0 $f0 - mfc1 $6 $f2 - bne $4 $6 fail - - lw $4 8($1) # fp_sm1 - lw $5 4($1) # fp_s1 - lwc1 $f0 0($1) # fp_s0 - lwc1 $f2 4($1) # fp_s1 - addu $0 $0 $0 #Nop - sub.s $f4 $f0 $f2 - mfc1 $6 $f4 - addu $0 $0 $0 # Nop - bne $4 $6 fail - sub.s $f4 $f2 $f0 - mfc1 $6 $f4 - addu $0 $0 $0 # Nop - bne $5 $6 fail - addu $0 $0 $0 # Nop - - lui $2 0x1000 - ori $2 $2 0x118 - lw $4 8($2) # fp_s1p5 - lwc1 $f0 8($2) # fp_s1p5 - lwc1 $f2 4($2) # fp_s3 - addu $0 $0 $0 #Nop - sub.s $f4 $f2 $f0 - mfc1 $6 $f4 - addu $0 $0 $0 # Nop - bne $4 $6 fail - addu $0 $0 $0 # Nop - - .data -sub.d_: .asciiz "Testing SUB.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 sub.d_ - lui $a0 0x1000 - ori $a0 $a0 0x1c7 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lw $4 0($1) # fp_d0 - lw $5 4($1) # fp_d0+4 - lwc1 $f0 0($1) # fp_d0 - lwc1 $f1 4($1) # fp_d0+4 - addu $0 $0 $0 #Nop - sub.d $f2 $f0 $f0 - mfc1 $6 $f2 - mfc1 $7 $f3 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - lw $4 16($1) # fp_dm1 - lw $5 20($1) # fp_dm1+4 - lwc1 $f0 0($1) # fp_d0 - lwc1 $f1 4($1) # fp_d0+4 - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # fp_d1+4 - addu $0 $0 $0 #Nop - sub.d $f4 $f0 $f2 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - lw $4 8($1) # fp_d1 - lw $5 12($1) # fp_d1+4 - sub.d $f4 $f2 $f0 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - lui $2 0x1000 - ori $2 $2 0x138 # Nop - lw $4 16($2) # fp_d1p5 - lw $5 20($2) # fp_d1p5+4 - lwc1 $f0 16($2) # fp_d1p5 - lwc1 $f1 20($2) # fp_d1p5+4 - lwc1 $f2 8($2) # fp_d3 - lwc1 $f3 12($2) # fp_d3+4 - addu $0 $0 $0 #Nop - sub.d $f4 $f2 $f0 - mfc1 $6 $f4 - mfc1 $7 $f5 - bne $4 $6 fail - addu $0 $0 $0 # Nop - bne $5 $7 fail - addu $0 $0 $0 # Nop - - - .data -c.eq.d_: .asciiz "Testing C.EQ.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.eq.d_ - lui $a0 0x1000 - ori $a0 $a0 0x1d6 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # fp_d1+4 - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # fp_d1+4 - lui $2 0x1000 - ori $2 $2 0x138 - lwc1 $f4 16($2) # fp_d1p5 - lwc1 $f5 20($2) # fp_d1p5+4 - addu $0 $0 $0 # Nop - c.eq.d $f0 $f2 - addu $0 $0 $0 - addu $0 $0 $0 - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l200 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l200: c.eq.d $f0 $f4 - addu $0 $2 $2 - addu $0 $3 $3 - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l201 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $4 $4 # Nop Delay slot -l201: addu $0 $5 $5 - - - .data -c.eq.s_: .asciiz "Testing C.EQ.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.eq.s_ - lui $a0 0x1000 - ori $a0 $a0 0x1e6 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - lui $2 0x1000 - ori $2 $2 0x118 - lwc1 $f4 8($2) # fp_s1p5 - addu $0 $0 $0 # Nop Delay slot - c.eq.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l210 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l210: c.eq.s $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l211 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l211: addu $0 $0 $0 # Nop Delay slot - - - - .data -c.f.d_: .asciiz "Testing C.F.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.f.d_ - lui $a0 0x1000 - ori $a0 $a0 0x1f6 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # fp_d1+4 - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # fp_d1+4 - lwc1 $f4 16($2) # fp_d1p5 - lwc1 $f5 20($2) # fp_d1p5+4 - c.f.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l220 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l220: c.f.d $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l221 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l221: addu $0 $0 $0 # Nop Delay slot - - .data -c.f.s_: .asciiz "Testing C.F.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.f.s_ - lui $a0 0x1000 - ori $a0 $a0 0x205 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - lwc1 $f4 8($2) # fp_s1p5 - c.f.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l230 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l230: c.f.s $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l231 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l231: addu $0 $0 $0 # Nop Delay slot - - - .data -c.le.d_: .asciiz "Testing C.LE.D\n" -fp_dm2: .double -2.0 - - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.le.d_ - lui $a0 0x1000 - ori $a0 $a0 0x214 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # fp_d1+4 - lwc1 $f2 16($2) # fp_d1p5 - lwc1 $f3 20($2) # fp_d1p5+4 - lui $3 0x1000 - ori $3 $3 0x228 - lwc1 $f4 0($3) # fp_dm2 - lwc1 $f5 4($3) # fp_dm2+4 - c.le.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l240 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l240: c.le.d $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l241 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l241: c.le.d $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l242 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l242: c.le.d $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l243 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l243: addu $0 $0 $0 # Nop Delay slot - - - - .data -c.le.s_: .asciiz "Testing C.LE.S\n" -fp_sm2: .float -2.0 - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.le.s_ - lui $a0 0x1000 - ori $a0 $a0 0x230 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 8($2) # fp_s1p5 - lui $3 0x1000 - ori $3 $3 0x240 - lwc1 $f4 0($3) # fp_sm2 - c.le.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l250 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l250: c.le.s $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l251 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l251: c.le.s $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l252 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l252: c.le.s $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l253 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l253: addu $0 $0 $0 # Nop Delay slot - - - - - - .data -c.lt.d_: .asciiz "Testing C.LT.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.lt.d_ - lui $a0 0x1000 - ori $a0 $a0 0x244 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # fp_d1+4 - lwc1 $f2 16($2) # fp_d1p5 - lwc1 $f3 20($2) # fp_d1p5+4 - lui $3 0x1000 - ori $3 $3 0x220 - lwc1 $f4 0($3) # fp_dm2 - lwc1 $f5 4($3) # fp_dm2+4 - c.lt.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l260 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l260: c.lt.d $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l261 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l261: c.lt.d $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l262 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l262: c.lt.d $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l263 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l263: - - - .data -c.lt.s_: .asciiz "Testing C.LT.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.lt.s_ - lui $a0 0x1000 - ori $a0 $a0 0x254 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 8($2) # fp_s1p5 - lui $3 0x1000 - ori $3 $3 0x240 - lwc1 $f4 0($3) # fp_sm2 - c.lt.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l270 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l270: c.lt.s $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l271 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l271: c.lt.s $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l272 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l272: c.lt.s $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l273 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l273: - - - .data -c.nge.d_: .asciiz "Testing C.NGE.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.nge.d_ - lui $a0 0x1000 - ori $a0 $a0 0x264 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # fp_d1+4 - lwc1 $f2 16($2) # fp_d1p5 - lwc1 $f3 20($2) # fp_d1p5+4 - lui $3 0x1000 - ori $3 $3 0x220 - lwc1 $f4 0($3) # fp_dm2 - lwc1 $f5 4($3) # fp_dm2+4 - c.nge.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l280 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l280: c.nge.d $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l281 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l281: c.nge.d $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l282 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l282: c.nge.d $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l283 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l283: - - - .data -c.nge.s_: .asciiz "Testing C.NGE.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.nge.s_ - lui $a0 0x1000 - ori $a0 $a0 0x275 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 8($2) # fp_s1p5 - lui $3 0x1000 - ori $3 $3 0x240 - lwc1 $f4 0($3) # fp_sm2 - c.nge.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l290 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l290: c.nge.s $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l291 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l291: c.nge.s $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l292 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l292: c.nge.s $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l293 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l293: - - - .data -c.ngle.d_: .asciiz "Testing C.NGLE.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ngle.d_ - lui $a0 0x1000 - ori $a0 $a0 0x286 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # fp_d1+4 - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # fp_d1+4 - lwc1 $f4 16($2) # fp_d1p5 - lwc1 $f5 20($2) # fp_d1p5+4 - c.ngle.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot -l300: c.ngle.d $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot -l301: - - - .data -c.ngle.s_: .asciiz "Testing C.NGLE.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ngle.s_ - lui $a0 0x1000 - ori $a0 $a0 0x298 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - lwc1 $f4 8($2) # fp_s1p5 - c.ngle.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot -l310: c.ngle.s $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot -l311: - - - .data -c.ngl.d_: .asciiz "Testing C.NGL.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ngl.d_ - lui $a0 0x1000 - ori $a0 $a0 0x2aa - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # Nop - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # Nop - lwc1 $f4 16($2) # fp_d1p5 - lwc1 $f5 20($2) # fp_d1p5+4 - c.ngl.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l320 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l320: c.ngl.d $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l321 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l321: - - - .data -c.ngl.s_: .asciiz "Testing C.NGL.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ngl.s_ - lui $a0 0x1000 - ori $a0 $a0 0x2bb - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - lwc1 $f4 8($2) # fp_s1p5 - c.ngl.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot bc1f fail - bc1t l330 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l330: c.ngl.s $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l331 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l331: - - - .data -c.ngt.d_: .asciiz "Testing C.NGT.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ngt.d_ - lui $a0 0x1000 - ori $a0 $a0 0x2cc - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # Nop - lwc1 $f2 16($2) # fp_d1p5 - lwc1 $f3 20($2) # fp_d1p5+4 - lui $3 0x1000 - ori $3 $3 0x220 - lwc1 $f4 0($3) # fp_dm2 - lwc1 $f5 4($3) # Nop - c.ngt.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l340 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l340: c.ngt.d $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l341 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l341: c.ngt.d $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l342 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l342: c.ngt.d $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l343 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l343: - - - .data -c.ngt.s_: .asciiz "Testing C.NGT.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ngt.s_ - lui $a0 0x1000 - ori $a0 $a0 0x2dd - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 8($2) # fp_s1p5 - lui $3 0x1000 - ori $3 $3 0x240 - lwc1 $f4 0($3) # fp_sm2 - c.ngt.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l350 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l350: c.ngt.s $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l351 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l351: c.ngt.s $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l352 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l352: c.ngt.s $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l353 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l353: - - - .data -c.ole.d_: .asciiz "Testing C.OLE.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ole.d_ - lui $a0 0x1000 - ori $a0 $a0 0x2ee - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # Nop - lwc1 $f2 16($2) # fp_d1p5 - lwc1 $f3 20($2) # fp_d1p5+4 - lui $3 0x1000 - ori $3 $3 0x220 - lwc1 $f4 0($3) # fp_dm2 - lwc1 $f5 4($3) # Nop - c.ole.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l360 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l360: c.ole.d $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l361 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l361: c.ole.d $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l362 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l362: c.ole.d $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l363 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l363: - - - .data -c.ole.s_: .asciiz "Testing C.OLE.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ole.s_ - lui $a0 0x1000 - ori $a0 $a0 0x2ff - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 8($2) # fp_s1p5 - lui $3 0x1000 - ori $3 $3 0x240 - lwc1 $f4 0($3) # fp_sm2 - c.ole.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l370 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l370: c.ole.s $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l371 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l371: c.ole.s $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l372 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l372: c.ole.s $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l373 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l373: - - - .data -c.seq.d_: .asciiz "Testing C.SEQ.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.seq.d_ - lui $a0 0x1000 - ori $a0 $a0 0x310 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # Nop - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # Nop - lwc1 $f4 16($2) # fp_d1p5 - lwc1 $f5 20($2) # fp_d1p5+4 - c.seq.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l380 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l380: c.seq.d $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l381 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l381: - - - .data -c.seq.s_: .asciiz "Testing C.SEQ.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.seq.s_ - lui $a0 0x1000 - ori $a0 $a0 0x321 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - lwc1 $f4 8($2) # fp_s1p5 - c.seq.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l390 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l390: c.seq.s $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l391 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l391: - - - .data -c.sf.d_: .asciiz "Testing C.SF.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.sf.d_ - lui $a0 0x1000 - ori $a0 $a0 0x332 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # Nop - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # Nop - lwc1 $f4 16($2) # fp_d1p5 - lwc1 $f5 20($2) # fp_d1p5+4 - c.sf.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot -l400: c.sf.d $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot -l401: - - - .data -c.sf.s_: .asciiz "Testing C.SF.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.sf.s_ - lui $a0 0x1000 - ori $a0 $a0 0x342 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - lwc1 $f4 8($2) # fp_s1p5 - c.sf.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot -l410: c.sf.s $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot -l411: - - - .data -c.ueq.d_: .asciiz "Testing C.UEQ.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ueq.d_ - lui $a0 0x1000 - ori $a0 $a0 0x352 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # Nop - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # Nop - lwc1 $f4 16($2) # fp_d1p5 - lwc1 $f5 20($2) # fp_d1p5+4 - c.ueq.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l420 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l420: c.ueq.d $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l421 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l421: - - - .data -c.ueq.s_: .asciiz "Testing C.UEQ.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ueq.s_ - lui $a0 0x1000 - ori $a0 $a0 0x363 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - lwc1 $f4 8($2) # fp_s1p5 - c.ueq.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l430 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l430: c.ueq.s $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l431 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l431: - - - .data -c.ule.d_: .asciiz "Testing C.ULE.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ule.d_ - lui $a0 0x1000 - ori $a0 $a0 0x374 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # Nop - lwc1 $f2 16($2) # fp_d1p5 - lwc1 $f3 20($2) # fp_d1p5+4 - lui $3 0x1000 - ori $3 $3 0x220 - lwc1 $f4 0($3) # fp_dm2 - lwc1 $f5 4($3) # Nop - c.ule.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l440 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l440: c.ule.d $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l441 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l441: c.ule.d $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l442 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l442: c.ule.d $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l443 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l443: - - - .data -c.ule.s_: .asciiz "Testing C.ULE.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.ule.s_ - lui $a0 0x1000 - ori $a0 $a0 0x385 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 8($2) # fp_s1p5 - lui $3 0x1000 - ori $3 $3 0x240 - lwc1 $f4 0($3) # fp_sm2 - c.ule.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l450 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l450: c.ule.s $f2 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l451 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l451: c.ule.s $f0 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l452 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l452: c.ule.s $f4 $f0 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1f fail - addu $0 $0 $0 # Nop Delay slot - bc1t l453 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l453: - - - .data -c.un.d_: .asciiz "Testing C.UN.D\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.un.d_ - lui $a0 0x1000 - ori $a0 $a0 0x396 - syscall - - lui $1 0x1000 - ori $1 $1 0x88 - lui $2 0x1000 - ori $2 $2 0x138 - - lwc1 $f0 8($1) # fp_d1 - lwc1 $f1 12($1) # Nop - lwc1 $f2 8($1) # fp_d1 - lwc1 $f3 12($1) # Nop - lwc1 $f4 16($2) # fp_d1p5 - lwc1 $f5 20($2) # fp_d1p5+4 - c.un.d $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l460 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l460: c.un.d $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l461 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l461: - - - .data -c.un.s_: .asciiz "Testing C.UN.S\n" - .text - addi $v0 $0 4 # syscall 4 (print_str) -# la $a0 c.un.s_ - lui $a0 0x1000 - ori $a0 $a0 0x3a6 - syscall - - lui $1 0x1000 - ori $1 $1 0x68 - lui $2 0x1000 - ori $2 $2 0x118 - - lwc1 $f0 4($1) # fp_s1 - lwc1 $f2 4($1) # fp_s1 - lwc1 $f4 8($2) # fp_s1p5 - c.un.s $f0 $f2 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l470 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l470: c.un.s $f0 $f4 - addu $0 $0 $0 # Nop Delay slot - addu $0 $0 $0 # Nop Delay slot - bc1t fail - addu $0 $0 $0 # Nop Delay slot - bc1f l471 - addu $0 $0 $0 # Nop Delay slot - j fail - addu $0 $0 $0 # Nop Delay slot -l471: - - - -# Done !!! - .text - addi $2 $0 4 # syscall 4 (print_str) -# la $a0 pt - lui $a0, 0x1000 - ori $a0 $a0 0xd - syscall - lui $4 0x1000 - lw $31 0($4) - addu $0 $0 $0 # Nop - jr $31 # Return from main - - - - -# .data -#fm: .asciiz "Failed test\n" - .text -fail: addi $2 $0 4 # syscall 4 (print_str) -# la $a0 fm - lui $a0, 0x1000 - ori $a0 $a0 0x4 - syscall - addi $2 $0 10 # syscall 10 (exit) - syscall - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - addu $0 $0 $0 # Nop - diff --git a/spim-qtbase/Tests/tt.in b/spim-qtbase/Tests/tt.in deleted file mode 100755 index 587b092..0000000 --- a/spim-qtbase/Tests/tt.in +++ /dev/null @@ -1,6 +0,0 @@ -17 -1717 -17.18 -1700.18 -17.18e10 -1700.18e10 diff --git a/spim-qtbase/Tests/tt.io.s b/spim-qtbase/Tests/tt.io.s deleted file mode 100755 index 00166ad..0000000 --- a/spim-qtbase/Tests/tt.io.s +++ /dev/null @@ -1,209 +0,0 @@ -# SPIM S20 MIPS simulator. -# Test of memory mapped IO. -# -# Copyright (c) 1990-2010, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - - .data -prompt: .asciiz "SPIM IO Test.\nOnly runs with -mapped_io flag.\nPlease type 6 input lines:\n" -nl: .asciiz "\n" - - .text - .globl main -main: - li $v0 4 - la $a0 prompt - syscall - - -# Register usage: -# s0 loop counter -# t0 address of recv_ctrl -# t1 address of recv_buffer -# t2 address of trans_ctrl -# t3 address of trans_buffer -# t4, t5 temporaries -# t6 char read from input -# t7 1 => char in t6 - - li $s0 3 # loop counter - - - li $t0 0xffff0000 # recv ctrl - li $t1 0xffff0004 # recv buf - li $t2 0xffff0008 # trans ctrl - li $t3 0xffff000c # trans buf - -# First, read and echo 3 lines of input by polling the IO registers, not through -# interrupts: - - mtc0 $0 $12 # Clear IE bit in Status reg to disable interrupts - -l1: - lw $t4 0($t0) # Wait for receiver ready - and $t4 $t4 1 - beq $t4 0 l1 - - lw $t6 0($t1) # Read character - -l2: - lw $t4 0($t2) # Wait for transmitter ready - and $t4 $t4 1 - beq $t4 0 l2 - - sw $t6 0($t3) # Write character - - beq $t6 0xa decr # New line (nl) - bne $t6 0xd l1 # Carriage return (cr) - -decr: - add $s0 $s0 -1 # Decrement line counter - bne $s0 0 l1 # If not zero, get another line - - -# Second, read and echo 3 lines of input by through interrupts: - - mfc0 $t4 $13 - and $t4 0xffff00ff # Clear IP bits in Cause register - mtc0 $t4 $13 - - li $s0 3 # loop counter - - li $t4 0x2 # Enable device interrupts - sw $t4 0($t0) - sw $t4 0($t2) - - mfc0 $t4 $12 # Enable interrupts and mask in Status reg - ori $t4 $t4 0xff01 - mtc0 $t4 $12 - - -l3: b l3 # Loop waiting for interrupts - - -# Trap handler. Replaces the standard SPIM handler. - - .ktext 0x80000180 - mfc0 $t4 $13 # Get ExcCode field from Cause reg - srl $t5 $t4 2 - and $t5 $t5 0x1f # ExcCode field - bne $t5 0 exception - -# An interrupt: - and $t5 $t4 0x800 # Check for IP3 (HW 1) - beq $t5 0 check_trans - -# Receiver interrupt: - lw $t5 0($t0) # Check receiver ready - and $t5 $t5 1 - beq $t5 0 no_recv_ready # Error if receiver is not ready - - lw $t6 0($t1) # Read character - li $t7 1 - - beq $t6 0xa decr2 # New line (nl) - bne $t6 0xd next # Carriage return (cr) - -decr2: - add $s0 $s0 -1 # Decrement line counter - -next: - mfc0 $t4 $13 # Get Cause register - and $t4 0xfffff7ff # Clear IP3 bit - mtc0 $t4 $13 - -check_trans: - beq $t7 0 ret_handler # No char to write yet - - and $t5 $t4 0x400 # Check for IP2 (HW 0) - beq $t5 0 check_loop - -# Transmitter interrupt: - lw $t5 0($t2) # Check transmitter ready - and $t5 $t5 1 - beq $t5 0 no_trans_ready - - sw $t6 0($t3) # Write character - li $t7 0 - - mfc0 $t4 $13 # Get Cause register - and $t4 0xfffffbff # Clear IP2 bit - mtc0 $t4 $13 - -check_loop: - bne $s0 0 ret_handler # If line counter not zero, get another line - -# Done echoing, so terminate program. - li $v0 10 - syscall # syscall 10 (exit) - -# Return from handler. -ret_handler: - mfc0 $t4 $12 # Enable interrupts and mask in Status reg - ori $t4 $t4 0xff01 - mtc0 $t4 $12 - - eret # return to interrupted instruction - - -exception: - li $v0 4 # Non-interrupt exception - la $a0 other_str # Print message and ignore - syscall - b ret_handler - -no_recv_ready: - li $v0 4 # Receiver was not ready after interrupt - la $a0 no_recv_str # Print message and ignore - syscall - b ret_handler - -bad_int: - li $v0 4 # Interrupt was not from recv or trans - la $a0 bad_int_str # Print message and ignore - syscall - b ret_handler - -no_trans_ready: - li $v0 4 # Transmitter was not ready after interrupt - la $a0 no_trans_str # Print message and ignore - syscall - b ret_handler - - .data -other_str: - .asciiz "Non-interrupt exception\n" -no_recv_str: - .asciiz "Receiver not ready\n" -no_trans_str: - .asciiz "Transmitter not ready\n" -bad_int_str: - .asciiz "Unknown interrupt\n" - diff --git a/spim-qtbase/Tests/tt.le.s b/spim-qtbase/Tests/tt.le.s deleted file mode 100755 index be5747b..0000000 --- a/spim-qtbase/Tests/tt.le.s +++ /dev/null @@ -1,546 +0,0 @@ -# SPIM S20 MIPS simulator. -# A torture test for the SPIM simulator. -# Tests for little-endian systems. -# Run in conjunction with tt.core.s -# -# Copyright (c) 1990-2010, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - - .data -saved_ret_pc: .word 0 # Holds PC to return from main -m3: .asciiz "The next few lines should contain exception error messages\n" -m4: .asciiz "Done with exceptions\n\n" -m5: .asciiz "Expect an address error exception:\n " -m6: .asciiz "Expect two address error exceptions:\n" - .text - .globl main -main: - sw $31 saved_ret_pc - - .data -lb_: .asciiz "Testing LB\n" -lbd_: .byte 1, -1, 0, 128 -lbd1_: .word 0x76543210, 0xfedcba98 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lb_ - syscall - - la $2 lbd_ - lb $3 0($2) - bne $3 1 fail - lb $3 1($2) - bne $3 -1 fail - lb $3 2($2) - bne $3 0 fail - lb $3 3($2) - bne $3 0xffffff80 fail - - la $t0 lbd1_ - lb $t1 0($t0) - bne $t1 0x10 fail - lb $t1 1($t0) - bne $t1 0x32 fail - lb $t1 2($t0) - bne $t1 0x54 fail - lb $t1 3($t0) - bne $t1 0x76 fail - lb $t1 4($t0) - bne $t1 0xffffff98 fail - lb $t1 5($t0) - bne $t1 0xffffffba fail - lb $t1 6($t0) - bne $t1 0xffffffdc fail - lb $t1 7($t0) - bne $t1 0xfffffffe fail - - li $v0 4 # syscall 4 (print_str) - la $a0 m5 - syscall - - li $t5 0x7fffffff - lb $3 1000($t5) - - - .data -lbu_: .asciiz "Testing LBU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lbu_ - syscall - - la $2 lbd_ - lbu $3 0($2) - bne $3 1 fail - lbu $3 1($2) - bne $3 0xff fail - lbu $3 2($2) - bne $3 0 fail - lbu $3 3($2) - bne $3 128 fail - - la $t0 lbd1_ - lbu $t1 0($t0) - bne $t1 0x10 fail - lbu $t1 1($t0) - bne $t1 0x32 fail - lbu $t1 2($t0) - bne $t1 0x54 fail - lbu $t1 3($t0) - bne $t1 0x76 fail - lbu $t1 4($t0) - bne $t1 0x98 fail - lbu $t1 5($t0) - bne $t1 0xba fail - lbu $t1 6($t0) - bne $t1 0xdc fail - lbu $t1 7($t0) - bne $t1 0xfe fail - - li $v0 4 # syscall 4 (print_str) - la $a0 m5 - syscall - - li $t5 0x7fffffff - lbu $3 1000($t5) - - - .data -lwl_: .asciiz "Testing LWL\n" - .align 2 -lwld_: .byte 0 1 2 3 4 5 6 7 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lwl_ - syscall - - la $2 lwld_ - move $3 $0 - lwl $3 0($2) - bne $3 0 fail - move $3 $0 - lwl $3 1($2) - bne $3 0x01000000 fail - li $3 5 - lwl $3 1($2) - bne $3 0x01000005 fail - move $3 $0 - lwl $3 2($2) - bne $3 0x02010000 fail - li $3 5 - lwl $3 2($2) - bne $3 0x02010005 fail - move $3 $0 - lwl $3 3($2) - bne $3 0x03020100 fail - li $3 5 - lwl $3 3($2) - bne $3 0x03020100 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 m6 - syscall - - li $t5 0x7fffffff - lwl $3 1000($t5) - lwl $3 1001($t5) - - - .data -lwr_: .asciiz "Testing LWR\n" - .align 2 -lwrd_: .byte 0 1 2 3 4 5 6 7 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 lwr_ - syscall - - la $2 lwrd_ - li $3 0x00000500 - lwr $3 0($2) - bne $3 0x3020100 fail - move $3 $0 - lwr $3 1($2) - bne $3 0x30201 fail - li $3 0x50000000 - lwr $3 1($2) - bne $3 0x50030201 fail - move $3 $0 - lwr $3 2($2) - bne $3 0x0302 fail - li $3 0x50000000 - lwr $3 2($2) - bne $3 0x50000302 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 m6 - syscall - - li $t5 0x7fffffff - lwr $3 1000($t5) - lwr $3 1001($t5) - - - .data -sb_: .asciiz "Testing SB\n" - .align 2 -sbd_: .byte 0, 0, 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sb_ - syscall - - li $3, 1 - la $2 sbd_ - sb $3 0($2) - lw $4 0($2) - bne $4 0x1 fail - li $3 2 - sb $3 1($2) - lw $4 0($2) - bne $4 0x201 fail - li $3 3 - sb $3 2($2) - lw $4 0($2) - bne $4 0x30201 fail - li $3 4 - sb $3 3($2) - lw $4 0($2) - bne $4 0x4030201 fail - - - li $v0 4 # syscall 4 (print_str) - la $a0 m5 - syscall - - li $t5 0x7fffffff - sb $3 1000($t5) - - - .data -sh_: .asciiz "Testing SH\n" -sh2_: .asciiz "Expect two address error exceptions:\n" - .align 2 -shd_: .byte 0, 0, 0, 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sh_ - syscall - - li $3, 1 - la $2 shd_ - sh $3 0($2) - lw $4 0($2) - bne $4 0x1 fail - li $3 2 - sh $3 2($2) - lw $4 0($2) - bne $4 0x20001 fail - - li $v0 4 # syscall 4 (print_str) - la $a0 sh2_ - syscall - - li $t5 0x7fffffff - sh $3 1000($t5) - sh $3 1001($t5) - - - .data -swl_: .asciiz "Testing SWL\n" - .align 2 -swld_: .word 0 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 swl_ - syscall - - la $2 swld_ - li $3 0x01000000 - swl $3 0($2) - lw $4 0($2) - bne $4 0x1 fail - - li $3 0x01020000 - swl $3 1($2) - lw $4 0($2) - bne $4 0x0102 fail - - li $3 0x01020300 - swl $3 2($2) - lw $4 0($2) - bne $4 0x010203 fail - - li $3 0x01020304 - swl $3 3($2) - lw $4 0($2) - bne $4 0x01020304 fail - - - .data -swr_: .asciiz "Testing SWR\n" - .align 2 -swrd_: .word 0 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 swr_ - syscall - - la $2 swrd_ - li $3 1 - swr $3 0($2) - lw $4 0($2) - bne $4 1 fail - - li $3 0x0102 - swr $3 1($2) - lw $4 0($2) - bne $4 0x10201 fail - - li $3 0x010203 - swr $3 2($2) - lw $4 0($2) - bne $4 0x2030201 fail - - li $3 0x01020304 - swr $3 3($2) - lw $4 0($2) - bne $4 0x4030201 fail - - - .data -ulh_: .asciiz "Testing ULH\n" -ulh1_: .byte 1 2 3 4 5 6 7 8 -ulh2_: .byte 0xff 0xff - .text - - li $v0 4 # syscall 4 (print_str) - la $a0 ulh_ - syscall - la $2 ulh1_ - ulh $3 0($2) - bne $3 0x0201 fail - ulh $3 1($2) - bne $3 0x0302 fail - ulh $3 2($2) - bne $3 0x0403 fail - ulh $3 3($2) - bne $3 0x0504 fail - ulh $3 4($2) - bne $3 0x0605 fail - la $2 ulh2_ - ulh $3 0($2) - bne $3 -1 fail - - - .data -ulhu_: .asciiz "Testing ULHU\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ulhu_ - syscall - - li $v0 4 # syscall 4 (print_str) - la $a0 ulhu_ - syscall - la $2 ulh1_ - ulhu $3 0($2) - bne $3 0x0201 fail - ulhu $3 1($2) - bne $3 0x0302 fail - ulhu $3 2($2) - bne $3 0x0403 fail - ulhu $3 3($2) - bne $3 0x0504 fail - ulhu $3 4($2) - bne $3 0x0605 fail - la $2 ulh2_ - ulhu $3 0($2) - bne $3 0xffff fail - - - .data -ulw_: .asciiz "Testing ULW\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ulw_ - syscall - - la $2 ulh1_ - ulw $3 0($2) - bne $3 0x04030201 fail - ulw $3 1($2) - bne $3 0x05040302 fail - ulw $3 2($2) - bne $3 0x06050403 fail - ulw $3 3($2) - bne $3 0x07060504 fail - - - .data -ush_: .asciiz "Testing USH\n" -ushd: .word 0 0 - .text - li $v0 4 # syscall 4 (print_str) - la $a0 ush_ - syscall - - la $2 ushd - sw $0 0($2) - sw $0 4($2) - li $3 0x01020304 - ush $3 0($2) - lw $4 0($2) - bne $4 0x0304 fail - lw $4 4($2) - bne $4 0 fail - - sw $0 0($2) - sw $0 4($2) - li $3 0x01020304 - ush $3 1($2) - lw $4 0($2) - bne $4 0x030400 fail - lw $4 4($2) - bne $4 0 fail - - sw $0 0($2) - sw $0 4($2) - li $3 0x01020304 - ush $3 2($2) - lw $4 0($2) - bne $4 0x03040000 fail - lw $4 4($2) - bne $4 0 fail - - sw $0 0($2) - sw $0 4($2) - li $3 0x01020304 - ush $3 3($2) - lw $4 0($2) - bne $4 0x04000000 fail - lw $4 4($2) - bne $4 0x03 fail - - - .data -usw_: .asciiz "Testing USW\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 usw_ - syscall - - la $2 ushd - sw $0 0($2) - sw $0 4($2) - li $3 -1 - usw $3 0($2) - lw $4 0($2) - bne $4 -1 fail - lw $4 4($2) - bne $4 0 fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - usw $3 1($2) - lw $4 0($2) - bne $4 0xffffff00 fail - lw $4 4($2) - bne $4 0xff fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - usw $3 2($2) - lw $4 0($2) - bne $4 0xffff0000 fail - lw $4 4($2) - bne $4 0xffff fail - - sw $0 0($2) - sw $0 4($2) - li $3 -1 - usw $3 3($2) - lw $4 0($2) - bne $4 0xff000000 fail - lw $4 4($2) - bne $4 0xffffff fail - - - .data -word_: .asciiz "Testing .WORD\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 word_ - syscall - - .data - .align 0 -wordd: .byte 0x1 - .word 0x2345678 - .word 0x9abcdef - .text - la $2 wordd - lwr $3 1($2) - lwl $3 4($2) - bne $3 0x2345678 fail - lwr $3 5($2) - lwl $3 8($2) - bne $3 0x9abcdef fail - - .data - .byte 0 -x: .word OK # Forward reference in unaligned data! - .text - lw $8 x - beq $8 $0 fail -OK: - - -# Done !!! - .data -sm: .asciiz "\nPassed all tests\n" - .text - li $v0 4 # syscall 4 (print_str) - la $a0 sm - syscall - lw $31 saved_ret_pc - jr $31 # Return from main - - - .data -fm: .asciiz "Failed test\n" - .text -fail: li $v0 4 # syscall 4 (print_str) - la $a0 fm - syscall - li $v0, 10 # syscall 10 (exit) - syscall diff --git a/spim-qtbase/helloworld.s b/spim-qtbase/helloworld.s deleted file mode 100644 index db91489..0000000 --- a/spim-qtbase/helloworld.s +++ /dev/null @@ -1,45 +0,0 @@ -# helloworld.s -# -# Print out "Hello World" -# -# Copyright (c) 2013, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - - .data -msg: .asciiz "Hello World" - .extern foobar 4 - - .text - .globl main -main: li $v0, 4 # syscall 4 (print_str) - la $a0, msg # argument: string - syscall # print the string - lw $t1, foobar - - jr $ra # retrun to caller diff --git a/spim-qtbase/spim.cpp b/spim-qtbase/spim.cpp deleted file mode 100755 index 3c8bd72..0000000 --- a/spim-qtbase/spim.cpp +++ /dev/null @@ -1,1277 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef WIN32 -#include -#endif -#include -#include -#include -#include -#include - - -#ifdef RS -/* This is problem on HP Snakes, which define RS in syscall.h */ -#undef RS -#endif - -#include -#include - -#ifdef _AIX -#ifndef NBBY -#define NBBY 8 -#endif -#endif - - -#ifndef WIN32 -#include -#ifdef NEED_TERMIOS -#include -#include -#else -#include -#endif -#endif - -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "parser.h" -#include "sym-tbl.h" -#include "scanner.h" -#include "parser_yacc.h" -#include "data.h" - - -/* Internal functions: */ - -static void console_to_program (); -static void console_to_spim (); -static void control_c_seen (int /*arg*/); -static void flush_to_newline (); -static int get_opt_int (); -static bool parse_spim_command (bool redo); -static void print_reg (int reg_no); -static int print_fp_reg (int reg_no); -static int print_reg_from_string (char *reg); -static void print_all_regs (int hex_flag); -static int read_assembly_command (); -static int str_prefix (char *s1, char *s2, int min_match); -static void top_level (); -static int read_token (); -static bool write_assembled_code(char* program_name); -static void dump_data_seg (bool kernel_also); -static void dump_text_seg (bool kernel_also); - - -/* Exported Variables: */ - -/* Not local, but not export so all files don't need setjmp.h */ -jmp_buf spim_top_level_env; /* For ^C */ - -bool bare_machine; /* => simulate bare machine */ -bool delayed_branches; /* => simulate delayed branches */ -bool delayed_loads; /* => simulate delayed loads */ -bool accept_pseudo_insts; /* => parse pseudo instructions */ -bool quiet; /* => no warning messages */ -bool assemble; /* => assemble, write to stdout and exit */ -char *exception_file_name = DEFAULT_EXCEPTION_HANDLER; -port message_out, console_out, console_in; -bool mapped_io; /* => activate memory-mapped IO */ -int pipe_out; -int spim_return_value; /* Value returned when spim exits */ - - -/* Local variables: */ - -/* => load standard exception handler */ -static bool load_exception_handler = true; -static int console_state_saved; -#ifdef NEED_TERMIOS -static struct sgttyb saved_console_state; -#else -static struct termios saved_console_state; -#endif -static int program_argc; -static char** program_argv; -static bool dump_user_segments = false; -static bool dump_all_segments = false; - - - -int -main (int argc, char **argv) -{ - int i; - bool assembly_file_loaded = false; - int print_usage_msg = 0; - - console_out.f = stdout; - message_out.f = stdout; - - bare_machine = false; - delayed_branches = false; - delayed_loads = false; - accept_pseudo_insts = true; - quiet = false; - assemble = false; - spim_return_value = 0; - - /* Input comes directly (not through stdio): */ - console_in.i = 0; - mapped_io = false; - - // write_startup_message (); - - if (getenv ("SPIM_EXCEPTION_HANDLER") != NULL) - exception_file_name = getenv ("SPIM_EXCEPTION_HANDLER"); - - for (i = 1; i < argc; i++) - { -#ifdef WIN32 - if (argv [i][0] == '/') { argv [i][0] = '-'; } -#endif - if (streq (argv [i], "-asm") - || streq (argv [i], "-a")) - { - bare_machine = false; - delayed_branches = false; - delayed_loads = false; - } - else if (streq (argv [i], "-bare") - || streq (argv [i], "-b")) - { - bare_machine = true; - delayed_branches = true; - delayed_loads = true; - quiet = true; - } - else if (streq (argv [i], "-delayed_branches") - || streq (argv [i], "-db")) - { - delayed_branches = true; - } - else if (streq (argv [i], "-delayed_loads") - || streq (argv [i], "-dl")) - { - delayed_loads = true; - } - else if (streq (argv [i], "-exception") - || streq (argv [i], "-e")) - { load_exception_handler = true; } - else if (streq (argv [i], "-noexception") - || streq (argv [i], "-ne")) - { load_exception_handler = false; } - else if (streq (argv [i], "-exception_file") - || streq (argv [i], "-ef")) - { - exception_file_name = argv[++i]; - load_exception_handler = true; - } - else if (streq (argv [i], "-mapped_io") - || streq (argv [i], "-mio")) - { mapped_io = true; } - else if (streq (argv [i], "-nomapped_io") - || streq (argv [i], "-nmio")) - { mapped_io = false; } - else if (streq (argv [i], "-pseudo") - || streq (argv [i], "-p")) - { accept_pseudo_insts = true; } - else if (streq (argv [i], "-nopseudo") - || streq (argv [i], "-np")) - { accept_pseudo_insts = false; } - else if (streq (argv [i], "-quiet") - || streq (argv [i], "-q")) - { quiet = true; } - else if (streq (argv [i], "-noquiet") - || streq (argv [i], "-nq")) - { quiet = false; } - else if (streq (argv [i], "-trap") - || streq (argv [i], "-t")) - { load_exception_handler = true; } - else if (streq (argv [i], "-notrap") - || streq (argv [i], "-nt")) - { load_exception_handler = false; } - else if (streq (argv [i], "-trap_file") - || streq (argv [i], "-tf")) - { - exception_file_name = argv[++i]; - load_exception_handler = true; - } - else if (streq (argv [i], "-stext") - || streq (argv [i], "-st")) - { initial_text_size = atoi (argv[++i]); } - else if (streq (argv [i], "-sdata") - || streq (argv [i], "-sd")) - { initial_data_size = atoi (argv[++i]); } - else if (streq (argv [i], "-ldata") - || streq (argv [i], "-ld")) - { initial_data_limit = atoi (argv[++i]); } - else if (streq (argv [i], "-sstack") - || streq (argv [i], "-ss")) - { initial_stack_size = atoi (argv[++i]); } - else if (streq (argv [i], "-lstack") - || streq (argv [i], "-ls")) - { initial_stack_limit = atoi (argv[++i]); } - else if (streq (argv [i], "-sktext") - || streq (argv [i], "-skt")) - { initial_k_text_size = atoi (argv[++i]); } - else if (streq (argv [i], "-skdata") - || streq (argv [i], "-skd")) - { initial_k_data_size = atoi (argv[++i]); } - else if (streq (argv [i], "-lkdata") - || streq (argv [i], "-lkd")) - { initial_k_data_limit = atoi (argv[++i]); } - else if (((streq (argv [i], "-file") - || streq (argv [i], "-f")) - && (i + 1 < argc)) - /* Assume this argument is a file name and everything following are - arguments for program */ - || (argv [i][0] != '-')) - { - program_argc = argc - (i + 1); - program_argv = &argv[i + 1]; /* Everything following is argv */ - - if (!assembly_file_loaded) - { - initialize_world (load_exception_handler ? exception_file_name : NULL, !quiet); - initialize_run_stack (program_argc, program_argv); - } - assembly_file_loaded = read_assembly_file (argv[++i]) || assembly_file_loaded; - break; - } - else if (streq (argv [i], "-assemble")) - { assemble = true; } - else if (streq (argv [i], "-dump")) - { dump_user_segments = true; } - else if (streq (argv [i], "-full_dump")) - { dump_all_segments = true; } - else - { - error ("\nUnknown argument: %s (ignored)\n", argv[i]); - print_usage_msg = 1; - } - } - - if (print_usage_msg) - { - error ("Usage: spim\n\ - -bare Bare machine (no pseudo-ops, delayed branches and loads)\n\ - -asm Extended machine (pseudo-ops, no delayed branches and loads) (default)\n\ - -delayed_branches Execute delayed branches\n\ - -delayed_loads Execute delayed loads\n\ - -exception Load exception handler (default)\n\ - -noexception Do not load exception handler\n\ - -exception_file Specify exception handler in place of default\n\ - -quiet Do not print warnings\n\ - -noquiet Print warnings (default)\n\ - -mapped_io Enable memory-mapped IO\n\ - -nomapped_io Do not enable memory-mapped IO (default)\n\ - -file Assembly code file and arguments to program\n\ - -assemble Write assembled code to standard output\n\ - -dump Write user data and text segments into files\n\ - -full_dump Write user and kernel data and text into files.\n"); - } - - - if (!assembly_file_loaded) - { - initialize_world (load_exception_handler ? exception_file_name : NULL, !quiet); - initialize_run_stack (program_argc, program_argv); - top_level (); - } - else /* assembly_file_loaded */ - { - if (assemble) - { - return write_assembled_code (program_argv[0]); - } - else if (dump_user_segments) - { - dump_data_seg (false); - dump_text_seg (false); - } - else if (dump_all_segments) - { - dump_data_seg (true); - dump_text_seg (true); - } - else - { - bool continuable; - console_to_program (); - initialize_run_stack (program_argc, program_argv); - if (!setjmp (spim_top_level_env)) - { - char *undefs = undefined_symbol_string (); - if (undefs != NULL) - { - write_output (message_out, "The following symbols are undefined:\n"); - write_output (message_out, undefs); - write_output (message_out, "\n"); - free (undefs); - } - run_program (find_symbol_address (DEFAULT_RUN_LOCATION), DEFAULT_RUN_STEPS, false, false, &continuable); - } - console_to_spim (); - } - } - - return (spim_return_value); -} - - - -/* Top-level read-eval-print loop for SPIM. */ - -static void -top_level () -{ - bool redo = false; /* => reexecute last command */ - - (void)signal (SIGINT, control_c_seen); - initialize_scanner (stdin); - initialize_parser (""); - while (1) - { - if (!redo) - write_output (message_out, "(spim) "); - if (!setjmp (spim_top_level_env)) - redo = parse_spim_command (redo); - else - redo = false; - fflush (stdout); - fflush (stderr); - } -} - - -static void -control_c_seen (int /*arg*/) -{ - console_to_spim (); - write_output (message_out, "\nExecution interrupted\n"); - longjmp (spim_top_level_env, 1); -} - - -/* SPIM commands */ - -enum { - UNKNOWN_CMD = 0, - EXIT_CMD, - READ_CMD, - RUN_CMD, - STEP_CMD, - PRINT_CMD, - PRINT_SYM_CMD, - PRINT_ALL_REGS_CMD, - REINITIALIZE_CMD, - ASM_CMD, - REDO_CMD, - NOP_CMD, - HELP_CMD, - CONTINUE_CMD, - SET_BKPT_CMD, - DELETE_BKPT_CMD, - LIST_BKPT_CMD, - DUMPNATIVE_TEXT_CMD, - DUMP_TEXT_CMD -}; - - -/* Parse a SPIM command from the currently open file and execute it. - If REDO is true, don't read a new command; just rexecute the - previous one. Return true if the command was to redo the previous - command. */ - -static bool -parse_spim_command (bool redo) -{ - static int prev_cmd = NOP_CMD; /* Default redo */ - static int prev_token; - int cmd; - - switch (cmd = (redo ? prev_cmd : read_assembly_command ())) - { - case EXIT_CMD: - console_to_spim (); - exit (0); - - case READ_CMD: - { - int token = (redo ? prev_token : read_token ()); - - if (!redo) flush_to_newline (); - if (token == Y_STR) - { - read_assembly_file ((char *) yylval.p); - pop_scanner(); - } - else - error ("Must supply a filename to read\n"); - prev_cmd = READ_CMD; - return (0); - } - - case RUN_CMD: - { - static mem_addr addr; - bool continuable; - - addr = (redo ? addr : get_opt_int ()); - if (addr == 0) - addr = starting_address (); - - initialize_run_stack (program_argc, program_argv); - console_to_program (); - if (addr != 0) - { - char *undefs = undefined_symbol_string (); - if (undefs != NULL) - { - write_output (message_out, "The following symbols are undefined:\n"); - write_output (message_out, undefs); - write_output (message_out, "\n"); - free (undefs); - } - - if (run_program (addr, DEFAULT_RUN_STEPS, false, false, &continuable)) - write_output (message_out, "Breakpoint encountered at 0x%08x\n", PC); - } - console_to_spim (); - - prev_cmd = RUN_CMD; - return (0); - } - - case CONTINUE_CMD: - { - if (PC != 0) - { - bool continuable; - console_to_program (); - if (run_program (PC, DEFAULT_RUN_STEPS, false, true, &continuable)) - write_output (message_out, "Breakpoint encountered at 0x%08x\n", PC); - console_to_spim (); - } - prev_cmd = CONTINUE_CMD; - return (0); - } - - case STEP_CMD: - { - static int steps; - mem_addr addr; - - steps = (redo ? steps : get_opt_int ()); - addr = PC == 0 ? starting_address () : PC; - - if (steps == 0) - steps = 1; - if (addr != 0) - { - bool continuable; - console_to_program (); - if (run_program (addr, steps, true, true, &continuable)) - write_output (message_out, "Breakpoint encountered at 0x%08x\n", PC); - console_to_spim (); - } - - prev_cmd = STEP_CMD; - return (0); - } - - case PRINT_CMD: - { - int token = (redo ? prev_token : read_token ()); - static int loc; - - if (token == Y_REG) - { - if (redo) loc += 1; - else loc = yylval.i; - print_reg (loc); - } - else if (token == Y_FP_REG) - { - if (redo) loc += 2; - else loc = yylval.i; - print_fp_reg (loc); - } - else if (token == Y_INT) - { - if (redo) loc += 4; - else loc = yylval.i; - print_mem (loc); - } - else if (token == Y_ID) - { - if (!print_reg_from_string ((char *) yylval.p)) - { - if (redo) loc += 4; - else loc = find_symbol_address ((char *) yylval.p); - - if (loc != 0) - print_mem (loc); - else - error ("Unknown label: %s\n", yylval.p); - } - } - else - error ("Print what?\n"); - if (!redo) flush_to_newline (); - prev_cmd = PRINT_CMD; - prev_token = token; - return (0); - } - - case PRINT_SYM_CMD: - print_symbols (); - if (!redo) flush_to_newline (); - prev_cmd = NOP_CMD; - return (0); - - case PRINT_ALL_REGS_CMD: - { - int hex_flag = 0; - int token = (redo ? prev_token : read_token ()); - if (token == Y_ID && streq((char*)yylval.p, "hex")) - hex_flag = 1; - print_all_regs (hex_flag); - if (!redo) flush_to_newline (); - prev_cmd = NOP_CMD; - return (0); - } - - case REINITIALIZE_CMD: - flush_to_newline (); - initialize_world (load_exception_handler ? exception_file_name : NULL, !quiet); - initialize_run_stack (program_argc, program_argv); - write_startup_message (); - prev_cmd = NOP_CMD; - return (0); - - case ASM_CMD: - yyparse (); - prev_cmd = ASM_CMD; - return (0); - - case REDO_CMD: - return (1); - - case NOP_CMD: - prev_cmd = NOP_CMD; - return (0); - - case HELP_CMD: - if (!redo) flush_to_newline (); - write_output (message_out, "\nSPIM is a MIPS32 simulator.\n"); - write_output (message_out, "Its top-level commands are:\n"); - write_output (message_out, "exit -- Exit the simulator\n"); - write_output (message_out, "quit -- Exit the simulator\n"); - write_output (message_out, - "read \"FILE\" -- Read FILE containing assembly code into memory\n"); - write_output (message_out, - "load \"FILE\" -- Same as read\n"); - write_output (message_out, - "run -- Start the program at (optional) ADDRESS\n"); - write_output (message_out, - "step -- Step the program for N instructions (default 1)\n"); - write_output (message_out, - "continue -- Continue program execution without stepping\n"); - write_output (message_out, "print $N -- Print register N\n"); - write_output (message_out, - "print $fN -- Print floating point register N\n"); - write_output (message_out, - "print ADDR -- Print contents of memory at ADDRESS\n"); - write_output (message_out, - "print_symbols -- Print all global symbols\n"); - write_output (message_out, - "print_all_regs -- Print all MIPS registers\n"); - write_output (message_out, - "print_all_regs hex -- Print all MIPS registers in hex\n"); - write_output (message_out, - "reinitialize -- Clear the memory and registers\n"); - write_output (message_out, - "breakpoint -- Set a breakpoint at address ADDR\n"); - write_output (message_out, - "delete -- Delete breakpoint at address ADDR\n"); - write_output (message_out, "list -- List all breakpoints\n"); - write_output (message_out, "dump [ \"FILE\" ] -- Dump binary code to spim.dump or FILE in network byte order\n"); - write_output (message_out, "dumpnative [ \"FILE\" ] -- Dump binary code to spim.dump or FILE in host byte order\n"); - write_output (message_out, - ". -- Rest of line is assembly instruction to execute\n"); - write_output (message_out, " -- Newline reexecutes previous command\n"); - write_output (message_out, "? -- Print this message\n"); - - write_output (message_out, - "\nMost commands can be abbreviated to their unique prefix\n"); - write_output (message_out, "e.g., ex(it), re(ad), l(oad), ru(n), s(tep), p(rint)\n\n"); - prev_cmd = HELP_CMD; - return (0); - - case SET_BKPT_CMD: - case DELETE_BKPT_CMD: - { - int token = (redo ? prev_token : read_token ()); - static mem_addr addr; - - if (!redo) flush_to_newline (); - if (token == Y_INT) - addr = redo ? addr + 4 : (mem_addr)yylval.i; - else if (token == Y_ID) - addr = redo ? addr + 4 : find_symbol_address ((char *) yylval.p); - else - error ("Must supply an address for breakpoint\n"); - if (cmd == SET_BKPT_CMD) - add_breakpoint (addr); - else - delete_breakpoint (addr); - prev_cmd = cmd; - - return (0); - } - - case LIST_BKPT_CMD: - if (!redo) flush_to_newline (); - list_breakpoints (); - prev_cmd = LIST_BKPT_CMD; - return (0); - - case DUMPNATIVE_TEXT_CMD: - case DUMP_TEXT_CMD: - { - int token = (redo ? prev_token : read_token ()); - - FILE *fp = NULL; - char *filename = NULL; - - int words = 0; - mem_addr addr; - mem_addr dump_start; - mem_addr dump_end; - - if (token == Y_STR) - filename = (char *) yylval.p; - else if (token == Y_NL) - filename = "spim.dump"; - else - { - fprintf (stderr, "usage: %s [ \"filename\" ]\n", - (cmd == DUMP_TEXT_CMD ? "dump" : "dumpnative")); - return (0); - } - - fp = fopen (filename, "wbt"); - if (fp == NULL) - { - perror (filename); - return (0); - } - - user_kernel_text_segment (false); - dump_start = find_symbol_address (END_OF_TRAP_HANDLER_SYMBOL); - dump_end = current_text_pc (); - - for (addr = dump_start; addr < dump_end; addr += BYTES_PER_WORD) - { - int32 code = inst_encode (read_mem_inst (addr)); - if (cmd == DUMP_TEXT_CMD) - code = (int32)htonl ((unsigned long)code); /* dump in network byte order */ - (void)fwrite (&code, 1, sizeof(code), fp); - words += 1; - } - - fclose (fp); - fprintf (stderr, "Dumped %d words starting at 0x%08x to file %s\n", - words, (unsigned int)dump_start, filename); - - prev_cmd = cmd; - return (0); - } - - default: - while (read_token () != Y_NL) ; - error ("Unknown spim command\n"); - return (0); - } -} - - -/* Read a SPIM command with the scanner and return its ennuemerated - value. */ - -static int -read_assembly_command () -{ - int token = read_token (); - - if (token == Y_NL) /* Blank line means redo */ - return (REDO_CMD); - else if (token != Y_ID) /* Better be a string */ - return (UNKNOWN_CMD); - else if (str_prefix ((char *) yylval.p, "exit", 2)) - return (EXIT_CMD); - else if (str_prefix ((char *) yylval.p, "quit", 2)) - return (EXIT_CMD); - else if (str_prefix ((char *) yylval.p, "print", 1)) - return (PRINT_CMD); - else if (str_prefix ((char *) yylval.p, "print_symbols", 7)) - return (PRINT_SYM_CMD); - else if (str_prefix ((char *) yylval.p, "print_all_regs", 7)) - return (PRINT_ALL_REGS_CMD); - else if (str_prefix ((char *) yylval.p, "run", 2)) - return (RUN_CMD); - else if (str_prefix ((char *) yylval.p, "read", 2)) - return (READ_CMD); - else if (str_prefix ((char *) yylval.p, "load", 2)) - return (READ_CMD); - else if (str_prefix ((char *) yylval.p, "reinitialize", 6)) - return (REINITIALIZE_CMD); - else if (str_prefix ((char *) yylval.p, "step", 1)) - return (STEP_CMD); - else if (str_prefix ((char *) yylval.p, "help", 1)) - return (HELP_CMD); - else if (str_prefix ((char *) yylval.p, "continue", 1)) - return (CONTINUE_CMD); - else if (str_prefix ((char *) yylval.p, "breakpoint", 2)) - return (SET_BKPT_CMD); - else if (str_prefix ((char *) yylval.p, "delete", 1)) - return (DELETE_BKPT_CMD); - else if (str_prefix ((char *) yylval.p, "list", 2)) - return (LIST_BKPT_CMD); - else if (str_prefix ((char *) yylval.p, "dumpnative", 5)) - return (DUMPNATIVE_TEXT_CMD); - else if (str_prefix ((char *) yylval.p, "dump", 4)) - return (DUMP_TEXT_CMD); - else if (*(char *) yylval.p == '?') - return (HELP_CMD); - else if (*(char *) yylval.p == '.') - return (ASM_CMD); - else - return (UNKNOWN_CMD); -} - - -/* Return non-nil if STRING1 is a (proper) prefix of STRING2. */ - -static int -str_prefix (char *s1, char *s2, int min_match) -{ - for ( ; *s1 == *s2 && *s1 != '\0'; s1 ++, s2 ++) min_match --; - return (*s1 == '\0' && min_match <= 0); -} - - -/* Read and return an integer from the current line of input. If the - line doesn't contain an integer, return 0. In either case, flush the - rest of the line, including the newline. */ - -static int -get_opt_int () -{ - int token; - - if ((token = read_token ()) == Y_INT) - { - flush_to_newline (); - return (yylval.i); - } - else if (token == Y_NL) - return (0); - else - { - flush_to_newline (); - return (0); - } -} - - -/* Flush the rest of the input line up to and including the next newline. */ - -static void -flush_to_newline () -{ - while (read_token () != Y_NL) ; -} - - -/* Print register number N. */ - -static void -print_reg (int reg_no) -{ - write_output (message_out, "Reg %d = 0x%08x (%d)\n", reg_no, R[reg_no], R[reg_no]); -} - - -static int -print_fp_reg (int reg_no) -{ - if ((reg_no & 1) == 0) - write_output (message_out, "FP reg %d = %g (double)\n", reg_no, FPR_D (reg_no)); - write_output (message_out, "FP reg %d = %g (single)\n", reg_no, FPR_S (reg_no)); - return (1); -} - - -static int -print_reg_from_string (char* reg_num) -{ - char s[100]; - char *s1 = s; - - /* Conver to lower case */ - while (*reg_num != '\0' && s1 - s < 100) - *s1++ = tolower (*reg_num++); - *s1 = '\0'; - /* Drop leading $ */ - if (s[0] == '$') - s1 = s + 1; - else - s1 = s; - - if (streq (s1, "pc")) - write_output (message_out, "PC = 0x%08x (%d)\n", PC, PC); - else if (streq (s1, "hi")) - write_output (message_out, "HI = 0x%08x (%d)\n", HI, HI); - else if (streq (s1, "lo")) - write_output (message_out, "LO = 0x%08x (%d)\n", LO, LO); - else if (streq (s1, "fpcond")) - write_output (message_out, "FCSR = 0x%08x (%d)\n", FCSR, FCSR); - else if (streq (s1, "cause")) - write_output (message_out, "Cause = 0x%08x (%d)\n", CP0_Cause, CP0_Cause); - else if (streq (s1, "epc")) - write_output (message_out, "EPC = 0x%08x (%d)\n", CP0_EPC, CP0_EPC); - else if (streq (s1, "status")) - write_output (message_out, "Status = 0x%08x (%d)\n", CP0_Status, CP0_Status); - else if (streq (s1, "badvaddr")) - write_output (message_out, "BadVAddr = 0x%08x (%d)\n", CP0_BadVAddr, CP0_BadVAddr); - else - return (0); - - return (1); -} - - -static void -print_all_regs (int hex_flag) -{ - static str_stream ss; - - ss_clear (&ss); - format_registers (&ss, hex_flag, hex_flag); - write_output (message_out, "%s\n", ss_to_string (&ss)); -} - - -static bool -write_assembled_code(char* program_name) -{ - if (parse_error_occurred) - { - return (parse_error_occurred); - } - - FILE *fp = NULL; - char *filename = NULL; - - mem_addr addr; - mem_addr dump_start; - mem_addr dump_end; - - filename = (char*) xmalloc(strlen(program_name) + 5); - strcpy(filename, program_name); - strcat(filename, ".out"); - - fp = fopen (filename, "wt"); - if (fp == NULL) - { - perror (filename); - return (true); - } - - /* dump text segment */ - user_kernel_text_segment (false); - dump_start = find_symbol_address (END_OF_TRAP_HANDLER_SYMBOL); - dump_end = current_text_pc (); - - (void)fprintf (fp, ".text # 0x%x .. 0x%x\n.word ", dump_start, dump_end); - for (addr = dump_start; addr < dump_end; addr += BYTES_PER_WORD) - { - int32 code = inst_encode (read_mem_inst (addr)); - (void)fprintf (fp, "0x%x%s", code, addr != (dump_end - BYTES_PER_WORD) ? ", " : ""); - } - (void)fprintf (fp, "\n"); - - /* dump data segment */ - user_kernel_data_segment (false); - if (bare_machine) - { - dump_start = 0; - } - else - { - dump_start = DATA_BOT; - } - dump_end = current_data_pc (); - - if (dump_end > dump_start) - { - (void)fprintf (fp, ".data # 0x%x .. 0x%x\n.word ", dump_start, dump_end); - for (addr = dump_start; addr < dump_end; addr += BYTES_PER_WORD) - { - int32 code = read_mem_word (addr); - (void)fprintf (fp, "0x%x%s", code, addr != (dump_end - BYTES_PER_WORD) ? ", " : ""); - } - (void)fprintf (fp, "\n"); - } - - fclose (fp); - return (false); -} - - - -/* Print an error message. */ - -void -error (char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, stderr); -#else - vfprintf (stderr, fmt, args); -#endif - va_end (args); -} - - -/* Print the error message then exit. */ - -void -fatal_error (char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - fmt = va_arg (args, char *); - -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, stderr); -#else - vfprintf (stderr, fmt, args); -#endif - exit (-1); -} - - -/* Print an error message and return to top level. */ - -void -run_error (char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - - console_to_spim (); - -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, stderr); -#else - vfprintf (stderr, fmt, args); -#endif - va_end (args); - longjmp (spim_top_level_env, 1); -} - - - -/* IO facilities: */ - -void -write_output (port fp, char *fmt, ...) -{ - va_list args; - FILE *f; - int restore_console_to_program = 0; - - va_start (args, fmt); - f = fp.f; - - if (console_state_saved) - { - restore_console_to_program = 1; - console_to_spim (); - } - - if (f != 0) - { -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, f); -#else - vfprintf (f, fmt, args); -#endif - fflush (f); - } - else - { -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, stdout); -#else - vfprintf (stdout, fmt, args); -#endif - fflush (stdout); - } - va_end (args); - - if (restore_console_to_program) - console_to_program (); -} - - -/* Simulate the semantics of fgets (not gets) on Unix file. */ - -void -read_input (char *str, int str_size) -{ - char *ptr; - int restore_console_to_program = 0; - - if (console_state_saved) - { - restore_console_to_program = 1; - console_to_spim (); - } - - ptr = str; - - while (1 < str_size) /* Reserve space for null */ - { - char buf[1]; - if (read ((int) console_in.i, buf, 1) <= 0) /* Not in raw mode! */ - break; - - *ptr ++ = buf[0]; - str_size -= 1; - - if (buf[0] == '\n') - break; - } - - if (0 < str_size) - *ptr = '\0'; /* Null terminate input */ - - if (restore_console_to_program) - console_to_program (); -} - - -/* Give the console to the program for IO. */ - -static void -console_to_program () -{ - if (mapped_io && !console_state_saved) - { -#ifdef NEED_TERMIOS - int flags; - ioctl ((int) console_in.i, TIOCGETP, (char *) &saved_console_state); - flags = saved_console_state.sg_flags; - saved_console_state.sg_flags = (flags | RAW) & ~(CRMOD|ECHO); - ioctl ((int) console_in.i, TIOCSETP, (char *) &saved_console_state); - saved_console_state.sg_flags = flags; -#else - struct termios params; - - tcgetattr (console_in.i, &saved_console_state); - params = saved_console_state; - params.c_iflag &= ~(ISTRIP|INLCR|ICRNL|IGNCR|IXON|IXOFF|INPCK|BRKINT|PARMRK); - - /* Translate CR -> NL to canonicalize input. */ - params.c_iflag |= IGNBRK|IGNPAR|ICRNL; - params.c_oflag = OPOST|ONLCR; - params.c_cflag &= ~PARENB; - params.c_cflag |= CREAD|CS8; - params.c_lflag = 0; - params.c_cc[VMIN] = 1; - params.c_cc[VTIME] = 1; - - tcsetattr (console_in.i, TCSANOW, ¶ms); -#endif - console_state_saved = 1; - } -} - - -/* Return the console to SPIM. */ - -static void -console_to_spim () -{ - if (mapped_io && console_state_saved) -#ifdef NEED_TERMIOS - ioctl ((int) console_in.i, TIOCSETP, (char *) &saved_console_state); -#else - tcsetattr (console_in.i, TCSANOW, &saved_console_state); -#endif - console_state_saved = 0; -} - - -int -console_input_available () -{ - fd_set fdset; - struct timeval timeout; - - if (mapped_io) - { - timeout.tv_sec = 0; - timeout.tv_usec = 0; - FD_ZERO (&fdset); - FD_SET ((int) console_in.i, &fdset); - return (select (sizeof (fdset) * 8, &fdset, NULL, NULL, &timeout)); - } - else - return (0); -} - - -char -get_console_char () -{ - char buf; - - read ((int) console_in.i, &buf, 1); - - if (buf == 3) /* ^C */ - control_c_seen (0); - return (buf); -} - - -void -put_console_char (char c) -{ - putc (c, console_out.f); - fflush (console_out.f); -} - - -static int -read_token () -{ - int token = yylex (); - - if (token == 0) /* End of file */ - { - console_to_spim (); - exit (0); - } - else - { - return (token); - } -} - - -/* - * Writes the contents of the (user and optionally kernel) data segment into data.asm file. - * If data.asm already exists, it's replaced. - */ - -static void -dump_data_seg(bool kernel_also) -{ - static str_stream ss; - ss_clear (&ss); - - if (kernel_also) - { - format_data_segs (&ss); - } - else - { - ss_printf (&ss, "\tDATA\n"); - format_mem (&ss, DATA_BOT, data_top); - } - - FILE *fp; - fp = fopen ("data.asm", "w"); - fprintf (fp, "%s", ss_to_string (&ss)); - fclose (fp); -} - - -/* - * Writes the contents of the (user and optionally kernel) text segment in text.asm file. - * If data.asm already exists, it's replaced. - */ - -static void -dump_text_seg(bool kernel_also) -{ - static str_stream ss; - ss_clear (&ss); - - if (kernel_also) - { - format_insts (&ss, TEXT_BOT, text_top); - ss_printf (&ss, "\n\tKERNEL\n"); - format_insts (&ss, K_TEXT_BOT, k_text_top); - } - else - { - ss_printf (&ss, "\n\tUSER TEXT SEGMENT\n"); - format_insts (&ss, TEXT_BOT, text_top); - } - - FILE *fp; - fp = fopen ("text.asm", "w"); - fprintf (fp, "%s", ss_to_string (&ss)); - fclose (fp); -} diff --git a/spim-qtspimbot/CPU/data.cpp b/spim-qtspimbot/CPU/data.cpp deleted file mode 100755 index 5359e3d..0000000 --- a/spim-qtspimbot/CPU/data.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to manipulate data segment directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser.h" -#include "run.h" -#include "data.h" - - -/* The first 64K of the data segment are dedicated to small data - segment, which is pointed to by $gp. This register points to the - middle of the segment, so we can use the full offset field in an - instruction. */ - -#define DATA_PC (reg_images[current_image].in_kernel ? reg_images[current_image].next_k_data_pc : reg_images[current_image].next_data_pc) - -/* If TO_KERNEL is true, subsequent data will be placed in the - kernel data segment. If false, data will go to the user's data - segment.*/ - -void -user_kernel_data_segment (bool to_kernel) -{ - reg_images[current_image].in_kernel = to_kernel; -} - - -void -end_of_assembly_file () -{ - reg_images[current_image].in_kernel = false; - reg_images[current_image].auto_alignment = true; -} - - -/* Set the point at which the first datum is stored to be ADDRESS + - 64K. The 64K increment allocates an area pointed to by register - $gp, which is initialized. */ - -void -data_begins_at_point (size_t context, mem_addr addr) -{ - if (bare_machine) - reg_images[context].next_data_pc = addr; - else - { - reg_images[context].next_gp_item_addr = addr; - mem_images[context].gp_midpoint = addr + 32*K; - reg_images[context].R[REG_GP] = mem_images[context].gp_midpoint; - reg_images[context].next_data_pc = addr + 64*K; - } -} - - -/* Set the point at which the first datum is stored in the kernel's - data segment. */ - -void -k_data_begins_at_point (size_t context, mem_addr addr) -{ - reg_images[context].next_k_data_pc = addr; -} - - -/* Arrange that the next datum is stored on a memory boundary with its - low ALIGNMENT bits equal to 0. If argument is 0, disable automatic - alignment.*/ - -void -align_data (int alignment) -{ - if (alignment == 0) - reg_images[current_image].auto_alignment = false; - else if (reg_images[current_image].in_kernel) - { - reg_images[current_image].next_k_data_pc = - (reg_images[current_image].next_k_data_pc + (1 << alignment) - 1) & (-1 << alignment); - fix_current_label_address (reg_images[current_image].next_k_data_pc); - } - else - { - reg_images[current_image].next_data_pc = (reg_images[current_image].next_data_pc + (1 << alignment) - 1) & (-1 << alignment); - fix_current_label_address (reg_images[current_image].next_data_pc); - } -} - - -void -set_data_alignment (int alignment) -{ - if (reg_images[current_image].auto_alignment) - align_data (alignment); -} - - -void -enable_data_alignment () -{ - reg_images[current_image].auto_alignment = true; -} - - -/* Set the location (in user or kernel data space) for the next datum. */ - -void -set_data_pc (mem_addr addr) -{ - if (reg_images[current_image].in_kernel) - reg_images[current_image].next_k_data_pc = addr; - else - reg_images[current_image].next_data_pc = addr; -} - - -/* Return the address at which the next datum will be stored. */ - -mem_addr -current_data_pc () -{ - return (DATA_PC); -} - - -/* Bump the address at which the next data will be stored by DELTA - bytes. */ - -void -increment_data_pc (int delta) -{ - if (reg_images[current_image].in_kernel) - { - reg_images[current_image].next_k_data_pc += delta; - if (mem_images[current_image].k_data_top <= reg_images[current_image].next_k_data_pc) - expand_k_data(current_image, ROUND_UP(reg_images[current_image].next_k_data_pc - mem_images[current_image].k_data_top + 1, 64*K)); - } - else - { - reg_images[current_image].next_data_pc += delta; - if (mem_images[current_image].data_top <= reg_images[current_image].next_data_pc) - expand_data(current_image, ROUND_UP(reg_images[current_image].next_data_pc - mem_images[current_image].data_top + 1, 64*K)); - } -} - - -/* Process a .extern NAME SIZE directive. */ - -void -extern_directive (char *name, int size) -{ - label *sym = make_label_global (name); - - if (!bare_machine - && !sym->gp_flag // Not already a global symbol - && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE - && reg_images[current_image].next_gp_item_addr + size < mem_images[current_image].gp_midpoint + 32*K) - { - sym->gp_flag = 1; - sym->addr = reg_images[current_image].next_gp_item_addr; - reg_images[current_image].next_gp_item_addr += size; - } -} - - -/* Process a .lcomm NAME SIZE directive. */ - -void -lcomm_directive (char *name, int size) -{ - if (!bare_machine - && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE - && reg_images[current_image].next_gp_item_addr + size < mem_images[current_image].gp_midpoint + 32*K) - { - label *sym = record_label (name, reg_images[current_image].next_gp_item_addr, 1); - sym->gp_flag = 1; - - reg_images[current_image].next_gp_item_addr += size; - /* Don't need to initialize since memory starts with 0's */ - } - else - { - (void)record_label (name, reg_images[current_image].next_data_pc, 1); - - for ( ; size > 0; size --) - { - store_byte (0); - } - } -} - - -/* Process a .ascii STRING or .asciiz STRING directive. */ - -void -store_string (char *string, int length, bool null_terminate) -{ - for ( ; length > 0; string ++, length --) { - store_byte (*string); - } - if (null_terminate) - { - store_byte (0); - } -} - - -/* Process a .byte EXPR directive. */ - -void -store_byte (int value) -{ - set_mem_byte (current_image, DATA_PC, value); - increment_data_pc (1); -} - - -/* Process a .half EXPR directive. */ - -void -store_half (int value) -{ - if ((DATA_PC & 0x1) != 0) - { -#ifdef SPIM_BIGENDIAN - store_byte ((value >> 8) & 0xff); - store_byte (value & 0xff); -#else - store_byte (value & 0xff); - store_byte ((value >> 8) & 0xff); -#endif - } - else - { - set_mem_half (current_image, DATA_PC, value); - increment_data_pc (BYTES_PER_WORD / 2); - } -} - - -/* Process a .word EXPR directive. */ - -void -store_word (int value) -{ - if ((DATA_PC & 0x3) != 0) - { -#ifdef SPIM_BIGENDIAN - store_half ((value >> 16) & 0xffff); - store_half (value & 0xffff); -#else - store_half (value & 0xffff); - store_half ((value >> 16) & 0xffff); -#endif - } - else - { - set_mem_word (current_image, DATA_PC, value); - increment_data_pc (BYTES_PER_WORD); - } -} - - -/* Process a .double EXPR directive. */ - -void -store_double (double *value) -{ - if ((DATA_PC & 0x7) != 0) - { - store_word (* ((mem_word *) value)); - store_word (* (((mem_word *) value) + 1)); - } - else - { - set_mem_word (current_image, DATA_PC, *((mem_word *) value)); - increment_data_pc (BYTES_PER_WORD); - set_mem_word (current_image, DATA_PC, *(((mem_word *) value) + 1)); - increment_data_pc (BYTES_PER_WORD); - } -} - - -/* Process a .float EXPR directive. */ - -void -store_float (double *value) -{ - float val = (float)*value; - float *vp = &val; - - if ((DATA_PC & 0x3) != 0) - { - store_half (*(mem_word *) vp & 0xffff); - store_half ((*(mem_word *) vp >> 16) & 0xffff); - } - else - { - set_mem_word (current_image, DATA_PC, *((mem_word *) vp)); - increment_data_pc (BYTES_PER_WORD); - } -} diff --git a/spim-qtspimbot/CPU/data.h b/spim-qtspimbot/CPU/data.h deleted file mode 100755 index 0c1ccdc..0000000 --- a/spim-qtspimbot/CPU/data.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to code to manipulate data segment directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -void align_data (int alignment); -mem_addr current_data_pc (); -void data_begins_at_point (size_t context, mem_addr addr); -void enable_data_alignment (); -void end_of_assembly_file (); -void extern_directive (char *name, int size); -void increment_data_pc (int value); -void k_data_begins_at_point (size_t context, mem_addr addr); -void lcomm_directive (char *name, int size); -void set_data_alignment (int); -void set_data_pc (mem_addr addr); -void set_text_pc (mem_addr addr); -void store_byte (int value); -void store_double (double *value); -void store_float (double *value); -void store_half (int value); -void store_string (char *string, int length, bool null_terminate); -void store_word (int value); -void user_kernel_data_segment (bool to_kernel); diff --git a/spim-qtspimbot/CPU/display-utils.cpp b/spim-qtspimbot/CPU/display-utils.cpp deleted file mode 100755 index 6160afe..0000000 --- a/spim-qtspimbot/CPU/display-utils.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* SPIM S20 MIPS simulator. - Utilities for displaying machine contents. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "data.h" -#include "reg.h" -#include "mem.h" -#include "run.h" -#include "sym-tbl.h" - - -char* int_reg_names[32] = - {"r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", - "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", - "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"}; - - -static mem_addr format_partial_line (str_stream *ss, mem_addr addr); - - -/* Write to the stream the contents of the machine's registers, in a wide - variety of formats. */ - -void -format_registers (str_stream *ss, int print_gpr_hex, int print_fpr_hex) -{ - reg_image_t ®_image = reg_images[0]; - - int i; - char *grstr, *fpstr; - char *grfill, *fpfill; - - ss_printf (ss, " PC = %08x ", reg_image.PC); - ss_printf (ss, "EPC = %08x ", CP0_EPC(reg_image)); - ss_printf (ss, " Cause = %08x ", CP0_Cause(reg_image)); - ss_printf (ss, " BadVAddr= %08x\n", CP0_BadVAddr(reg_image)); - ss_printf (ss, " Status = %08x ", CP0_Status(reg_image)); - ss_printf (ss, "HI = %08x ", reg_image.HI); - ss_printf (ss, " LO = %08x\n", reg_image.LO); - - if (print_gpr_hex) - grstr = "R%-2d (%2s) = %08x", grfill = " "; - else - grstr = "R%-2d (%2s) = %-10d", grfill = " "; - - ss_printf (ss, "\t\t\t\t General Registers\n"); - for (i = 0; i < 8; i++) - { - ss_printf (ss, grstr, i, int_reg_names[i], reg_image.R[i]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+8, int_reg_names[i+8], reg_image.R[i+8]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+16, int_reg_names[i+16], reg_image.R[i+16]); - ss_printf (ss, grfill); - ss_printf (ss, grstr, i+24, int_reg_names[i+24], reg_image.R[i+24]); - ss_printf (ss, "\n"); - } - - ss_printf (ss, "\n FIR = %08x ", FIR(reg_image)); - ss_printf (ss, " FCSR = %08x ", FCSR(reg_image)); - ss_printf (ss, " FCCR = %08x ", FCCR(reg_image)); - ss_printf (ss, " FEXR = %08x\n", FEXR(reg_image)); - ss_printf (ss, " FENR = %08x\n", FENR(reg_image)); - - ss_printf (ss, "\t\t\t Double Floating Point Registers\n"); - - if (print_fpr_hex) - fpstr = "FP%-2d=%08x,%08x", fpfill = " "; - else - fpstr = "FP%-2d = %#-13.6g", fpfill = " "; - - if (print_fpr_hex) - for (i = 0; i < 4; i += 1) - { - int *r1, *r2; - - /* Use pointers to cast to ints without invoking float->int conversion - so we can just print the bits. */ - r1 = (int *)®_image.FPR[i]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)®_image.FPR[i+4]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+8, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)®_image.FPR[i+8]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+16, *r1, *r2); - ss_printf (ss, fpfill); - - r1 = (int *)®_image.FPR[i+12]; r2 = r1 + 1; - ss_printf (ss, fpstr, 2*i+24, *r1, *r2); - ss_printf (ss, "\n"); - } - else for (i = 0; i < 4; i += 1) - { - ss_printf (ss, fpstr, 2*i, reg_image.FPR[i]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+8, reg_image.FPR[i+4]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+16, reg_image.FPR[i+8]); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, 2*i+24, reg_image.FPR[i+12]); - ss_printf (ss, "\n"); - } - - if (print_fpr_hex) - fpstr = "FP%-2d=%08x", fpfill = " "; - else - fpstr = "FP%-2d = %#-13.6g", fpfill = " "; - - ss_printf (ss, "\t\t\t Single Floating Point Registers\n"); - - if (print_fpr_hex) - for (i = 0; i < 8; i += 1) - { - /* Use pointers to cast to ints without invoking float->int conversion - so we can just print the bits. */ - ss_printf (ss, fpstr, i, *(int *)&FPR_S(reg_image, i)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+8, *(int *)&FPR_S(reg_image, i+8)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+16, *(int *)&FPR_S(reg_image, i+16)); - ss_printf (ss, fpfill); - - ss_printf (ss, fpstr, i+24, *(int *)&FPR_S(reg_image, i+24)); - ss_printf (ss, "\n"); - } - else for (i = 0; i < 8; i += 1) - { - ss_printf (ss, fpstr, i, FPR_S(reg_image, i)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+8, FPR_S(reg_image, i+8)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+16, FPR_S(reg_image, i+16)); - ss_printf (ss, fpfill); - ss_printf (ss, fpstr, i+24, FPR_S(reg_image, i+24)); - ss_printf (ss, "\n"); - } -} - - - -/* Write to the stream a printable representation of the instructions in - memory addresses: FROM...TO. */ - -void -format_insts (str_stream *ss, mem_addr from, mem_addr to) -{ - instruction *inst; - mem_addr i; - - for (i = from; i < to; i += 4) - { - inst = read_mem_inst (0, i); - if (inst != NULL) - { - format_an_inst (ss, inst, i); - } - } -} - - -/* Write to the stream a printable representation of the data and stack - segments. */ - -void -format_data_segs (str_stream *ss) -{ - reg_image_t ®_image = reg_images[0]; - mem_image_t &mem_image = mem_images[0]; - - ss_printf (ss, "\tDATA\n"); - format_mem (ss, DATA_BOT, mem_image.data_top); - - ss_printf (ss, "\n\tSTACK\n"); - format_mem (ss, ROUND_DOWN (reg_image.R[29], BYTES_PER_WORD), STACK_TOP); - - ss_printf (ss, "\n\tKERNEL DATA\n"); - format_mem (ss, K_DATA_BOT, mem_image.k_data_top); -} - - -#define BYTES_PER_LINE (4*BYTES_PER_WORD) - - -/* Write to the stream a printable representation of the data in memory - address: FROM...TO. */ - -void -format_mem (str_stream *ss, mem_addr from, mem_addr to) -{ - mem_word val; - mem_addr i = ROUND_UP (from, BYTES_PER_WORD); - int j; - - i = format_partial_line (ss, i); - - for ( ; i < to; ) - { - /* Count consecutive zero words */ - for (j = 0; (i + (uint32) j * BYTES_PER_WORD) < to; j += 1) - { - val = read_mem_word (0, i + (uint32) j * BYTES_PER_WORD); - if (val != 0) - { - break; - } - } - - if (j >= 4) - { - /* Block of 4 or more zero memory words: */ - ss_printf (ss, "[0x%08x]...[0x%08x] 0x00000000\n", - i, - i + (uint32) j * BYTES_PER_WORD); - - i = i + (uint32) j * BYTES_PER_WORD; - i = format_partial_line (ss, i); - } - else - { - /* Fewer than 4 zero words, print them on a single line: */ - ss_printf (ss, "[0x%08x] ", i); - do - { - val = read_mem_word (0, i); - ss_printf (ss, " 0x%08x", (unsigned int)val); - i += BYTES_PER_WORD; - } - while (i % BYTES_PER_LINE != 0); - - ss_printf (ss, "\n"); - } - } -} - - -/* Write to the stream a text line containing a fraction of a - quadword. Return the address after the last one written. */ - -static mem_addr -format_partial_line (str_stream *ss, mem_addr addr) -{ - if ((addr % BYTES_PER_LINE) != 0) - { - ss_printf (ss, "[0x%08x] ", addr); - - for (; (addr % BYTES_PER_LINE) != 0; addr += BYTES_PER_WORD) - { - mem_word val = read_mem_word (0, addr); - ss_printf (ss, " 0x%08x", (unsigned int)val); - } - - ss_printf (ss, "\n"); - } - - return addr; -} diff --git a/spim-qtspimbot/CPU/dump_ops.cpp b/spim-qtspimbot/CPU/dump_ops.cpp deleted file mode 100644 index 873acf3..0000000 --- a/spim-qtspimbot/CPU/dump_ops.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* SPIM S20 MIPS simulator. - Dump the op.h file in a readable format to allow checking of encodings. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include - -typedef struct inst_t -{ - char *opcode; - - union - { - unsigned int x; - struct - { - unsigned int funct:6; - unsigned int pad:10; - unsigned int rt:5; - unsigned int rs:5; - unsigned int op:6; - } f; - }; -} inst; - - -#define OP(a, b, c, d) {a, d}, - -inst ops [] = { -#include "op.h" -}; - - -int -compare_ops (inst *p1, inst *p2) -{ - if (p1->f.op < p2->f.op) - return (-1); - else if (p1->f.op > p2->f.op) - return (1); - else - { - if (p1->f.rs < p2->f.rs) - return (-1); - else if (p1->f.rs > p2->f.rs) - return (1); - else - { - if (p1->f.rt < p2->f.rt) - return (-1); - else if (p1->f.rt > p2->f.rt) - return (1); - else - { - if (p1->f.funct < p2->f.funct) - return (-1); - else if (p1->f.funct > p2->f.funct) - return (1); - else - return 0; - } - } - } -} - - -main (int argc, char** argv) -{ - /* Remove pseudo ops (opcode == -1) from table */ - int empty, next; - for (empty = 0, next = 0; next < (sizeof(ops) / sizeof(ops[0])); next += 1) - { - if (-1 == ops[next].x) - { - } - else - { - ops[empty] = ops[next]; - empty += 1; - } - } - - /* Radix sort instructions by field: op, rs, rt, funct */ - qsort (ops, empty, sizeof(ops[0]), compare_ops); - - /* Print related instructions in groups */ - int i; - for (i = 0; i < empty; i += 1) - { - if (0 < i && ops[i - 1].f.op != ops[i].f.op) - printf ("\n"); - - printf ("%10s op=%2d rs=%2d rt=%2d funct=%02x 0x%08x\n", - ops[i].opcode, - ops[i].f.op, - ops[i].f.rs, - ops[i].f.rt, - ops[i].f.funct, - ops[i].x); - } -} diff --git a/spim-qtspimbot/CPU/exceptions.s b/spim-qtspimbot/CPU/exceptions.s deleted file mode 100755 index c88334d..0000000 --- a/spim-qtspimbot/CPU/exceptions.s +++ /dev/null @@ -1,195 +0,0 @@ -# SPIM S20 MIPS simulator. -# The default exception handler for spim. -# -# Copyright (c) 1990-2010, James R. Larus. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, -# are permitted provided that the following conditions are met: -# -# Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation and/or -# other materials provided with the distribution. -# -# Neither the name of the James R. Larus nor the names of its contributors may be -# used to endorse or promote products derived from this software without specific -# prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -# Define the exception handling code. This must go first! - - .kdata -__m1_: .asciiz " Exception " -__m2_: .asciiz " occurred and ignored\n" -__e0_: .asciiz " [Interrupt] " -__e1_: .asciiz " [TLB]" -__e2_: .asciiz " [TLB]" -__e3_: .asciiz " [TLB]" -__e4_: .asciiz " [Address error in inst/data fetch] " -__e5_: .asciiz " [Address error in store] " -__e6_: .asciiz " [Bad instruction address] " -__e7_: .asciiz " [Bad data address] " -__e8_: .asciiz " [Error in syscall] " -__e9_: .asciiz " [Breakpoint] " -__e10_: .asciiz " [Reserved instruction] " -__e11_: .asciiz "" -__e12_: .asciiz " [Arithmetic overflow] " -__e13_: .asciiz " [Trap] " -__e14_: .asciiz "" -__e15_: .asciiz " [Floating point] " -__e16_: .asciiz "" -__e17_: .asciiz "" -__e18_: .asciiz " [Coproc 2]" -__e19_: .asciiz "" -__e20_: .asciiz "" -__e21_: .asciiz "" -__e22_: .asciiz " [MDMX]" -__e23_: .asciiz " [Watch]" -__e24_: .asciiz " [Machine check]" -__e25_: .asciiz "" -__e26_: .asciiz "" -__e27_: .asciiz "" -__e28_: .asciiz "" -__e29_: .asciiz "" -__e30_: .asciiz " [Cache]" -__e31_: .asciiz "" -__excp: .word __e0_, __e1_, __e2_, __e3_, __e4_, __e5_, __e6_, __e7_, __e8_, __e9_ - .word __e10_, __e11_, __e12_, __e13_, __e14_, __e15_, __e16_, __e17_, __e18_, - .word __e19_, __e20_, __e21_, __e22_, __e23_, __e24_, __e25_, __e26_, __e27_, - .word __e28_, __e29_, __e30_, __e31_ -s1: .word 0 -s2: .word 0 - -# This is the exception handler code that the processor runs when -# an exception occurs. It only prints some information about the -# exception, but can server as a model of how to write a handler. -# -# Because we are running in the kernel, we can use $k0/$k1 without -# saving their old values. - -# This is the exception vector address for MIPS-1 (R2000): -# .ktext 0x80000080 -# This is the exception vector address for MIPS32: - .ktext 0x80000180 -# Select the appropriate one for the mode in which SPIM is compiled. - .set noat - move $k1 $at # Save $at - .set at - sw $v0 s1 # Not re-entrant and we can't trust $sp - sw $a0 s2 # But we need to use these registers - - mfc0 $k0 $13 # Cause register - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - - # Print information about exception. - # - li $v0 4 # syscall 4 (print_str) - la $a0 __m1_ - syscall - - li $v0 1 # syscall 1 (print_int) - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - syscall - - li $v0 4 # syscall 4 (print_str) - andi $a0 $k0 0x3c - lw $a0 __excp($a0) - nop - syscall - - bne $k0 0x18 ok_pc # Bad PC exception requires special checks - nop - - mfc0 $a0 $14 # EPC - andi $a0 $a0 0x3 # Is EPC word-aligned? - beq $a0 0 ok_pc - nop - - li $v0 10 # Exit on really bad PC - syscall - -ok_pc: - li $v0 4 # syscall 4 (print_str) - la $a0 __m2_ - syscall - - srl $a0 $k0 2 # Extract ExcCode Field - andi $a0 $a0 0x1f - bne $a0 0 ret # 0 means exception was an interrupt - nop - -# Interrupt-specific code goes here! -# Don't skip instruction at EPC since it has not executed. - - -ret: -# Return from (non-interrupt) exception. Skip offending instruction -# at EPC to avoid infinite loop. -# - mfc0 $k0 $14 # Bump EPC register - addiu $k0 $k0 4 # Skip faulting instruction - # (Need to handle delayed branch case here) - mtc0 $k0 $14 - - -# Restore registers and reset procesor state -# - lw $v0 s1 # Restore other registers - lw $a0 s2 - - .set noat - move $at $k1 # Restore $at - .set at - - mtc0 $0 $13 # Clear Cause register - - mfc0 $k0 $12 # Set Status register - ori $k0 0x1 # Interrupts enabled - mtc0 $k0 $12 - -# Return from exception on MIPS32: - eret - -# Return sequence for MIPS-I (R2000): -# rfe # Return from exception handler - # Should be in jr's delay slot -# jr $k0 -# nop - - - -# Standard startup code. Invoke the routine "main" with arguments: -# main(argc, argv, envp) -# - .text - .globl __start -__start: - lw $a0 0($sp) # argc - addiu $a1 $sp 4 # argv - addiu $a2 $a1 4 # envp - sll $v0 $a0 2 - addu $a2 $a2 $v0 - jal main - nop - - li $v0 10 - syscall # syscall 10 (exit) - - .globl __eoth -__eoth: diff --git a/spim-qtspimbot/CPU/inst.cpp b/spim-qtspimbot/CPU/inst.cpp deleted file mode 100755 index df97aaa..0000000 --- a/spim-qtspimbot/CPU/inst.cpp +++ /dev/null @@ -1,1606 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to build assembly instructions and resolve symbolic labels. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser.h" -#include "scanner.h" -#include "parser_yacc.h" -#include "data.h" - - -/* Local functions: */ - -static int compare_pair_value (name_val_val *p1, name_val_val *p2); -static void format_imm_expr (str_stream *ss, imm_expr *expr, int base_reg); -static void i_type_inst_full_word (int opcode, int rt, int rs, imm_expr *expr, - int value_known, int32 value); -static void inst_cmp (instruction *inst1, instruction *inst2); -static instruction *make_r_type_inst (int opcode, int rd, int rs, int rt); -static instruction *mk_i_inst (int32 value, int opcode, int rs, int rt, int offset); -static instruction *mk_j_inst (int32, int opcode, int target); -static instruction *mk_r_inst (int32, int opcode, int rs, int rt, int rd, int shamt); -static void produce_immediate (imm_expr *expr, int rt, int value_known, int32 value); -static void sort_a_opcode_table (); -static void sort_i_opcode_table (); -static void sort_name_table (); - - -/* Instruction used as breakpoint by SPIM: */ - -static instruction *break_inst = NULL; - - -#define INST_PC (reg_images[current_image].in_kernel ? reg_images[current_image].next_k_text_pc : reg_images[current_image].next_text_pc) - - - -/* Set ADDRESS at which the next instruction is stored. */ - -void -text_begins_at_point (size_t context, mem_addr addr) -{ - reg_images[context].next_text_pc = addr; -} - - -void -k_text_begins_at_point (size_t context, mem_addr addr) -{ - reg_images[context].next_k_text_pc = addr; -} - - -/* Set the location (in user or kernel text space) for the next instruction. */ - -void -set_text_pc (mem_addr addr) -{ - if (reg_images[current_image].in_kernel) - reg_images[current_image].next_k_text_pc = addr; - else - reg_images[current_image].next_text_pc = addr; -} - - -/* Return address for next instruction, in appropriate text segment. */ - -mem_addr -current_text_pc () -{ - return (INST_PC); -} - - -/* Increment the current text segement PC. */ - -void -increment_text_pc (int delta) -{ - if (reg_images[current_image].in_kernel) - { - reg_images[current_image].next_k_text_pc += delta; - if (mem_images[current_image].k_text_top <= reg_images[current_image].next_k_text_pc) - run_error("Can't expand kernel text segment\n"); - } - else - { - reg_images[current_image].next_text_pc += delta; - if (mem_images[current_image].text_top <= reg_images[current_image].next_text_pc) - run_error("Can't expand text segment\n"); - } -} - - -/* If FLAG is true, next instruction goes to kernel text segment, - otherwise it goes to user segment. */ - -void -user_kernel_text_segment (bool to_kernel) -{ - reg_images[current_image].in_kernel = to_kernel; -} - - -/* Store an INSTRUCTION in memory at the next location. */ - -void -store_instruction (instruction *inst) -{ - if (data_dir) - { - store_word (inst_encode (inst)); - free_inst (inst); - } - else if (text_dir) - { - reg_images[current_image].exception_occurred = 0; - set_mem_inst (current_image, INST_PC, inst); - if (reg_images[current_image].exception_occurred) - error ("Invalid address (0x%08x) for instruction\n", INST_PC); - else - increment_text_pc (BYTES_PER_WORD); - if (inst != NULL) - { - SET_SOURCE (inst, source_line ()); - if (ENCODING (inst) == 0) - SET_ENCODING (inst, inst_encode (inst)); - } - } -} - - - -void -i_type_inst_free (int opcode, int rt, int rs, imm_expr *expr) -{ - i_type_inst (opcode, rt, rs, expr); - free (expr); -} - - -/* Produce an immediate instruction with the OPCODE, RT, RS, and IMM - fields. NB, because the immediate value may not fit in the field, - this routine may produce more than one instruction. On the bare - machine, we resolve symbolic address, but they better produce values - that fit into instruction's immediate field. */ - -void -i_type_inst (int opcode, int rt, int rs, imm_expr *expr) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_EXPR (inst, copy_imm_expr (expr)); - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* Evaluate the instruction's expression. */ - int32 value = eval_imm_expr (expr); - - if (!bare_machine - && (((opcode == Y_ADDI_OP - || opcode == Y_ADDIU_OP - || opcode == Y_SLTI_OP - || opcode == Y_SLTIU_OP - || opcode == Y_TEQI_OP - || opcode == Y_TGEI_OP - || opcode == Y_TGEIU_OP - || opcode == Y_TLTI_OP - || opcode == Y_TLTIU_OP - || opcode == Y_TNEI_OP - || (opcode_is_load_store (opcode) && expr->bits == 0)) - // Sign-extended immediate values: - ? ((value & 0xffff8000) != 0 && (value & 0xffff8000) != 0xffff8000) - // Not sign-extended: - : (value & 0xffff0000) != 0))) - { - // Non-immediate value - free_inst (inst); - i_type_inst_full_word (opcode, rt, rs, expr, 1, value); - return; - } - else - resolve_a_label (expr->symbol, inst); - } - else if (bare_machine || expr->bits != 0) - /* Don't know expression's value, but only needed upper/lower 16-bits - anyways. */ - record_inst_uses_symbol (inst, expr->symbol); - else - { - /* Don't know the expressions's value and want all of its bits, - so assume that it will not produce a small result and generate - sequence for 32 bit value. */ - free_inst (inst); - - i_type_inst_full_word (opcode, rt, rs, expr, 0, 0); - return; - } - - store_instruction (inst); -} - - -/* The immediate value for an instruction will (or may) not fit in 16 bits. - Build the value from its piece with separate instructions. */ - -static void -i_type_inst_full_word (int opcode, int rt, int rs, imm_expr *expr, - int value_known, int32 value) -{ - if (opcode_is_load_store (opcode)) - { - int32 offset; - - if (expr->symbol != NULL - && expr->symbol->gp_flag - && rs == 0 - && (int32)IMM_MIN <= (offset = expr->symbol->addr + expr->offset) - && offset <= (int32)IMM_MAX) - { - i_type_inst_free (opcode, rt, REG_GP, make_imm_expr (offset, NULL, false)); - } - else if (value_known) - { - int low, high; - - high = (value >> 16) & 0xffff; - low = value & 0xffff; - - if (!(high == 0 && !(low & 0x8000)) && - !(high == 0xffff && (low & 0x8000))) - { - /* Some of high 16 bits are non-zero */ - if (low & 0x8000) - { - /* Adjust high 16, since load sign-extends low 16*/ - high += 1; - } - - i_type_inst_free (Y_LUI_OP, 1, 0, const_imm_expr (high)); - if (rs != 0) /* Base register */ - { - r_type_inst (Y_ADDU_OP, 1, 1, rs); - } - i_type_inst_free (opcode, rt, 1, lower_bits_of_expr (const_imm_expr (low))); - } - else - { - /* Special case, sign-extension of low 16 bits sets high to 0xffff */ - i_type_inst_free (opcode, rt, rs, const_imm_expr (low)); - } - } - else - { - /* Use $at */ - /* Need to adjust if lower bits are negative */ - i_type_inst_free (Y_LUI_OP, 1, 0, upper_bits_of_expr (expr)); - if (rs != 0) /* Base register */ - { - r_type_inst (Y_ADDU_OP, 1, 1, rs); - } - i_type_inst_free (opcode, rt, 1, lower_bits_of_expr (expr)); - } - } - else if (opcode_is_branch (opcode)) - { - /* This only allows branches +/- 32K, which is not correct! */ - i_type_inst_free (opcode, rt, rs, lower_bits_of_expr (expr)); - } - else - /* Computation instruction */ - { - int offset; - - if (expr->symbol != NULL - && expr->symbol->gp_flag && rs == 0 - && (int32)IMM_MIN <= (offset = expr->symbol->addr + expr->offset) - && offset <= (int32)IMM_MAX) - { - i_type_inst_free ((opcode == Y_LUI_OP ? Y_ADDIU_OP : opcode), - rt, REG_GP, make_imm_expr (offset, NULL, false)); - } - else - { - /* Use $at */ - if ((opcode == Y_ORI_OP - || opcode == Y_ADDI_OP - || opcode == Y_ADDIU_OP - || opcode == Y_LUI_OP) - && rs == 0) - { - produce_immediate(expr, rt, value_known, value); - } - else - { - produce_immediate(expr, 1, value_known, value); - r_type_inst (imm_op_to_op (opcode), rt, rs, 1); - } - } - } -} - - -static void -produce_immediate (imm_expr *expr, int rt, int value_known, int32 value) -{ - if (value_known && (value & 0xffff) == 0) - { - i_type_inst_free (Y_LUI_OP, rt, 0, upper_bits_of_expr (expr)); - } - else if (value_known && (value & 0xffff0000) == 0) - { - i_type_inst_free (Y_ORI_OP, rt, 0, lower_bits_of_expr (expr)); - } - else - { - i_type_inst_free (Y_LUI_OP, 1, 0, upper_bits_of_expr (expr)); - i_type_inst_free (Y_ORI_OP, rt, 1, lower_bits_of_expr(expr)); - } -} - - -/* Return a jump-type instruction with the given OPCODE and TARGET - fields. NB, even the immediate value may not fit in the field, this - routine will not produce more than one instruction. */ - -void -j_type_inst (int opcode, imm_expr *target) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE(inst, opcode); - target->offset = 0; /* Not PC relative */ - target->pc_relative = false; - SET_EXPR (inst, copy_imm_expr (target)); - if (target->symbol == NULL || SYMBOL_IS_DEFINED (target->symbol)) - resolve_a_label (target->symbol, inst); - else - record_inst_uses_symbol (inst, target->symbol); - store_instruction (inst); -} - - -/* Return a register-type instruction with the given OPCODE, RD, RS, and RT - fields. */ - -static instruction * -make_r_type_inst (int opcode, int rd, int rs, int rt) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE(inst, opcode); - SET_RS(inst, rs); - SET_RT(inst, rt); - SET_RD(inst, rd); - SHAMT(inst) = 0; - return (inst); -} - - -/* Return a register-type instruction with the given OPCODE, RD, RS, and RT - fields. */ - -void -r_type_inst (int opcode, int rd, int rs, int rt) -{ - store_instruction (make_r_type_inst (opcode, rd, rs, rt)); -} - - -/* Return a register-type instruction with the given OPCODE, FD, FS, and FT - fields. */ - -void -r_co_type_inst (int opcode, int fd, int fs, int ft) -{ - instruction *inst = make_r_type_inst (opcode, fs, 0, ft); - SET_FD (inst, fd); - store_instruction (inst); -} - - -/* Return a register-shift instruction with the given OPCODE, RD, RT, and - SHAMT fields.*/ - -void -r_sh_type_inst (int opcode, int rd, int rt, int shamt) -{ - instruction *inst = make_r_type_inst (opcode, rd, 0, rt); - SET_SHAMT(inst, shamt & 0x1f); - store_instruction (inst); -} - - -/* Return a floating-point compare instruction with the given OPCODE, - FS, FT, and CC fields.*/ - -void -r_cond_type_inst (int opcode, int fs, int ft, int cc) -{ - instruction *inst = make_r_type_inst (opcode, fs, 0, ft); - SET_FD(inst, cc << 2); - switch (opcode) - { - case Y_C_EQ_D_OP: - case Y_C_EQ_S_OP: - { - SET_COND(inst, COND_EQ); - break; - } - - case Y_C_LE_D_OP: - case Y_C_LE_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_EQ); - break; - } - - case Y_C_LT_D_OP: - case Y_C_LT_S_OP: - { - SET_COND(inst, COND_IN | COND_LT); - break; - } - - case Y_C_NGE_D_OP: - case Y_C_NGE_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_UN); - break; - } - - case Y_C_NGLE_D_OP: - case Y_C_NGLE_S_OP: - { - SET_COND(inst, COND_IN | COND_UN); - break; - } - - case Y_C_NGL_D_OP: - case Y_C_NGL_S_OP: - { - SET_COND(inst, COND_IN | COND_EQ | COND_UN); - break; - } - - case Y_C_NGT_D_OP: - case Y_C_NGT_S_OP: - { - SET_COND(inst, COND_IN | COND_LT | COND_EQ | COND_UN); - break; - } - - case Y_C_OLT_D_OP: - case Y_C_OLT_S_OP: - { - SET_COND(inst, COND_LT); - break; - } - - case Y_C_OLE_D_OP: - case Y_C_OLE_S_OP: - { - SET_COND(inst, COND_LT | COND_EQ); - break; - } - - case Y_C_SEQ_D_OP: - case Y_C_SEQ_S_OP: - { - SET_COND(inst, COND_IN | COND_EQ); - break; - } - - case Y_C_SF_D_OP: - case Y_C_SF_S_OP: - { - SET_COND(inst, COND_IN); - break; - } - - case Y_C_F_D_OP: - case Y_C_F_S_OP: - { - SET_COND(inst, 0); - break; - } - - case Y_C_UEQ_D_OP: - case Y_C_UEQ_S_OP: - { - SET_COND(inst, COND_EQ | COND_UN); - break; - } - - case Y_C_ULT_D_OP: - case Y_C_ULT_S_OP: - { - SET_COND(inst, COND_LT | COND_UN); - break; - } - - case Y_C_ULE_D_OP: - case Y_C_ULE_S_OP: - { - SET_COND(inst, COND_LT | COND_EQ | COND_UN); - break; - } - - case Y_C_UN_D_OP: - case Y_C_UN_S_OP: - { - SET_COND(inst, COND_UN); - break; - } - } - store_instruction (inst); -} - - -/* Make and return a deep copy of INST. */ - -instruction * -copy_inst (instruction *inst) -{ - instruction *new_inst = (instruction *) xmalloc (sizeof (instruction)); - - *new_inst = *inst; - /*memcpy ((void*)new_inst, (void*)inst , sizeof (instruction));*/ - SET_EXPR (new_inst, copy_imm_expr (EXPR (inst))); - return (new_inst); -} - - -void -free_inst (instruction *inst) -{ - if (inst != break_inst) - /* Don't free the breakpoint insructions since we only have one. */ - { - if (EXPR (inst)) - free (EXPR (inst)); - free (inst); - } -} - - - -/* Maintain a table mapping from opcode to instruction name and - instruction type. - - Table must be sorted before first use since its entries are - alphabetical on name, not ordered by opcode. */ - - -/* Sort all instruction table before first use. */ - -void -initialize_inst_tables () -{ - sort_name_table (); - sort_i_opcode_table (); - sort_a_opcode_table (); -} - - -/* Map from opcode -> name/type. */ - -static name_val_val name_tbl [] = { -#undef OP -#define OP(NAME, OPCODE, TYPE, R_OPCODE) {NAME, OPCODE, TYPE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the opcode value). */ - -static void -sort_name_table () -{ - qsort (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - -/* Compare the VALUE1 field of two NAME_VAL_VAL entries in the format - required by qsort. */ - -static int -compare_pair_value (name_val_val *p1, name_val_val *p2) -{ - if (p1->value1 < p2->value1) - return (-1); - else if (p1->value1 > p2->value1) - return (1); - else - return (0); -} - - -/* Print the instruction stored at the memory ADDRESS. */ - -void -print_inst (mem_addr addr) -{ - char* inst_str = inst_to_string (addr); - write_output (message_out, inst_str); - free (inst_str); -} - - -char* -inst_to_string(mem_addr addr) -{ - reg_image_t ®_image = reg_images[0]; - - str_stream ss; - instruction *inst; - - reg_image.exception_occurred = 0; - inst = read_mem_inst (0, addr); - - if (reg_image.exception_occurred) - { - error ("Can't print instruction not in text segment (0x%08x)\n", addr); - return ""; - } - - ss_init (&ss); - format_an_inst (&ss, inst, addr); - return ss_to_string (&ss); -} - - -void -format_an_inst (str_stream *ss, instruction *inst, mem_addr addr) -{ - name_val_val *entry; - int line_start = ss_length (ss); - - if (inst_is_breakpoint (addr)) - { - delete_breakpoint (addr); - ss_printf (ss, "*"); - format_an_inst (ss, read_mem_inst (0, addr), addr); - add_breakpoint (addr); - return; - } - - ss_printf (ss, "[0x%08x]\t", addr); - if (inst == NULL) - { - ss_printf (ss, "\n"); - return; - } - - entry = map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - OPCODE (inst)); - if (entry == NULL) - { - ss_printf (ss, "\n", OPCODE (inst)); - return; - } - - ss_printf (ss, "0x%08x %s", (uint32)ENCODING (inst), entry->name); - switch (entry->value2) - { - case BC_TYPE_INST: - ss_printf (ss, "%d %d", CC (inst), IDISP (inst)); - break; - - case B1_TYPE_INST: - ss_printf (ss, " $%d %d", RS (inst), IDISP (inst)); - break; - - case I1s_TYPE_INST: - ss_printf (ss, " $%d, %d", RS (inst), IMM (inst)); - break; - - case I1t_TYPE_INST: - ss_printf (ss, " $%d, %d", RT (inst), IMM (inst)); - break; - - case I2_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RT (inst), RS (inst), IMM (inst)); - break; - - case B2_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RS (inst), RT (inst), IDISP (inst)); - break; - - case I2a_TYPE_INST: - ss_printf (ss, " $%d, %d($%d)", RT (inst), IMM (inst), BASE (inst)); - break; - - case R1s_TYPE_INST: - ss_printf (ss, " $%d", RS (inst)); - break; - - case R1d_TYPE_INST: - ss_printf (ss, " $%d", RD (inst)); - break; - - case R2td_TYPE_INST: - ss_printf (ss, " $%d, $%d", RT (inst), RD (inst)); - break; - - case R2st_TYPE_INST: - ss_printf (ss, " $%d, $%d", RS (inst), RT (inst)); - break; - - case R2ds_TYPE_INST: - ss_printf (ss, " $%d, $%d", RD (inst), RS (inst)); - break; - - case R2sh_TYPE_INST: - if (ENCODING (inst) == 0) - { - ss_erase (ss, 3); /* zap sll */ - ss_printf (ss, "nop"); - } - else - ss_printf (ss, " $%d, $%d, %d", RD (inst), RT (inst), SHAMT (inst)); - break; - - case R3_TYPE_INST: - ss_printf (ss, " $%d, $%d, $%d", RD (inst), RS (inst), RT (inst)); - break; - - case R3sh_TYPE_INST: - ss_printf (ss, " $%d, $%d, $%d", RD (inst), RT (inst), RS (inst)); - break; - - case FP_I2a_TYPE_INST: - ss_printf (ss, " $f%d, %d($%d)", FT (inst), IMM (inst), BASE (inst)); - break; - - case FP_R2ds_TYPE_INST: - ss_printf (ss, " $f%d, $f%d", FD (inst), FS (inst)); - break; - - case FP_R2ts_TYPE_INST: - ss_printf (ss, " $%d, $f%d", RT (inst), FS (inst)); - break; - - case FP_CMP_TYPE_INST: - if (FD (inst) == 0) - ss_printf (ss, " $f%d, $f%d", FS (inst), FT (inst)); - else - ss_printf (ss, " %d, $f%d, $f%d", FD (inst) >> 2, FS (inst), FT (inst)); - break; - - case FP_R3_TYPE_INST: - ss_printf (ss, " $f%d, $f%d, $f%d", FD (inst), FS (inst), FT (inst)); - break; - - case MOVC_TYPE_INST: - ss_printf (ss, " $%d, $%d, %d", RD (inst), RS (inst), RT (inst) >> 2); - break; - - case FP_MOVC_TYPE_INST: - ss_printf (ss, " $f%d, $f%d, %d", FD (inst), FS (inst), CC (inst)); - break; - - case J_TYPE_INST: - ss_printf (ss, " 0x%08x", TARGET (inst) << 2); - break; - - case NOARG_TYPE_INST: - break; - - default: - fatal_error ("Unknown instruction type in print_inst\n"); - } - - if (EXPR (inst) != NULL && EXPR (inst)->symbol != NULL) - { - ss_printf (ss, " ["); - if (opcode_is_load_store (OPCODE (inst))) - format_imm_expr (ss, EXPR (inst), BASE (inst)); - else - format_imm_expr (ss, EXPR (inst), -1); - ss_printf (ss, "]"); - } - - if (SOURCE (inst) != NULL) - { - /* Comment is source line text of current line. */ - int gap_length = 57 - (ss_length (ss) - line_start); - for ( ; 0 < gap_length; gap_length -= 1) - { - ss_printf (ss, " "); - } - - ss_printf (ss, "; "); - ss_printf (ss, "%s", SOURCE (inst)); - } - - ss_printf (ss, "\n"); -} - - - -/* Return true if SPIM OPCODE (e.g. Y_...) represents a conditional - branch. */ - -bool -opcode_is_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1F_OP: - case Y_BC1FL_OP: - case Y_BC1T_OP: - case Y_BC1TL_OP: - case Y_BC2F_OP: - case Y_BC2FL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - case Y_BEQ_OP: - case Y_BEQL_OP: - case Y_BEQZ_POP: - case Y_BGE_POP: - case Y_BGEU_POP: - case Y_BGEZ_OP: - case Y_BGEZAL_OP: - case Y_BGEZALL_OP: - case Y_BGEZL_OP: - case Y_BGT_POP: - case Y_BGTU_POP: - case Y_BGTZ_OP: - case Y_BGTZL_OP: - case Y_BLE_POP: - case Y_BLEU_POP: - case Y_BLEZ_OP: - case Y_BLEZL_OP: - case Y_BLT_POP: - case Y_BLTU_POP: - case Y_BLTZ_OP: - case Y_BLTZAL_OP: - case Y_BLTZALL_OP: - case Y_BLTZL_OP: - case Y_BNE_OP: - case Y_BNEL_OP: - case Y_BNEZ_POP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE represents a nullified (e.g., Y_...L_OP) - conditional branch. */ - -bool -opcode_is_nullified_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1FL_OP: - case Y_BC1TL_OP: - case Y_BC2FL_OP: - case Y_BC2TL_OP: - case Y_BEQL_OP: - case Y_BGEZALL_OP: - case Y_BGEZL_OP: - case Y_BGTZL_OP: - case Y_BLEZL_OP: - case Y_BLTZALL_OP: - case Y_BLTZL_OP: - case Y_BNEL_OP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE (e.g. Y_...) represents a conditional - branch on a true condition. */ - -bool -opcode_is_true_branch (int opcode) -{ - switch (opcode) - { - case Y_BC1T_OP: - case Y_BC1TL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - return true; - - default: - return false; - } -} - - -/* Return true if SPIM OPCODE (e.g. Y_...) is a direct unconditional - branch (jump). */ - -bool -opcode_is_jump (int opcode) -{ - switch (opcode) - { - case Y_J_OP: - case Y_JAL_OP: - return true; - - default: - return false; - } -} - -/* Return true if SPIM OPCODE (e.g. Y_...) is a load or store. */ - -bool -opcode_is_load_store (int opcode) -{ - switch (opcode) - { - case Y_LB_OP: - case Y_LBU_OP: - case Y_LH_OP: - case Y_LHU_OP: - case Y_LL_OP: - case Y_LDC1_OP: - case Y_LDC2_OP: - case Y_LW_OP: - case Y_LWC1_OP: - case Y_LWC2_OP: - case Y_LWL_OP: - case Y_LWR_OP: - case Y_SB_OP: - case Y_SC_OP: - case Y_SH_OP: - case Y_SDC1_OP: - case Y_SDC2_OP: - case Y_SW_OP: - case Y_SWC1_OP: - case Y_SWC2_OP: - case Y_SWL_OP: - case Y_SWR_OP: - return true; - - default: - return false; - } -} - - -/* Return true if a breakpoint is set at ADDR. */ - -bool -inst_is_breakpoint (mem_addr addr) -{ - bkpt *trav = bkpts; - while (trav != NULL) { - if (trav->addr == addr) { - return 1; - } - trav = trav->next; - } - return false; -} - - -/* An immediate expression has the form: SYMBOL +/- IOFFSET, where either - part may be omitted. */ - -/* Make and return a new immediate expression */ - -imm_expr * -make_imm_expr (int offs, char *sym, bool is_pc_relative) -{ - imm_expr *expr = (imm_expr *) xmalloc (sizeof (imm_expr)); - - expr->offset = offs; - expr->bits = 0; - expr->pc_relative = is_pc_relative; - if (sym != NULL) - expr->symbol = lookup_label (sym); - else - expr->symbol = NULL; - return (expr); -} - - -/* Return a shallow copy of the EXPRESSION. */ - -imm_expr * -copy_imm_expr (imm_expr *old_expr) -{ - imm_expr *expr = (imm_expr *) xmalloc (sizeof (imm_expr)); - - *expr = *old_expr; - /*memcpy ((void*)expr, (void*)old_expr, sizeof (imm_expr));*/ - return (expr); -} - - -/* Return a shallow copy of an EXPRESSION that only uses the upper - sixteen bits of the expression's value. */ - -imm_expr * -upper_bits_of_expr (imm_expr *old_expr) -{ - imm_expr *expr = copy_imm_expr (old_expr); - - expr->bits = 1; - return (expr); -} - - -/* Return a shallow copy of the EXPRESSION that only uses the lower - sixteen bits of the expression's value. */ - -imm_expr * -lower_bits_of_expr (imm_expr *old_expr) -{ - imm_expr *expr = copy_imm_expr (old_expr); - - expr->bits = -1; - return (expr); -} - - -/* Return an instruction expression for a constant VALUE. */ - -imm_expr * -const_imm_expr (int32 value) -{ - return (make_imm_expr (value, NULL, false)); -} - - -/* Return a shallow copy of the EXPRESSION with the offset field - incremented by the given amount. */ - -imm_expr * -incr_expr_offset (imm_expr *expr, int32 value) -{ - imm_expr *new_expr = copy_imm_expr (expr); - - new_expr->offset += value; - return (new_expr); -} - - -/* Return the value of the EXPRESSION. */ - -int32 -eval_imm_expr (imm_expr *expr) -{ - int32 value; - - if (expr->symbol == NULL) - value = expr->offset; - else if (SYMBOL_IS_DEFINED (expr->symbol)) - { - value = expr->offset + expr->symbol->addr; - } - else - { - error ("Evaluated undefined symbol: %s\n", expr->symbol->name); - value = 0; - } - if (expr->bits > 0) - return ((value >> 16) & 0xffff); /* Use upper bits of result */ - else if (expr->bits < 0) - return (value & 0xffff); /* Use lower bits */ - else - return (value); -} - - -/* Print the EXPRESSION. */ - -static void -format_imm_expr (str_stream *ss, imm_expr *expr, int base_reg) -{ - if (expr->symbol != NULL) - { - ss_printf (ss, "%s", expr->symbol->name); - } - - if (expr->pc_relative) - ss_printf (ss, "-0x%08x", (unsigned int)-expr->offset); - else if (expr->offset < -10) - ss_printf (ss, "-%d (-0x%08x)", -expr->offset, (unsigned int)-expr->offset); - else if (expr->offset > 10) - ss_printf (ss, "+%d (0x%08x)", expr->offset, (unsigned int)expr->offset); - - if (base_reg != -1 && expr->symbol != NULL && - (expr->offset > 10 || expr->offset < -10)) - { - if (expr->offset == 0 && base_reg != 0) - ss_printf (ss, "+0"); - - if (expr->offset != 0 || base_reg != 0) - ss_printf (ss, "($%d)", base_reg); - } -} - - -/* Return true if the EXPRESSION is a constant 0. */ - -bool -is_zero_imm (imm_expr *expr) -{ - return (expr->offset == 0 && expr->symbol == NULL); -} - - - -/* Return an address expression of the form SYMBOL +/- IOFFSET (REGISTER). - Any of the three parts may be omitted. */ - -addr_expr * -make_addr_expr (int offs, char *sym, int reg_no) -{ - addr_expr *expr = (addr_expr *) xmalloc (sizeof (addr_expr)); - label *lab; - - if (reg_no == 0 && sym != NULL && (lab = lookup_label (sym))->gp_flag) - { - expr->reg_no = REG_GP; - expr->imm = make_imm_expr (offs + lab->addr - mem_images[current_image].gp_midpoint, NULL, false); - } - else - { - expr->reg_no = (unsigned char)reg_no; - expr->imm = make_imm_expr (offs, (sym ? str_copy (sym) : sym), false); - } - return (expr); -} - - -imm_expr * -addr_expr_imm (addr_expr *expr) -{ - return (expr->imm); -} - - -int -addr_expr_reg (addr_expr *expr) -{ - return (expr->reg_no); -} - - - -/* Map between a SPIM instruction and the binary representation of the - instruction. */ - - -/* Maintain a table mapping from internal opcode (i_opcode) to actual - opcode (a_opcode). Table must be sorted before first use since its - entries are alphabetical on name, not ordered by opcode. */ - - -/* Map from internal opcode -> real opcode */ - -static name_val_val i_opcode_tbl [] = { -#undef OP -#define OP(NAME, I_OPCODE, TYPE, A_OPCODE) {NAME, I_OPCODE, (int)A_OPCODE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the interal opcode value). */ - -static void -sort_i_opcode_table () -{ - qsort (i_opcode_tbl, - sizeof (i_opcode_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - -#define REGS(R,O) (((R) & 0x1f) << O) - - -int32 -inst_encode (instruction *inst, bool correct_branches) -{ - int32 a_opcode = 0; - name_val_val *entry; - - if (inst == NULL) - return (0); - - entry = map_int_to_name_val_val (i_opcode_tbl, - sizeof (i_opcode_tbl) / sizeof (name_val_val), - OPCODE (inst)); - if (entry == NULL) - return 0; - - a_opcode = entry->value2; - entry = map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - OPCODE (inst)); - - switch (entry->value2) - { - case BC_TYPE_INST: - return (a_opcode - | REGS (CC (inst) << 2, 16) - | ((IOFFSET (inst) - correct_branches) & 0xffff)); - - case B1_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | ((IOFFSET (inst) - correct_branches) & 0xffff)); - - case I1s_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | (IMM (inst) & 0xffff)); - - case I1t_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | (IMM (inst) & 0xffff)); - - case I2_TYPE_INST: - case B2_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | ((IOFFSET (inst) - correct_branches) & 0xffff)); - - case I2a_TYPE_INST: - return (a_opcode - | REGS (BASE (inst), 21) - | REGS (RT (inst), 16) - | (IOFFSET (inst) & 0xffff)); - - case R1s_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21)); - - case R1d_TYPE_INST: - return (a_opcode - | REGS (RD (inst), 11)); - - case R2td_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case R2st_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16)); - - case R2ds_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RD (inst), 11)); - - case R2sh_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (RD (inst), 11) - | REGS (SHAMT (inst), 6)); - - case R3_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case R3sh_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case FP_I2a_TYPE_INST: - return (a_opcode - | REGS (BASE (inst), 21) - | REGS (RT (inst), 16) - | (IOFFSET (inst) & 0xffff)); - - case FP_R2ds_TYPE_INST: - return (a_opcode - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case FP_R2ts_TYPE_INST: - return (a_opcode - | REGS (RT (inst), 16) - | REGS (FS (inst), 11)); - - case FP_CMP_TYPE_INST: - return (a_opcode - | REGS (FT (inst), 16) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6) - | COND (inst)); - - case FP_R3_TYPE_INST: - return (a_opcode - | REGS (FT (inst), 16) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case MOVC_TYPE_INST: - return (a_opcode - | REGS (RS (inst), 21) - | REGS (RT (inst), 16) - | REGS (RD (inst), 11)); - - case FP_MOVC_TYPE_INST: - return (a_opcode - | REGS (CC (inst), 18) - | REGS (FS (inst), 11) - | REGS (FD (inst), 6)); - - case J_TYPE_INST: - return (a_opcode - | TARGET (inst)); - - case NOARG_TYPE_INST: - return (a_opcode); - - default: - fatal_error ("Unknown instruction type in inst_encoding\n"); - return (0); /* Not reached */ - } -} - - -/* Maintain a table mapping from actual opcode to interal opcode. - Table must be sorted before first use since its entries are - alphabetical on name, not ordered by opcode. */ - - -/* Map from internal opcode -> real opcode */ - -static name_val_val a_opcode_tbl [] = { -#undef OP -#define OP(NAME, I_OPCODE, TYPE, A_OPCODE) {NAME, (int)A_OPCODE, (int)I_OPCODE}, -#include "op.h" -}; - - -/* Sort the opcode table on their key (the interal opcode value). */ - -static void -sort_a_opcode_table () -{ - qsort (a_opcode_tbl, - sizeof (a_opcode_tbl) / sizeof (name_val_val), - sizeof (name_val_val), - (QSORT_FUNC) compare_pair_value); -} - - - -instruction * -inst_decode (int32 val) -{ - int32 a_opcode = val & 0xfc000000; - name_val_val *entry; - int32 i_opcode; - - /* Field classes: (opcode is continued in other part of instruction): */ - if (a_opcode == 0 || a_opcode == 0x70000000) /* SPECIAL or SPECIAL2 */ - a_opcode |= (val & 0x3f); - else if (a_opcode == 0x04000000) /* REGIMM */ - a_opcode |= (val & 0x001f0000); - else if (a_opcode == 0x40000000) /* COP0 */ - a_opcode |= (val & 0x03e00000) | (val & 0x1f); - else if (a_opcode == 0x44000000) /* COP1 */ - { - a_opcode |= (val & 0x03e00000); - if ((val & 0xff000000) == 0x45000000) - a_opcode |= (val & 0x00010000); /* BC1f/t */ - else - a_opcode |= (val & 0x3f); - } - else if (a_opcode == 0x48000000 /* COPz */ - || a_opcode == 0x4c000000) - a_opcode |= (val & 0x03e00000); - - - entry = map_int_to_name_val_val (a_opcode_tbl, - sizeof (a_opcode_tbl) / sizeof (name_val_val), - a_opcode); - if (entry == NULL) - return (mk_r_inst (val, 0, 0, 0, 0, 0)); /* Invalid inst */ - - i_opcode = entry->value2; - - switch (map_int_to_name_val_val (name_tbl, - sizeof (name_tbl) / sizeof (name_val_val), - i_opcode)->value2) - { - case BC_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case B1_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), 0, val & 0xffff)); - - case I1s_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), 0, val & 0xffff)); - - case I1t_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case I2_TYPE_INST: - case B2_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case I2a_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), - val & 0xffff)); - - case R1s_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), 0, 0, 0)); - - case R1d_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, 0, BIN_RD(val), 0)); - - case R2td_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_RD(val), 0)); - - case R2st_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), 0, 0)); - - case R2ds_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), 0, BIN_RD(val), 0)); - - case R2sh_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_RD(val), BIN_SA(val))); - - case R3_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case R3sh_TYPE_INST: - return(mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case FP_I2a_TYPE_INST: - return (mk_i_inst (val, i_opcode, BIN_BASE(val), BIN_FT(val), val & 0xffff)); - - case FP_R2ds_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_FS(val), 0, BIN_FD(val), 0)); - - case FP_R2ts_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, BIN_RT(val), BIN_FS(val), 0)); - - case FP_CMP_TYPE_INST: - { - instruction *inst = mk_r_inst (val, i_opcode, BIN_FS (val), BIN_FT (val), BIN_FD(val), 0); - SET_COND (inst, val & 0xf); - return (inst); - } - - case FP_R3_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_FS(val), BIN_FT(val), BIN_FD(val), 0)); - - case MOVC_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_RS(val), BIN_RT(val), BIN_RD(val), 0)); - - case FP_MOVC_TYPE_INST: - return (mk_r_inst (val, i_opcode, BIN_FS(val), BIN_RT(val), BIN_FD(val), 0)); - - case J_TYPE_INST: - return (mk_j_inst (val, i_opcode, val & 0x2ffffff)); - - - case NOARG_TYPE_INST: - return (mk_r_inst (val, i_opcode, 0, 0, 0, 0)); - - default: - return (mk_r_inst (val, 0, 0, 0, 0, 0)); /* Invalid inst */ - } -} - - -static instruction * -mk_r_inst (int32 val, int opcode, int rs, int rt, int rd, int shamt) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_RD (inst, rd); - SET_SHAMT (inst, shamt); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - - -static instruction * -mk_i_inst (int32 val, int opcode, int rs, int rt, int offset) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_RS (inst, rs); - SET_RT (inst, rt); - SET_IOFFSET (inst, offset); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - -static instruction * -mk_j_inst (int32 val, int opcode, int target) -{ - instruction *inst = (instruction *) zmalloc (sizeof (instruction)); - - SET_OPCODE (inst, opcode); - SET_TARGET (inst, target); - SET_ENCODING (inst, val); - SET_EXPR (inst, NULL); - return (inst); -} - - - -/* Code to test encode/decode of instructions. */ - -void -test_assembly (instruction *inst) -{ - instruction *new_inst = inst_decode (inst_encode (inst)); - - inst_cmp (inst, new_inst); - free_inst (new_inst); -} - - -static void -inst_cmp (instruction *inst1, instruction *inst2) -{ - static str_stream ss; - - ss_clear (&ss); - if (memcmp (inst1, inst2, sizeof (instruction) - 4) != 0) - { - ss_printf (&ss, "=================== Not Equal ===================\n"); - format_an_inst (&ss, inst1, 0); - format_an_inst (&ss, inst2, 0); - ss_printf (&ss, "=================== Not Equal ===================\n"); - } -} diff --git a/spim-qtspimbot/CPU/inst.h b/spim-qtspimbot/CPU/inst.h deleted file mode 100755 index d848f39..0000000 --- a/spim-qtspimbot/CPU/inst.h +++ /dev/null @@ -1,280 +0,0 @@ -/* SPIM S20 MIPS simulator. - Description of a SPIM S20 instruction. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef INST_H -#define INST_H - -#include "spim.h" -#include "string-stream.h" - - -/* Represenation of the expression that produce a value for an instruction's - immediate field. Immediates have the form: label +/- offset. */ - -typedef struct immexpr -{ - int offset; /* Offset from symbol */ - struct lab *symbol; /* Symbolic label */ - short bits; /* > 0 => 31..16, < 0 => 15..0 */ - bool pc_relative; /* => offset from label in code */ -} imm_expr; - - -/* Representation of the expression that produce an address for an - instruction. Address have the form: label +/- offset (register). */ - -typedef struct addrexpr -{ - unsigned char reg_no; /* Register number */ - imm_expr *imm; /* The immediate part */ -} addr_expr; - - - -/* Representation of an instruction. Store the instruction fields in an - overlapping manner similar to the real encoding (but not identical, to - speed decoding in C code, as opposed to hardware).. */ - -typedef struct inst_s -{ - short opcode; - - union - { - /* R-type or I-type: */ - struct - { - unsigned char rs; - unsigned char rt; - - union - { - short imm; - - struct - { - unsigned char rd; - unsigned char shamt; - } r; - } r_i; - } r_i; - - /* J-type: */ - mem_addr target; - } r_t; - - int32 encoding; - imm_expr *expr; - char *source_line; -} instruction; - - -#define OPCODE(INST) (INST)->opcode -#define SET_OPCODE(INST, VAL) (INST)->opcode = (short)(VAL) - - -#define RS(INST) (INST)->r_t.r_i.rs -#define SET_RS(INST, VAL) (INST)->r_t.r_i.rs = (unsigned char)(VAL) - -#define RT(INST) (INST)->r_t.r_i.rt -#define SET_RT(INST, VAL) (INST)->r_t.r_i.rt = (unsigned char)(VAL) - -#define RD(INST) (INST)->r_t.r_i.r_i.r.rd -#define SET_RD(INST, VAL) (INST)->r_t.r_i.r_i.r.rd = (unsigned char)(VAL) - - -#define FS(INST) RD(INST) -#define SET_FS(INST, VAL) SET_RD(INST, VAL) - -#define FT(INST) RT(INST) -#define SET_FT(INST, VAL) SET_RT(INST, VAL) - -#define FD(INST) SHAMT(INST) -#define SET_FD(INST, VAL) SET_SHAMT(INST, VAL) - - -#define SHAMT(INST) (INST)->r_t.r_i.r_i.r.shamt -#define SET_SHAMT(INST, VAL) (INST)->r_t.r_i.r_i.r.shamt = (unsigned char)(VAL) - -#define IMM(INST) (INST)->r_t.r_i.r_i.imm -#define SET_IMM(INST, VAL) (INST)->r_t.r_i.r_i.imm = (short)(VAL) - - -#define BASE(INST) RS(INST) -#define SET_BASE(INST, VAL) SET_RS(INST, VAL) - -#define IOFFSET(INST) IMM(INST) -#define SET_IOFFSET(INST, VAL) SET_IMM(INST, VAL) -#define IDISP(INST) (SIGN_EX (IOFFSET (INST) << 2)) - - -#define COND(INST) RS(INST) -#define SET_COND(INST, VAL) SET_RS(INST, VAL) - -#define CC(INST) (RT(INST) >> 2) -#define ND(INST) ((RT(INST) & 0x2) >> 1) -#define TF(INST) (RT(INST) & 0x1) - - -#define TARGET(INST) (INST)->r_t.target -#define SET_TARGET(INST, VAL) (INST)->r_t.target = (mem_addr)(VAL) - -#define ENCODING(INST) (INST)->encoding -#define SET_ENCODING(INST, VAL) (INST)->encoding = (int32)(VAL) - -#define EXPR(INST) (INST)->expr -#define SET_EXPR(INST, VAL) (INST)->expr = (imm_expr*)(VAL) - -#define SOURCE(INST) (INST)->source_line -#define SET_SOURCE(INST, VAL) (INST)->source_line = (char *)(VAL) - - -#define COND_UN 0x1 -#define COND_EQ 0x2 -#define COND_LT 0x4 -#define COND_IN 0x8 - -/* Minimum and maximum values that fit in instruction's imm field */ -#define IMM_MIN 0xffff8000 -#define IMM_MAX 0x00007fff - -#define UIMM_MIN (unsigned)0 -#define UIMM_MAX ((unsigned)((1<<16)-1)) - -#define RAISE_EXCEPTION(REGIMAGE, CAUSE, MISC) \ - { \ - if (((CAUSE) != ExcCode_Int) && spimbot_tournament) { \ - robots[(REGIMAGE).context].done = 1; \ - } else { \ - raise_exception((REGIMAGE).context, (CAUSE)); \ - MISC; \ - } \ - } \ - - -#define RAISE_INTERRUPT(REGIMAGE, LEVEL) \ - { \ - /* Set IP (pending) bit for interrupt level. */ \ - CP0_Cause(REGIMAGE) |= (1 << ((LEVEL) + 8)); \ - } \ - -#define CLEAR_INTERRUPT(REGIMAGE, LEVEL) \ - { \ - /* Clear IP (pending) bit for interrupt level. */ \ - CP0_Cause(REGIMAGE) &= ~(1 << ((LEVEL) + 8)); \ - } \ - -/* Recognized exceptions: */ - -#define ExcCode_Int 0 /* Interrupt */ -#define ExcCode_Mod 1 /* TLB modification (not implemented) */ -#define ExcCode_TLBL 2 /* TLB exception (not implemented) */ -#define ExcCode_TLBS 3 /* TLB exception (not implemented) */ -#define ExcCode_AdEL 4 /* Address error (load/fetch) */ -#define ExcCode_AdES 5 /* Address error (store) */ -#define ExcCode_IBE 6 /* Bus error, instruction fetch */ -#define ExcCode_DBE 7 /* Bus error, data reference */ -#define ExcCode_Sys 8 /* Syscall exception */ -#define ExcCode_Bp 9 /* Breakpoint exception */ -#define ExcCode_RI 10 /* Reserve instruction */ -#define ExcCode_CpU 11 /* Coprocessor unusable */ -#define ExcCode_Ov 12 /* Arithmetic overflow */ -#define ExcCode_Tr 13 /* Trap */ -#define ExcCode_FPE 15 /* Floating point */ -#define ExcCode_C2E 18 /* Coprocessor 2 (not impelemented) */ -#define ExcCode_MDMX 22 /* MDMX unusable (not implemented) */ -#define ExcCode_WATCH 23 /* Reference to Watch (not impelemented) */ -#define ExcCode_MCheck 24 /* Machine check (not implemented) */ -#define ExcCode_CacheErr 30 /* Cache error (not impelemented) */ - -#define LAST_REAL_EXCEPT ExcCode_CacheErr - - - -/* Fields in binary representation of instructions: */ - -#define BIN_REG(V,O) (((V) >> O) & 0x1f) -#define BIN_RS(V) (BIN_REG(V, 21)) -#define BIN_RT(V) (BIN_REG(V, 16)) -#define BIN_RD(V) (BIN_REG(V, 11)) -#define BIN_SA(V) (BIN_REG(V, 6)) - -#define BIN_BASE(V) (BIN_REG(V, 21)) -#define BIN_FT(V) (BIN_REG(V, 16)) -#define BIN_FS(V) (BIN_REG(V, 11)) -#define BIN_FD(V) (BIN_REG(V, 6)) - - - -/* Exported functions: */ - -imm_expr *addr_expr_imm (addr_expr *expr); -int addr_expr_reg (addr_expr *expr); -imm_expr *const_imm_expr (int32 value); -imm_expr *copy_imm_expr (imm_expr *old_expr); -instruction *copy_inst (instruction *inst); -mem_addr current_text_pc (); -int32 eval_imm_expr (imm_expr *expr); -void format_an_inst (str_stream *ss, instruction *inst, mem_addr addr); -void free_inst (instruction *inst); -void i_type_inst (int opcode, int rt, int rs, imm_expr *expr); -void i_type_inst_free (int opcode, int rt, int rs, imm_expr *expr); -void increment_text_pc (int delta); -imm_expr *incr_expr_offset (imm_expr *expr, int32 value); -void initialize_inst_tables (); -instruction *inst_decode (int32 value); -int32 inst_encode (instruction *inst, bool correct_branches = false); -bool inst_is_breakpoint (mem_addr addr); -void j_type_inst (int opcode, imm_expr *target); -void k_text_begins_at_point (size_t context, mem_addr addr); -imm_expr *lower_bits_of_expr (imm_expr *old_expr); -addr_expr *make_addr_expr (int offs, char *sym, int reg_no); -imm_expr *make_imm_expr (int offs, char *sym, bool is_pc_relative); -bool opcode_is_branch (int opcode); -bool opcode_is_nullified_branch (int opcode); -bool opcode_is_true_branch (int opcode); -bool opcode_is_jump (int opcode); -bool opcode_is_load_store (int opcode); -void print_inst (mem_addr addr); -char* inst_to_string (mem_addr addr); -void r_co_type_inst (int opcode, int fd, int fs, int ft); -void r_cond_type_inst (int opcode, int fs, int ft, int cc); -void r_sh_type_inst (int opcode, int rd, int rt, int shamt); -void r_type_inst (int opcode, int rd, int rs, int rt); -void raise_exception(size_t context, int excode); -void store_instruction (instruction *inst); -void text_begins_at_point (size_t context, mem_addr addr); -imm_expr *upper_bits_of_expr (imm_expr *old_expr); -void user_kernel_text_segment (bool to_kernel); -bool is_zero_imm (imm_expr *expr); - -#endif diff --git a/spim-qtspimbot/CPU/mem.cpp b/spim-qtspimbot/CPU/mem.cpp deleted file mode 100755 index 5e0cae0..0000000 --- a/spim-qtspimbot/CPU/mem.cpp +++ /dev/null @@ -1,882 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to create, maintain and access memory. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" - -#include "../Spimbot/robot.h" - -extern char* prof_file_name; - -/* Exported Variables: */ - -mem_image_t mem_images[2]; - - -/* Local functions: */ - -static mem_word bad_mem_read (size_t context, mem_addr addr, int mask); -static void bad_mem_write (size_t context, mem_addr addr, mem_word value, int mask); -static instruction *bad_text_read (size_t context, mem_addr addr); -static void bad_text_write (size_t context, mem_addr addr, instruction *inst); -static void free_instructions (instruction **inst, int n); - - -/* Local variables: */ - -static int32 data_size_limit, stack_size_limit, k_data_size_limit; - - - -/* Memory is allocated in five chunks: - text, data, stack, kernel text, and kernel data. - - The arrays are independent and have different semantics. - - text is allocated from 0x400000 up and only contains INSTRUCTIONs. - It does not expand. - - data is allocated from 0x10000000 up. It can be extended by the - SBRK system call. Programs can only read and write this segment. - - stack grows from 0x7fffefff down. It is automatically extended. - Programs can only read and write this segment. - - k_text is like text, except its is allocated from 0x80000000 up. - - k_data is like data, but is allocated from 0x90000000 up. - - Both kernel text and kernel data can only be accessed in kernel mode. -*/ - -/* The text segments contain pointers to instructions, not actual - instructions, so they must be allocated large enough to hold as many - pointers as there would be instructions (the two differ on machines in - which pointers are not 32 bits long). The following calculations round - up in case size is not a multiple of BYTES_PER_WORD. */ - -#define BYTES_TO_INST(N) (((N) + BYTES_PER_WORD - 1) / BYTES_PER_WORD * sizeof(instruction*)) - - -void -make_memory (size_t context, int text_size, int data_size, int data_limit, - int stack_size, int stack_limit, int k_text_size, - int k_data_size, int k_data_limit) -{ - mem_image_t &mem_image = mem_images[context]; - - if (data_size <= 65536) - data_size = 65536; - data_size = ROUND_UP(data_size, BYTES_PER_WORD); /* Keep word aligned */ - - if (mem_image.text_seg == NULL) { - mem_image.text_seg = (instruction **) xmalloc (BYTES_TO_INST(text_size)); - mem_image.text_prof = (unsigned *) xmalloc(text_size); - } - else - { - free_instructions (mem_image.text_seg, (mem_image.text_top - TEXT_BOT) / BYTES_PER_WORD); - mem_image.text_seg = (instruction **) realloc (mem_image.text_seg, BYTES_TO_INST(text_size)); - mem_image.text_prof = (unsigned *)realloc(mem_image.text_prof,text_size); - } - memclr (mem_image.text_seg, BYTES_TO_INST(text_size)); - memclr(mem_image.text_prof,text_size); - mem_image.text_top = TEXT_BOT + text_size; - - data_size = ROUND_UP(data_size, BYTES_PER_WORD); /* Keep word aligned */ - if (mem_image.data_seg == NULL) - mem_image.data_seg = (mem_word *) xmalloc (data_size); - else - mem_image.data_seg = (mem_word *) realloc (mem_image.data_seg, data_size); - memclr (mem_image.data_seg, data_size); - mem_image.data_seg_b = (BYTE_TYPE *) mem_image.data_seg; - mem_image.data_seg_h = (short *) mem_image.data_seg; - mem_image.data_top = DATA_BOT + data_size; - data_size_limit = data_limit; - - stack_size = ROUND_UP(stack_size, BYTES_PER_WORD); /* Keep word aligned */ - if (mem_image.stack_seg == NULL) - mem_image.stack_seg = (mem_word *) xmalloc (stack_size); - else - mem_image.stack_seg = (mem_word *) realloc (mem_image.stack_seg, stack_size); - memclr (mem_image.stack_seg, stack_size); - mem_image.stack_seg_b = (BYTE_TYPE *) mem_image.stack_seg; - mem_image.stack_seg_h = (short *) mem_image.stack_seg; - mem_image.stack_bot = STACK_TOP - stack_size; - stack_size_limit = stack_limit; - - if (mem_image.special_seg == NULL) { - mem_image.special_seg = (mem_word *) xmalloc (SPECIAL_TOP - SPECIAL_BOT); - mem_image.special_seg_b = (BYTE_TYPE *) mem_image.special_seg; - mem_image.special_seg_h = (short *) mem_image.special_seg; - } - memclr (mem_image.special_seg, (SPECIAL_TOP - SPECIAL_BOT)); - - if (mem_image.k_text_seg == NULL){ - mem_image.k_text_seg = (instruction **) xmalloc (BYTES_TO_INST(k_text_size)); - mem_image.k_text_prof = (unsigned *) xmalloc(k_text_size); - } - else - { - free_instructions (mem_image.k_text_seg, - (mem_image.k_text_top - K_TEXT_BOT) / BYTES_PER_WORD); - mem_image.k_text_seg = (instruction **) realloc(mem_image.k_text_seg, - BYTES_TO_INST(k_text_size)); - mem_image.k_text_prof = (unsigned *) realloc(mem_image.k_text_prof, k_text_size); - } - memclr (mem_image.k_text_seg, BYTES_TO_INST(k_text_size)); - memclr (mem_image.k_text_prof, k_text_size); - mem_image.k_text_top = K_TEXT_BOT + k_text_size; - - k_data_size = ROUND_UP(k_data_size, BYTES_PER_WORD); /* Keep word aligned */ - if (mem_image.k_data_seg == NULL) - mem_image.k_data_seg = (mem_word *) xmalloc (k_data_size); - else - mem_image.k_data_seg = (mem_word *) realloc (mem_image.k_data_seg, k_data_size); - memclr (mem_image.k_data_seg, k_data_size); - mem_image.k_data_seg_b = (BYTE_TYPE *) mem_image.k_data_seg; - mem_image.k_data_seg_h = (short *) mem_image.k_data_seg; - mem_image.k_data_top = K_DATA_BOT + k_data_size; - k_data_size_limit = k_data_limit; - - mem_image.text_modified = true; - mem_image.data_modified = true; -} - - -void mem_dump_profile() { - mem_image_t &mem_image = mem_images[0]; - - str_stream ss; - ss_init(&ss); - FILE *file = NULL; - - if ((prof_file_name == NULL) || (prof_file_name[0] == 0)) { - return; - } - file = fopen(prof_file_name, "w"); - if (file == NULL) { - printf("failed to open profile file: %s\n", prof_file_name); - return; - } - - int text_size = (mem_image.text_top - TEXT_BOT)/4; - for (int i = 0 ; i < text_size ; ++ i) { - instruction *inst = mem_image.text_seg[i]; - if (inst == NULL) { - continue; - } - unsigned prof_count = mem_image.text_prof[i]; - mem_addr addr = TEXT_BOT + (i << 2); - fprintf(file, "%9d ", prof_count - 1); - format_an_inst(&ss, inst, addr); - //print_inst_internal (&buf[10], sizeof(buf)-12, inst, addr); - fprintf(file, "%s", ss_to_string(&ss)); - ss_clear(&ss); - fflush(file); - } - - fprintf(file, "\n\nkernel text segment\n\n"); - - int k_text_size = (mem_image.k_text_top - K_TEXT_BOT)/4; - for (int i = 0 ; i < k_text_size ; ++ i) { - instruction *inst = mem_image.k_text_seg[i]; - if (inst == NULL) { - continue; - } - unsigned prof_count = mem_image.k_text_prof[i]; - mem_addr addr = K_TEXT_BOT + (i << 2); - fprintf(file, "%9d ", prof_count - 1); - format_an_inst(&ss, inst, addr); - //print_inst_internal (&buf[10], sizeof(buf)-12, inst, addr); - fprintf(file, "%s", ss_to_string(&ss)); - ss_clear(&ss); - } - - fclose(file); -} - - -/* Free the storage used by the old instructions in memory. */ - -static void -free_instructions (instruction **inst, int n) -{ - for ( ; n > 0; n --, inst ++) - if (*inst) - free_inst (*inst); -} - - -/* Expand the data segment by adding N bytes. */ - -void -expand_data (size_t context, int addl_bytes) -{ - mem_image_t &mem_image = mem_images[context]; - - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = mem_image.data_top - DATA_BOT; - int new_size = old_size + delta; - BYTE_TYPE *p; - - if ((addl_bytes < 0) || (new_size > data_size_limit)) - { - error ("Can't expand data segment by %d bytes to %d bytes\n", - addl_bytes, new_size); - run_error ("Use -ldata # with # > %d\n", new_size); - } - mem_image.data_seg = (mem_word *) realloc (mem_image.data_seg, new_size); - if (mem_image.data_seg == NULL) - fatal_error ("realloc failed in expand_data\n"); - - mem_image.data_seg_b = (BYTE_TYPE *) mem_image.data_seg; - mem_image.data_seg_h = (short *) mem_image.data_seg; - mem_image.data_top += delta; - - /* Zero new memory */ - for (p = mem_image.data_seg_b + old_size; p < mem_image.data_seg_b + new_size; ) - *p ++ = 0; -} - - -/* Expand the stack segment by adding N bytes. Can't use REALLOC - since it copies from bottom of memory blocks and stack grows down from - top of its block. */ - -void -expand_stack (size_t context, int addl_bytes) -{ - mem_image_t &mem_image = mem_images[context]; - - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = STACK_TOP - mem_image.stack_bot; - int new_size = old_size + MAX (delta, old_size); - mem_word *new_seg; - mem_word *po, *pn; - - if ((addl_bytes < 0) || (new_size > stack_size_limit)) - { - run_error ("Can't expand stack segment by %d bytes to %d bytes.\nUse -lstack # with # > %d\n", - addl_bytes, new_size, new_size); - } - - new_seg = (mem_word *) xmalloc (new_size); - memset(new_seg, 0, new_size); - - po = mem_image.stack_seg + (old_size / BYTES_PER_WORD - 1); - pn = new_seg + (new_size / BYTES_PER_WORD - 1); - for ( ; po >= mem_image.stack_seg ; ) *pn -- = *po --; - - free (mem_image.stack_seg); - mem_image.stack_seg = new_seg; - mem_image.stack_seg_b = (BYTE_TYPE *) mem_image.stack_seg; - mem_image.stack_seg_h = (short *) mem_image.stack_seg; - mem_image.stack_bot -= (new_size - old_size); -} - - -/* Expand the kernel data segment by adding N bytes. */ - -void -expand_k_data (size_t context, int addl_bytes) -{ - mem_image_t &mem_image = mem_images[context]; - - int delta = ROUND_UP(addl_bytes, BYTES_PER_WORD); /* Keep word aligned */ - int old_size = mem_image.k_data_top - K_DATA_BOT; - int new_size = old_size + delta; - BYTE_TYPE *p; - - if ((addl_bytes < 0) || (new_size > k_data_size_limit)) - { - run_error ("Can't expand kernel data segment by %d bytes to %d bytes.\nUse -lkdata # with # > %d\n", - addl_bytes, new_size, new_size); - } - mem_image.k_data_seg = (mem_word *) realloc (mem_image.k_data_seg, new_size); - if (mem_image.k_data_seg == NULL) - fatal_error ("realloc failed in expand_k_data\n"); - - mem_image.k_data_seg_b = (BYTE_TYPE *) mem_image.k_data_seg; - mem_image.k_data_seg_h = (short *) mem_image.k_data_seg; - mem_image.k_data_top += delta; - - /* Zero new memory */ - for (p = mem_image.k_data_seg_b + old_size / BYTES_PER_WORD; - p < mem_image.k_data_seg_b + new_size / BYTES_PER_WORD; ) - *p ++ = 0; -} - - - -/* Access memory */ - -void* -mem_reference(size_t context, mem_addr addr) -{ - mem_image_t &mem_image = mem_images[context]; - - if ((addr >= TEXT_BOT) && (addr < mem_image.text_top)) - return addr - TEXT_BOT + (char*) mem_image.text_seg; - else if ((addr >= DATA_BOT) && (addr < mem_image.data_top)) - return addr - DATA_BOT + (char*) mem_image.data_seg; - else if ((addr >= mem_image.stack_bot) && (addr < STACK_TOP)) - return addr - mem_image.stack_bot + (char*) mem_image.stack_seg; - else if ((addr >= K_TEXT_BOT) && (addr < mem_image.k_text_top)) - return addr - K_TEXT_BOT + (char*) mem_image.k_text_seg; - else if ((addr >= K_DATA_BOT) && (addr < mem_image.k_data_top)) - return addr - K_DATA_BOT + (char*) mem_image.k_data_seg; - else - { - run_error ("Memory address out of bounds\n"); - return NULL; - } -} - - -instruction* -read_mem_inst(size_t context, mem_addr addr) -{ - mem_image_t &mem_image = mem_images[context]; - - if ((addr >= TEXT_BOT) && (addr < mem_image.text_top) && !(addr & 0x3)) { - ++ mem_image.text_prof[(addr - TEXT_BOT) >> 2]; - return mem_image.text_seg [(addr - TEXT_BOT) >> 2]; - } - else if ((addr >= K_TEXT_BOT) && (addr < mem_image.k_text_top) && !(addr & 0x3)) { - ++ mem_image.k_text_prof[(addr - K_TEXT_BOT) >> 2]; - return mem_image.k_text_seg [(addr - K_TEXT_BOT) >> 2]; - } - else - return bad_text_read (context, addr); -} - - -reg_word -read_mem_byte(size_t context, mem_addr addr) -{ - mem_image_t &mem_image = mem_images[context]; - - if ((addr >= DATA_BOT) && (addr < mem_image.data_top)) - return mem_image.data_seg_b [addr - DATA_BOT]; - else if ((addr >= mem_image.stack_bot) && (addr < STACK_TOP)) - return mem_image.stack_seg_b [addr - mem_image.stack_bot]; - else if ((addr >= K_DATA_BOT) && (addr < mem_image.k_data_top)) - return mem_image.k_data_seg_b [addr - K_DATA_BOT]; - else if ((addr >= SPECIAL_BOT) && (addr < SPECIAL_TOP)) - return mem_image.special_seg_b [addr - SPECIAL_BOT]; - else - return bad_mem_read (context, addr, 0); -} - - -reg_word -read_mem_half(size_t context, mem_addr addr) -{ - mem_image_t &mem_image = mem_images[context]; - - if ((addr >= DATA_BOT) && (addr < mem_image.data_top) && !(addr & 0x1)) - return mem_image.data_seg_h [(addr - DATA_BOT) >> 1]; - else if ((addr >= mem_image.stack_bot) && (addr < STACK_TOP) && !(addr & 0x1)) - return mem_image.stack_seg_h [(addr - mem_image.stack_bot) >> 1]; - else if ((addr >= K_DATA_BOT) && (addr < mem_image.k_data_top) && !(addr & 0x1)) - return mem_image.k_data_seg_h [(addr - K_DATA_BOT) >> 1]; - else if ((addr >= SPECIAL_BOT) && (addr < SPECIAL_TOP) && !(addr & 0x1)) - return mem_image.special_seg_h [(addr - SPECIAL_BOT) >> 1]; - else - return bad_mem_read (context, addr, 0x1); -} - - -reg_word -read_mem_word(size_t context, mem_addr addr) -{ - mem_image_t &mem_image = mem_images[context]; - - if ((addr >= DATA_BOT) && (addr < mem_image.data_top) && !(addr & 0x3)) - return mem_image.data_seg [(addr - DATA_BOT) >> 2]; - else if ((addr >= mem_image.stack_bot) && (addr < STACK_TOP) && !(addr & 0x3)) - return mem_image.stack_seg [(addr - mem_image.stack_bot) >> 2]; - else if ((addr >= K_DATA_BOT) && (addr < mem_image.k_data_top) && !(addr & 0x3)) - return mem_image.k_data_seg [(addr - K_DATA_BOT) >> 2]; - else if ((addr >= SPECIAL_BOT) && (addr < SPECIAL_TOP) && !(addr & 0x3)) - return mem_image.special_seg [(addr - SPECIAL_BOT) >> 2]; - else - return bad_mem_read (context, addr, 0x3); -} - - -void -set_mem_inst(size_t context, mem_addr addr, instruction* inst) -{ - mem_image_t &mem_image = mem_images[context]; - - mem_image.text_modified = true; - if ((addr >= TEXT_BOT) && (addr < mem_image.text_top) && !(addr & 0x3)) - mem_image.text_seg [(addr - TEXT_BOT) >> 2] = inst; - else if ((addr >= K_TEXT_BOT) && (addr < mem_image.k_text_top) && !(addr & 0x3)) - mem_image.k_text_seg [(addr - K_TEXT_BOT) >> 2] = inst; - else - bad_text_write (context, addr, inst); -} - - -void -set_mem_byte(size_t context, mem_addr addr, reg_word value) -{ - mem_image_t &mem_image = mem_images[context]; - - mem_image.data_modified = true; - if ((addr >= DATA_BOT) && (addr < mem_image.data_top)) - mem_image.data_seg_b [addr - DATA_BOT] = (BYTE_TYPE) value; - else if ((addr >= mem_image.stack_bot) && (addr < STACK_TOP)) - mem_image.stack_seg_b [addr - mem_image.stack_bot] = (BYTE_TYPE) value; - else if ((addr >= K_DATA_BOT) && (addr < mem_image.k_data_top)) - mem_image.k_data_seg_b [addr - K_DATA_BOT] = (BYTE_TYPE) value; - else if ((addr >= SPECIAL_BOT) && (addr < SPECIAL_TOP)) - mem_image.special_seg_b [addr - SPECIAL_BOT] = (BYTE_TYPE) value; - else - bad_mem_write (context, addr, value, 0); -} - - -void -set_mem_half(size_t context, mem_addr addr, reg_word value) -{ - mem_image_t &mem_image = mem_images[context]; - - mem_image.data_modified = true; - if ((addr >= DATA_BOT) && (addr < mem_image.data_top) && !(addr & 0x1)) - mem_image.data_seg_h [(addr - DATA_BOT) >> 1] = (short) value; - else if ((addr >= mem_image.stack_bot) && (addr < STACK_TOP) && !(addr & 0x1)) - mem_image.stack_seg_h [(addr - mem_image.stack_bot) >> 1] = (short) value; - else if ((addr >= K_DATA_BOT) && (addr < mem_image.k_data_top) && !(addr & 0x1)) - mem_image.k_data_seg_h [(addr - K_DATA_BOT) >> 1] = (short) value; - else if ((addr >= SPECIAL_BOT) && (addr < SPECIAL_TOP) && !(addr & 0x1)) - mem_image.special_seg_h [(addr - SPECIAL_BOT) >> 1] = (short) value; - else - bad_mem_write (context, addr, value, 0x1); -} - - -void -set_mem_word(size_t context, mem_addr addr, reg_word value) -{ - mem_image_t &mem_image = mem_images[context]; - - mem_image.data_modified = true; - if ((addr >= DATA_BOT) && (addr < mem_image.data_top) && !(addr & 0x3)) - mem_image.data_seg [(addr - DATA_BOT) >> 2] = (mem_word) value; - else if ((addr >= mem_image.stack_bot) && (addr < STACK_TOP) && !(addr & 0x3)) - mem_image.stack_seg [(addr - mem_image.stack_bot) >> 2] = (mem_word) value; - else if ((addr >= K_DATA_BOT) && (addr < mem_image.k_data_top) && !(addr & 0x3)) - mem_image.k_data_seg [(addr - K_DATA_BOT) >> 2] = (mem_word) value; - else if ((addr >= SPECIAL_BOT) && (addr < SPECIAL_TOP) && !(addr & 0x3)) - mem_image.special_seg [(addr - SPECIAL_BOT) >> 2] = (mem_word) value; - else - bad_mem_write (context, addr, value, 0x3); -} - - -/* Handle the infrequent and erroneous cases in memory accesses. */ - -static instruction * -bad_text_read (size_t context, mem_addr addr) -{ - reg_image_t ®_image = reg_images[context]; - - RAISE_EXCEPTION (reg_image, ExcCode_IBE, CP0_BadVAddr(reg_image) = addr); - return (inst_decode (0)); -} - - -static void -bad_text_write (size_t context, mem_addr addr, instruction *inst) -{ - reg_image_t ®_image = reg_images[context]; - - RAISE_EXCEPTION (reg_image, ExcCode_IBE, CP0_BadVAddr(reg_image) = addr); - set_mem_word (context, addr, ENCODING (inst)); -} - - -static mem_word -bad_mem_read (size_t context, mem_addr addr, int mask) -{ - reg_image_t ®_image = reg_images[context]; - mem_image_t &mem_image = mem_images[context]; - - mem_word tmp; - - if ((addr & mask) != 0) - RAISE_EXCEPTION (reg_image, ExcCode_AdEL, CP0_BadVAddr(reg_image) = addr) - else if (addr >= TEXT_BOT && addr < mem_image.text_top) - switch (mask) - { - case 0x0: - tmp = ENCODING (mem_image.text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = (unsigned)tmp >> (8 * (3 - (addr & 0x3))); -#else - tmp = (unsigned)tmp >> (8 * (addr & 0x3)); -#endif - return (0xff & tmp); - - case 0x1: - tmp = ENCODING (mem_image.text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = (unsigned)tmp >> (8 * (2 - (addr & 0x2))); -#else - tmp = (unsigned)tmp >> (8 * (addr & 0x2)); -#endif - return (0xffff & tmp); - - case 0x3: - { - instruction *inst = mem_image.text_seg [(addr - TEXT_BOT) >> 2]; - if (inst == NULL) - return 0; - else - return (ENCODING (inst)); - } - - default: - run_error ("Bad mask (0x%x) in bad_mem_read\n", mask); - } - else if (addr > mem_image.data_top - && addr < mem_image.stack_bot - /* If more than 16 MB below stack, probably is bad data ref */ - && addr > mem_image.stack_bot - 16*K*K) - { - /* Grow stack segment */ - expand_stack (context,mem_image.stack_bot - addr + 4); - return (0); - } - else if (SPIMBOT_IO_BOT <= addr && addr <= SPIMBOT_IO_TOP) - return (read_spimbot_IO (context, addr)); - else - /* Address out of range */ - RAISE_EXCEPTION (reg_image, ExcCode_DBE, CP0_BadVAddr(reg_image) = addr) - return (0); -} - - -static void -bad_mem_write (size_t context, mem_addr addr, mem_word value, int mask) -{ - reg_image_t ®_image = reg_images[context]; - mem_image_t &mem_image = mem_images[context]; - - mem_word tmp; - - if ((addr & mask) != 0) - /* Unaligned address fault */ - RAISE_EXCEPTION (reg_image, ExcCode_AdES, CP0_BadVAddr(reg_image) = addr) - else if (addr >= TEXT_BOT && addr < mem_image.text_top) - { - switch (mask) - { - case 0x0: - tmp = ENCODING (mem_image.text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = ((tmp & ~(0xff << (8 * (3 - (addr & 0x3))))) - | (value & 0xff) << (8 * (3 - (addr & 0x3)))); -#else - tmp = ((tmp & ~(0xff << (8 * (addr & 0x3)))) - | (value & 0xff) << (8 * (addr & 0x3))); -#endif - break; - - case 0x1: - tmp = ENCODING (mem_image.text_seg [(addr - TEXT_BOT) >> 2]); -#ifdef SPIM_BIGENDIAN - tmp = ((tmp & ~(0xffff << (8 * (2 - (addr & 0x2))))) - | (value & 0xffff) << (8 * (2 - (addr & 0x2)))); -#else - tmp = ((tmp & ~(0xffff << (8 * (addr & 0x2)))) - | (value & 0xffff) << (8 * (addr & 0x2))); -#endif - break; - - case 0x3: - tmp = value; - break; - - default: - tmp = 0; - run_error ("Bad mask (0x%x) in bad_mem_read\n", mask); - } - - if (mem_image.text_seg [(addr - TEXT_BOT) >> 2] != NULL) - { - free_inst (mem_image.text_seg[(addr - TEXT_BOT) >> 2]); - } - mem_image.text_seg [(addr - TEXT_BOT) >> 2] = inst_decode (tmp); - - mem_image.text_modified = true; - } - else if (addr > mem_image.data_top - && addr < mem_image.stack_bot - /* If more than 16 MB below stack, probably is bad data ref */ - && addr > mem_image.stack_bot - 16*K*K) - { - /* Grow stack segment */ - expand_stack (context,mem_image.stack_bot - addr + 4); - if (addr >= mem_image.stack_bot) - { - if (mask == 0) - mem_image.stack_seg_b [addr - mem_image.stack_bot] = (char)value; - else if (mask == 1) - mem_image.stack_seg_h [(addr - mem_image.stack_bot) >> 1] = (short)value; - else - mem_image.stack_seg [(addr - mem_image.stack_bot) >> 2] = value; - } - else - RAISE_EXCEPTION (reg_image, ExcCode_DBE, CP0_BadVAddr(reg_image) = addr) - - mem_image.data_modified = true; - } - else if (SPIMBOT_IO_BOT <= addr && addr <= SPIMBOT_IO_TOP) - write_spimbot_IO (context, addr, value); - else - /* Address out of range */ - RAISE_EXCEPTION (reg_image, ExcCode_DBE, CP0_BadVAddr(reg_image) = addr) -} - - - -/* Memory-mapped IO routines. */ - -static int recv_control = 0; /* No input */ -static int recv_buffer; -static int recv_buffer_full_timer = 0; - -static int trans_control = TRANS_READY; /* Ready to write */ -// static int trans_buffer; -static int trans_buffer_full_timer = 0; - - -/* Check if input is available and output is possible. If so, update the - memory-mapped control registers and buffers. */ - -void -check_memory_mapped_IO (size_t context) -{ - reg_image_t ®_image = reg_images[context]; - - if (recv_buffer_full_timer > 0) - { - /* Do not check for more input until this interval expires. */ - recv_buffer_full_timer -= 1; - } - else if (console_input_available ()) - { - /* Read new char into the buffer and raise an interrupt, if interrupts - are enabled for device. */ - /* assert(recv_buffer_full_timer == 0); */ - recv_buffer = get_console_char (); - recv_control |= RECV_READY; - recv_buffer_full_timer = RECV_INTERVAL; - if (recv_control & RECV_INT_ENABLE) - { - RAISE_INTERRUPT (reg_image, RECV_INT_LEVEL); - } - } - - if (trans_buffer_full_timer > 0) - { - /* Do not allow output until this interval expires. */ - trans_buffer_full_timer -= 1; - } - else if (!(trans_control & TRANS_READY)) - { - /* Done writing: empty the buffer and raise an interrupt, if interrupts - are enabled for device. */ - /* assert(trans_buffer_full_timer == 0); */ - trans_control |= TRANS_READY; - if (trans_control & TRANS_INT_ENABLE) - { - RAISE_INTERRUPT (reg_image, TRANS_INT_LEVEL); - } - } -} - - -/* Invoked on a write to the memory-mapped IO area. */ -// SPIMBOT: we over-ride these functions with our own I/O routines - -// static void -// write_memory_mapped_IO (mem_addr addr, mem_word value) -// { -// reg_image_t ®_image = reg_images[0]; -// -// switch (addr) -// { -// case TRANS_CTRL_ADDR: -// /* Program can only set the interrupt enable, not ready, bit. */ -// if ((value & TRANS_INT_ENABLE) != 0) -// { -// /* Enable interrupts: */ -// trans_control |= TRANS_INT_ENABLE; -// if (trans_control & TRANS_READY) -// { -// /* Raise interrupt on enabling a ready transmitter */ -// RAISE_INTERRUPT (reg_image, TRANS_INT_LEVEL); -// } -// } -// else -// { -// /* Disable interrupts: */ -// trans_control &= ~TRANS_INT_ENABLE; -// CLEAR_INTERRUPT (reg_image, TRANS_INT_LEVEL); /* Clear IP bit in Cause */ -// } -// break; -// -// case TRANS_BUFFER_ADDR: -// /* Ignore write if device is not ready. */ -// if ((trans_control & TRANS_READY) != 0) -// { -// /* Write char: */ -// trans_buffer = value & 0xff; -// put_console_char ((char)trans_buffer); -// /* Device is busy for a while: */ -// trans_control &= ~TRANS_READY; -// trans_buffer_full_timer = TRANS_LATENCY; -// CLEAR_INTERRUPT (reg_image, TRANS_INT_LEVEL); /* Clear IP bit in Cause */ -// } -// break; -// -// case RECV_CTRL_ADDR: -// /* Program can only set the interrupt enable, not ready, bit. */ -// if ((value & RECV_INT_ENABLE) != 0) -// { -// /* Enable interrupts: */ -// recv_control |= RECV_INT_ENABLE; -// if (recv_control & RECV_READY) -// { -// /* Raise interrupt on enabling a ready receiver */ -// RAISE_INTERRUPT (reg_image, RECV_INT_LEVEL); -// } -// } -// else -// { -// /* Disable interrupts: */ -// recv_control &= ~RECV_INT_ENABLE; -// CLEAR_INTERRUPT (reg_image, RECV_INT_LEVEL); /* Clear IP bit in Cause */ -// } -// break; -// -// case RECV_BUFFER_ADDR: -// /* Nop: program can't change buffer. */ -// break; -// -// default: -// run_error ("Write to unused memory-mapped IO address (0x%x)\n", addr); -// } -// } -// -// -// /* Invoked on a read in the memory-mapped IO area. */ -// -// static mem_word -// read_memory_mapped_IO (mem_addr addr) -// { -// reg_image_t ®_image = reg_images[0]; -// -// switch (addr) -// { -// case TRANS_CTRL_ADDR: -// return (trans_control); -// -// case TRANS_BUFFER_ADDR: -// return (trans_buffer & 0xff); -// -// case RECV_CTRL_ADDR: -// return (recv_control); -// -// case RECV_BUFFER_ADDR: -// recv_control &= ~RECV_READY; /* Buffer now empty */ -// recv_buffer_full_timer = 0; -// CLEAR_INTERRUPT (reg_image, RECV_INT_LEVEL); /* Clear IP bit in Cause */ -// return (recv_buffer & 0xff); -// -// default: -// run_error ("Read from unused memory-mapped IO address (0x%x)\n", addr); -// return (0); -// } -// } - - - -/* Misc. routines */ - -void -print_mem (size_t context, mem_addr addr) -{ - mem_image_t &mem_image = mem_images[context]; - - mem_word value; - - if ((addr & 0x3) != 0) - addr &= ~0x3; /* Address must be word-aligned */ - - if (TEXT_BOT <= addr && addr < mem_image.text_top) - print_inst (addr); - else if (DATA_BOT <= addr && addr < mem_image.data_top) - { - value = read_mem_word (context, addr); - write_output (message_out, "Data seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else if (mem_image.stack_bot <= addr && addr < STACK_TOP) - { - value = read_mem_word (context, addr); - write_output (message_out, "Stack seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else if (K_TEXT_BOT <= addr && addr < mem_image.k_text_top) - print_inst (addr); - else if (K_DATA_BOT <= addr && addr < mem_image.k_data_top) - { - value = read_mem_word (context, addr); - write_output (message_out, - "Kernel Data seg @ 0x%08x (%d) = 0x%08x (%d)\n", - addr, addr, value, value); - } - else - error ("Address 0x%08x (%d) to print_mem is out of bounds\n", addr, addr); -} diff --git a/spim-qtspimbot/CPU/mem.h b/spim-qtspimbot/CPU/mem.h deleted file mode 100755 index 94cde81..0000000 --- a/spim-qtspimbot/CPU/mem.h +++ /dev/null @@ -1,158 +0,0 @@ -/* SPIM S20 MIPS simulator. - Macros for accessing memory. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef MEM_H -#define MEM_H - -#include "reg.h" - - -/* A note on directions: "Bottom" of memory is the direction of - decreasing addresses. "Top" is the direction of increasing addresses.*/ - - -/* Type of contents of a memory word. */ - -typedef int32 /*@alt unsigned int @*/ mem_word; - -#define BYTE_TYPE signed char - -typedef struct memimage { - /* The text segment. */ - instruction **text_seg; - unsigned *text_prof; - int text_modified; /* => text segment was written */ - mem_addr text_top; - - /* The data segment. */ - mem_word *data_seg; - bool data_modified; /* => a data segment was written */ - short *data_seg_h; /* Points to same vector as DATA_SEG */ - BYTE_TYPE *data_seg_b; /* Ditto */ - mem_addr data_top; - mem_addr gp_midpoint; /* Middle of $gp area */ - - /* The stack segment. */ - mem_word *stack_seg; - short *stack_seg_h; /* Points to same vector as STACK_SEG */ - BYTE_TYPE *stack_seg_b; /* Ditto */ - mem_addr stack_bot; - - /* Used for SPIMbot stuff. */ - mem_word *special_seg; - short *special_seg_h; - BYTE_TYPE *special_seg_b; - - /* The kernel text segment. */ - instruction **k_text_seg; - unsigned *k_text_prof; - mem_addr k_text_top; - - /* The kernel data segment. */ - mem_word *k_data_seg; - short *k_data_seg_h; - BYTE_TYPE *k_data_seg_b; - mem_addr k_data_top; - -} mem_image_t; - -extern mem_image_t mem_images[2]; - -/* The text boundaries. */ -#define TEXT_BOT ((mem_addr) 0x400000) -/* Amount to grow text segment when we run out of space for instructions. */ -#define TEXT_CHUNK_SIZE 4096 - -/* The data boundaries. */ -#define DATA_BOT ((mem_addr) 0x10000000) - -/* The stack boundaries. */ -/* Exclusive, but include 4K at top of stack. */ -#define STACK_TOP ((mem_addr) 0x80000000) - -/* The kernel text boundaries. */ -#define K_TEXT_BOT ((mem_addr) 0x80000000) - -/* The Kernel data boundaries. */ -#define K_DATA_BOT ((mem_addr) 0x90000000) - -/* Memory-mapped IO area: */ -#define MM_IO_BOT ((mem_addr) 0xffff0000) -#define MM_IO_TOP ((mem_addr) 0xffffffff) - -#define SPECIAL_BOT ((mem_addr) 0xfffe0000) -#define SPECIAL_TOP ((mem_addr) 0xffff0000) - -/* Read from console: */ -#define RECV_CTRL_ADDR ((mem_addr) 0xffff0000) -#define RECV_BUFFER_ADDR ((mem_addr) 0xffff0004) - -#define RECV_READY 0x1 -#define RECV_INT_ENABLE 0x2 - -#define RECV_INT_LEVEL 3 /* HW Interrupt 1 */ - - -/* Write to console: */ -#define TRANS_CTRL_ADDR ((mem_addr) 0xffff0008) -#define TRANS_BUFFER_ADDR ((mem_addr) 0xffff000c) - -#define TRANS_READY 0x1 -#define TRANS_INT_ENABLE 0x2 - -#define TRANS_INT_LEVEL 2 /* HW Interrupt 0 */ - - - - -/* Exported functions: */ - -void check_memory_mapped_IO (size_t context); -void expand_data (size_t context, int addl_bytes); -void expand_k_data (size_t context, int addl_bytes); -void expand_stack (size_t context, int addl_bytes); -void make_memory (size_t context, int text_size, int data_size, int data_limit, - int stack_size, int stack_limit, int k_text_size, - int k_data_size, int k_data_limit); -void mem_dump_profile(); -void* mem_reference(size_t context, mem_addr addr); -void print_mem (mem_addr addr); -instruction* read_mem_inst(size_t context, mem_addr addr); -reg_word read_mem_byte(size_t context, mem_addr addr); -reg_word read_mem_half(size_t context, mem_addr addr); -reg_word read_mem_word(size_t context, mem_addr addr); -void set_mem_inst(size_t context, mem_addr addr, instruction* inst); -void set_mem_byte(size_t context, mem_addr addr, reg_word value); -void set_mem_half(size_t context, mem_addr addr, reg_word value); -void set_mem_word(size_t context, mem_addr addr, reg_word value); - -#endif diff --git a/spim-qtspimbot/CPU/op.h b/spim-qtspimbot/CPU/op.h deleted file mode 100755 index 4b46df5..0000000 --- a/spim-qtspimbot/CPU/op.h +++ /dev/null @@ -1,525 +0,0 @@ -/* SPIM S20 MIPS simulator. - This file describes the MIPS instructions, the assembler pseudo - instructions, the assembler pseudo-ops, and the spim commands. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Type of each entry: */ - -#define ASM_DIR 0 -#define PSEUDO_OP 1 - -#define BC_TYPE_INST 10 -#define B1_TYPE_INST 11 -#define I1s_TYPE_INST 12 -#define I1t_TYPE_INST 13 -#define I2_TYPE_INST 14 -#define B2_TYPE_INST 15 -#define I2a_TYPE_INST 16 - -#define R1s_TYPE_INST 20 -#define R1d_TYPE_INST 21 -#define R2st_TYPE_INST 22 -#define R2ds_TYPE_INST 23 -#define R2td_TYPE_INST 24 -#define R2sh_TYPE_INST 25 -#define R3_TYPE_INST 26 -#define R3sh_TYPE_INST 27 - -#define FP_I2a_TYPE_INST 30 -#define FP_R2ds_TYPE_INST 31 -#define FP_R2ts_TYPE_INST 32 -#define FP_CMP_TYPE_INST 33 -#define FP_R3_TYPE_INST 34 -#define FP_R4_TYPE_INST 35 -#define FP_MOVC_TYPE_INST 36 -#define MOVC_TYPE_INST 37 - -#define J_TYPE_INST 40 -#define NOARG_TYPE_INST 42 - - -/* Information on each keyword token that can be read by spim. Must be - sorted in alphabetical order. */ - -OP(".alias", Y_ALIAS_DIR, ASM_DIR, -1) -OP(".align", Y_ALIGN_DIR, ASM_DIR, -1) -OP(".ascii", Y_ASCII_DIR, ASM_DIR, -1) -OP(".asciiz", Y_ASCIIZ_DIR, ASM_DIR, -1) -OP(".asm0", Y_ASM0_DIR, ASM_DIR, -1) -OP(".bgnb", Y_BGNB_DIR, ASM_DIR, -1) -OP(".byte", Y_BYTE_DIR, ASM_DIR, -1) -OP(".comm", Y_COMM_DIR, ASM_DIR, -1) -OP(".data", Y_DATA_DIR, ASM_DIR, -1) -OP(".double", Y_DOUBLE_DIR, ASM_DIR, -1) -OP(".end", Y_END_DIR, ASM_DIR, -1) -OP(".endb", Y_ENDB_DIR, ASM_DIR, -1) -OP(".endr", Y_ENDR_DIR, ASM_DIR, -1) -OP(".ent", Y_ENT_DIR, ASM_DIR, -1) -OP(".err", Y_ERR_DIR, ASM_DIR, -1) -OP(".extern", Y_EXTERN_DIR, ASM_DIR, -1) -OP(".file", Y_FILE_DIR, ASM_DIR, -1) -OP(".float", Y_FLOAT_DIR, ASM_DIR, -1) -OP(".fmask", Y_FMASK_DIR, ASM_DIR, -1) -OP(".frame", Y_FRAME_DIR, ASM_DIR, -1) -OP(".globl", Y_GLOBAL_DIR, ASM_DIR, -1) -OP(".half", Y_HALF_DIR, ASM_DIR, -1) -OP(".kdata", Y_K_DATA_DIR, ASM_DIR, -1) -OP(".ktext", Y_K_TEXT_DIR, ASM_DIR, -1) -OP(".lab", Y_LABEL_DIR, ASM_DIR, -1) -OP(".lcomm", Y_LCOMM_DIR, ASM_DIR, -1) -OP(".livereg", Y_LIVEREG_DIR, ASM_DIR, -1) -OP(".loc", Y_LOC_DIR, ASM_DIR, -1) -OP(".mask", Y_MASK_DIR, ASM_DIR, -1) -OP(".noalias", Y_NOALIAS_DIR, ASM_DIR, -1) -OP(".option", Y_OPTIONS_DIR, ASM_DIR, -1) -OP(".rdata", Y_RDATA_DIR, ASM_DIR, -1) -OP(".repeat", Y_REPEAT_DIR, ASM_DIR, -1) -OP(".sdata", Y_SDATA_DIR, ASM_DIR, -1) -OP(".set", Y_SET_DIR, ASM_DIR, -1) -OP(".space", Y_SPACE_DIR, ASM_DIR, -1) -OP(".struct", Y_STRUCT_DIR, ASM_DIR, -1) -OP(".text", Y_TEXT_DIR, ASM_DIR, -1) -OP(".verstamp",Y_VERSTAMP_DIR, ASM_DIR, -1) -OP(".vreg", Y_VREG_DIR, ASM_DIR, -1) -OP(".word", Y_WORD_DIR, ASM_DIR, -1) - -OP("abs", Y_ABS_POP, PSEUDO_OP, -1) -OP("abs.d", Y_ABS_D_OP, FP_R2ds_TYPE_INST, 0x46200005) -OP("abs.ps", Y_ABS_PS_OP, FP_R2ds_TYPE_INST, 0x46600005) /* MIPS32 Rev 2 */ -OP("abs.s", Y_ABS_S_OP, FP_R2ds_TYPE_INST, 0x46000005) - -OP("add", Y_ADD_OP, R3_TYPE_INST, 0x00000020) -OP("add.d", Y_ADD_D_OP, FP_R3_TYPE_INST, 0x46200000) -OP("add.ps", Y_ADD_PS_OP, FP_R3_TYPE_INST, 0x46600000) /* MIPS32 Rev 2 */ -OP("add.s", Y_ADD_S_OP, FP_R3_TYPE_INST, 0x46000000) -OP("addi", Y_ADDI_OP, I2_TYPE_INST, 0x20000000) -OP("addiu", Y_ADDIU_OP, I2_TYPE_INST, 0x24000000) -OP("addu", Y_ADDU_OP, R3_TYPE_INST, 0x00000021) - -OP("alnv.ps", Y_ALNV_PS_OP, FP_R4_TYPE_INST, 0x4c00001e) /* MIPS32 Rev 2 */ - -OP("and", Y_AND_OP, R3_TYPE_INST, 0x00000024) -OP("andi", Y_ANDI_OP, I2_TYPE_INST, 0x30000000) - -OP("b", Y_B_POP, PSEUDO_OP, -1) -OP("bal", Y_BAL_POP, PSEUDO_OP, -1) - -OP("bc1f", Y_BC1F_OP, BC_TYPE_INST, 0x45000000) -OP("bc1fl", Y_BC1FL_OP, BC_TYPE_INST, 0x45020000) /* MIPS32 */ -OP("bc1t", Y_BC1T_OP, BC_TYPE_INST, 0x45010000) -OP("bc1tl", Y_BC1TL_OP, BC_TYPE_INST, 0x45030000) /* MIPS32 */ - -OP("bc2f", Y_BC2F_OP, BC_TYPE_INST, 0x49000000) -OP("bc2fl", Y_BC2FL_OP, BC_TYPE_INST, 0x49020000) /* MIPS32 */ -OP("bc2t", Y_BC2T_OP, BC_TYPE_INST, 0x49010000) -OP("bc2tl", Y_BC2TL_OP, BC_TYPE_INST, 0x49030000) /* MIPS32 */ - -OP("beq", Y_BEQ_OP, B2_TYPE_INST, 0x10000000) -OP("beql", Y_BEQL_OP, B2_TYPE_INST, 0x50000000) /* MIPS32 */ -OP("beqz", Y_BEQZ_POP, PSEUDO_OP, -1) -OP("bge", Y_BGE_POP, PSEUDO_OP, -1) -OP("bgeu", Y_BGEU_POP, PSEUDO_OP, -1) -OP("bgez", Y_BGEZ_OP, B1_TYPE_INST, 0x04010000) -OP("bgezal", Y_BGEZAL_OP, B1_TYPE_INST, 0x04110000) -OP("bgezall", Y_BGEZALL_OP, B1_TYPE_INST, 0x04130000) /* MIPS32 */ -OP("bgezl", Y_BGEZL_OP, B1_TYPE_INST, 0x04030000) /* MIPS32 */ -OP("bgt", Y_BGT_POP, PSEUDO_OP, -1) -OP("bgtu", Y_BGTU_POP, PSEUDO_OP, -1) -OP("bgtz", Y_BGTZ_OP, B1_TYPE_INST, 0x1c000000) -OP("bgtzl", Y_BGTZL_OP, B1_TYPE_INST, 0x5c000000) /* MIPS32 */ -OP("ble", Y_BLE_POP, PSEUDO_OP, -1) -OP("bleu", Y_BLEU_POP, PSEUDO_OP, -1) -OP("blez", Y_BLEZ_OP, B1_TYPE_INST, 0x18000000) -OP("blezl", Y_BLEZL_OP, B1_TYPE_INST, 0x58000000) /* MIPS32 */ -OP("blt", Y_BLT_POP, PSEUDO_OP, -1) -OP("bltu", Y_BLTU_POP, PSEUDO_OP, -1) -OP("bltz", Y_BLTZ_OP, B1_TYPE_INST, 0x04000000) -OP("bltzal", Y_BLTZAL_OP, B1_TYPE_INST, 0x04100000) -OP("bltzall", Y_BLTZALL_OP, B1_TYPE_INST, 0x04120000) /* MIPS32 */ -OP("bltzl", Y_BLTZL_OP, B1_TYPE_INST, 0x04020000) /* MIPS32 */ -OP("bne", Y_BNE_OP, B2_TYPE_INST, 0x14000000) -OP("bnel", Y_BNEL_OP, B2_TYPE_INST, 0x54000000) /* MIPS32 */ -OP("bnez", Y_BNEZ_POP, PSEUDO_OP, -1) - -OP("break", Y_BREAK_OP, NOARG_TYPE_INST, 0x0000000d) - -OP("c.eq.d", Y_C_EQ_D_OP, FP_CMP_TYPE_INST, 0x46200032) -OP("c.eq.ps", Y_C_EQ_PS_OP, FP_CMP_TYPE_INST, 0x46600032) /* MIPS32 Rev 2 */ -OP("c.eq.s", Y_C_EQ_S_OP, FP_CMP_TYPE_INST, 0x46000032) -OP("c.f.d", Y_C_F_D_OP, FP_CMP_TYPE_INST, 0x46200030) -OP("c.f.ps", Y_C_F_PS_OP, FP_CMP_TYPE_INST, 0x46600030) /* MIPS32 Rev 2 */ -OP("c.f.s", Y_C_F_S_OP, FP_CMP_TYPE_INST, 0x46000030) -OP("c.le.d", Y_C_LE_D_OP, FP_CMP_TYPE_INST, 0x4620003e) -OP("c.le.ps", Y_C_LE_PS_OP, FP_CMP_TYPE_INST, 0x4660003e) /* MIPS32 Rev 2 */ -OP("c.le.s", Y_C_LE_S_OP, FP_CMP_TYPE_INST, 0x4600003e) -OP("c.lt.d", Y_C_LT_D_OP, FP_CMP_TYPE_INST, 0x4620003c) -OP("c.lt.ps", Y_C_LT_PS_OP, FP_CMP_TYPE_INST, 0x4660003c) /* MIPS32 Rev 2 */ -OP("c.lt.s", Y_C_LT_S_OP, FP_CMP_TYPE_INST, 0x4600003c) -OP("c.nge.d", Y_C_NGE_D_OP, FP_CMP_TYPE_INST, 0x4620003d) -OP("c.nge.ps", Y_C_NGE_PS_OP, FP_CMP_TYPE_INST, 0x4660003d) /* MIPS32 Rev 2 */ -OP("c.nge.s", Y_C_NGE_S_OP, FP_CMP_TYPE_INST, 0x4600003d) -OP("c.ngl.d", Y_C_NGL_D_OP, FP_CMP_TYPE_INST, 0x4620003b) -OP("c.ngl.ps", Y_C_NGL_PS_OP, FP_CMP_TYPE_INST, 0x4660003b) /* MIPS32 Rev 2 */ -OP("c.ngl.s", Y_C_NGL_S_OP, FP_CMP_TYPE_INST, 0x4600003b) -OP("c.ngle.d", Y_C_NGLE_D_OP, FP_CMP_TYPE_INST, 0x46200039) -OP("c.ngle.ps", Y_C_NGLE_PS_OP, FP_CMP_TYPE_INST, 0x46600039) /* MIPS32 Rev 2 */ -OP("c.ngle.s", Y_C_NGLE_S_OP, FP_CMP_TYPE_INST, 0x46000039) -OP("c.ngt.d", Y_C_NGT_D_OP, FP_CMP_TYPE_INST, 0x4620003f) -OP("c.ngt.ps", Y_C_NGT_PS_OP, FP_CMP_TYPE_INST, 0x4660003f) /* MIPS32 Rev 2 */ -OP("c.ngt.s", Y_C_NGT_S_OP, FP_CMP_TYPE_INST, 0x4600003f) -OP("c.ole.d", Y_C_OLE_D_OP, FP_CMP_TYPE_INST, 0x46200036) -OP("c.ole.ps", Y_C_OLE_PS_OP, FP_CMP_TYPE_INST, 0x46600036) /* MIPS32 Rev 2 */ -OP("c.ole.s", Y_C_OLE_S_OP, FP_CMP_TYPE_INST, 0x46000036) -OP("c.olt.d", Y_C_OLT_D_OP, FP_CMP_TYPE_INST, 0x46200034) -OP("c.olt.ps", Y_C_OLT_PS_OP, FP_CMP_TYPE_INST, 0x46600034) /* MIPS32 Rev 2 */ -OP("c.olt.s", Y_C_OLT_S_OP, FP_CMP_TYPE_INST, 0x46000034) -OP("c.seq.d", Y_C_SEQ_D_OP, FP_CMP_TYPE_INST, 0x4620003a) -OP("c.seq.ps", Y_C_SEQ_PS_OP, FP_CMP_TYPE_INST, 0x4660003a) /* MIPS32 Rev 2 */ -OP("c.seq.s", Y_C_SEQ_S_OP, FP_CMP_TYPE_INST, 0x4600003a) -OP("c.sf.d", Y_C_SF_D_OP, FP_CMP_TYPE_INST, 0x46200038) -OP("c.sf.ps", Y_C_SF_PS_OP, FP_CMP_TYPE_INST, 0x46600038) /* MIPS32 Rev 2 */ -OP("c.sf.s", Y_C_SF_S_OP, FP_CMP_TYPE_INST, 0x46000038) -OP("c.ueq.d", Y_C_UEQ_D_OP, FP_CMP_TYPE_INST, 0x46200033) -OP("c.ueq.ps", Y_C_UEQ_PS_OP, FP_CMP_TYPE_INST, 0x46600033) /* MIPS32 Rev 2 */ -OP("c.ueq.s", Y_C_UEQ_S_OP, FP_CMP_TYPE_INST, 0x46000033) -OP("c.ule.d", Y_C_ULE_D_OP, FP_CMP_TYPE_INST, 0x46200037) -OP("c.ule.ps", Y_C_ULE_PS_OP, FP_CMP_TYPE_INST, 0x46600037) /* MIPS32 Rev 2 */ -OP("c.ule.s", Y_C_ULE_S_OP, FP_CMP_TYPE_INST, 0x46000037) -OP("c.ult.d", Y_C_ULT_D_OP, FP_CMP_TYPE_INST, 0x46200035) -OP("c.ult.ps", Y_C_ULT_PS_OP, FP_CMP_TYPE_INST, 0x46600035) /* MIPS32 Rev 2 */ -OP("c.ult.s", Y_C_ULT_S_OP, FP_CMP_TYPE_INST, 0x46000035) -OP("c.un.d", Y_C_UN_D_OP, FP_CMP_TYPE_INST, 0x46200031) -OP("c.un.ps", Y_C_UN_PS_OP, FP_CMP_TYPE_INST, 0x46600031) /* MIPS32 Rev 2 */ -OP("c.un.s", Y_C_UN_S_OP, FP_CMP_TYPE_INST, 0x46000031) - -OP("cache", Y_CACHE_OP, I2_TYPE_INST, 0xbc000000) /* MIPS32 */ - -OP("ceil.l.d", Y_CEIL_L_D_OP, FP_R2ds_TYPE_INST, 0x4620000a) /* MIPS32 Rev 2 */ -OP("ceil.l.s", Y_CEIL_L_S_OP, FP_R2ds_TYPE_INST, 0x4600000a) /* MIPS32 Rev 2 */ -OP("ceil.w.d", Y_CEIL_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000e) /* MIPS32 */ -OP("ceil.w.s", Y_CEIL_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000e) /* MIPS32 */ - -OP("cfc0", Y_CFC0_OP, FP_R2ts_TYPE_INST, 0x40400000) -OP("cfc1", Y_CFC1_OP, FP_R2ts_TYPE_INST, 0x44400000) -OP("cfc2", Y_CFC2_OP, FP_R2ts_TYPE_INST, 0x48400000) - -OP("clo", Y_CLO_OP, R3_TYPE_INST, 0x70000021) -OP("clz", Y_CLZ_OP, R3_TYPE_INST, 0x70000020) - -OP("cop2", Y_COP2_OP, J_TYPE_INST, 0x4a000000) - -OP("ctc0", Y_CTC0_OP, FP_R2ts_TYPE_INST, 0x40c00000) -OP("ctc1", Y_CTC1_OP, FP_R2ts_TYPE_INST, 0x44c00000) -OP("ctc2", Y_CTC2_OP, FP_R2ts_TYPE_INST, 0x48c00000) - -OP("cvt.d.l", Y_CVT_D_L_OP, FP_R2ds_TYPE_INST, 0x46b00021) /* MIPS32 Rev 2 */ -OP("cvt.d.s", Y_CVT_D_S_OP, FP_R2ds_TYPE_INST, 0x46000021) -OP("cvt.d.w", Y_CVT_D_W_OP, FP_R2ds_TYPE_INST, 0x46200021) -OP("cvt.l.d", Y_CVT_L_D_OP, FP_R2ds_TYPE_INST, 0x46200025) /* MIPS32 Rev 2 */ -OP("cvt.l.s", Y_CVT_L_S_OP, FP_R2ds_TYPE_INST, 0x46000025) /* MIPS32 Rev 2 */ -OP("cvt.ps.s", Y_CVT_PS_S_OP, FP_R2ds_TYPE_INST, 0x46000026) /* MIPS32 Rev 2 */ -OP("cvt.s.d", Y_CVT_S_D_OP, FP_R2ds_TYPE_INST, 0x46200020) -OP("cvt.s.l", Y_CVT_S_L_OP, FP_R2ds_TYPE_INST, 0x46b00020) /* MIPS32 Rev 2 */ -OP("cvt.s.pl", Y_CVT_S_PL_OP, FP_R2ds_TYPE_INST, 0x46c00024) /* MIPS32 Rev 2 */ -OP("cvt.s.pu", Y_CVT_S_PU_OP, FP_R2ds_TYPE_INST, 0x46c00020) /* MIPS32 Rev 2 */ -OP("cvt.s.w", Y_CVT_S_W_OP, FP_R2ds_TYPE_INST, 0x46800020) -OP("cvt.w.d", Y_CVT_W_D_OP, FP_R2ds_TYPE_INST, 0x46200024) -OP("cvt.w.s", Y_CVT_W_S_OP, FP_R2ds_TYPE_INST, 0x46000024) - -OP("deret", Y_DERET_OP, NOARG_TYPE_INST, 0x4200001f) /* MIPS32 Rev 2 */ -OP("di", Y_DI_OP, I1t_TYPE_INST, 0x41606000) /* MIPS32 Rev 2 */ - -OP("div", Y_DIV_OP, R2st_TYPE_INST, 0x0000001a) -OP("div.d", Y_DIV_D_OP, FP_R3_TYPE_INST, 0x46200003) -OP("div.s", Y_DIV_S_OP, FP_R3_TYPE_INST, 0x46000003) -OP("divu", Y_DIVU_OP, R2st_TYPE_INST, 0x0000001b) - -OP("ehb", Y_EHB_OP, NOARG_TYPE_INST, 0x000000c0) /* MIPS32 Rev 2 */ -OP("ei", Y_EI_OP, I1t_TYPE_INST, 0x41606020) /* MIPS32 Rev 2 */ -OP("eret", Y_ERET_OP, NOARG_TYPE_INST, 0x42000018) /* MIPS32 */ -OP("ext", Y_EXT_OP, FP_R2ds_TYPE_INST, 0x7c000000) /* MIPS32 Rev 2 */ - -OP("floor.l.d", Y_FLOOR_L_D_OP, FP_R2ds_TYPE_INST, 0x4620000b) /* MIPS32 Rev 2 */ -OP("floor.l.s", Y_FLOOR_L_S_OP, FP_R2ds_TYPE_INST, 0x4600000b) /* MIPS32 Rev 2 */ -OP("floor.w.d", Y_FLOOR_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000f) /* MIPS32 */ -OP("floor.w.s", Y_FLOOR_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000f) /* MIPS32 */ - -OP("ins", Y_INS_OP, FP_R2ds_TYPE_INST, 0x7c000004) /* MIPS32 Rev 2 */ - -OP("j", Y_J_OP, J_TYPE_INST, 0x08000000) -OP("jal", Y_JAL_OP, J_TYPE_INST, 0x0c000000) -OP("jalr", Y_JALR_OP, R2ds_TYPE_INST, 0x00000009) -OP("jalr.hb", Y_JALR_HB_OP, R2ds_TYPE_INST, 0x00000409) /* MIPS32 Rev 2 */ - -OP("jr", Y_JR_OP, R1s_TYPE_INST, 0x00000008) -OP("jr.hb", Y_JR_HB_OP, R1s_TYPE_INST, 0x00000408) /* MIPS32 Rev 2 */ - -OP("l.d", Y_L_D_POP, PSEUDO_OP, -1) -OP("l.s", Y_L_S_POP, PSEUDO_OP, -1) - -OP("la", Y_LA_POP, PSEUDO_OP, -1) -OP("lb", Y_LB_OP, I2a_TYPE_INST, 0x80000000) -OP("lbu", Y_LBU_OP, I2a_TYPE_INST, 0x90000000) -OP("ld", Y_LD_POP, PSEUDO_OP, -1) -OP("ldc1", Y_LDC1_OP, FP_I2a_TYPE_INST, 0xd4000000) /* MIPS32 */ -OP("ldc2", Y_LDC2_OP, I2a_TYPE_INST, 0xd8000000) /* MIPS32 */ -OP("ldxc1", Y_LDXC1_OP, FP_R3_TYPE_INST, 0x4c000001) /* MIPS32 Rev 2 */ -OP("lh", Y_LH_OP, I2a_TYPE_INST, 0x84000000) -OP("lhu", Y_LHU_OP, I2a_TYPE_INST, 0x94000000) - -OP("li", Y_LI_POP, PSEUDO_OP, -1) -OP("li.d", Y_LI_D_POP, PSEUDO_OP, -1) -OP("li.s", Y_LI_S_POP, PSEUDO_OP, -1) - -OP("ll", Y_LL_OP, I2a_TYPE_INST, 0xc0000000) /* MIPS32 */ - -OP("lui", Y_LUI_OP, I1t_TYPE_INST, 0x3c000000) -OP("luxc1", Y_LUXC1_OP, FP_R3_TYPE_INST, 0x4c000005) /* MIPS32 Rev 2 */ - -OP("lw", Y_LW_OP, I2a_TYPE_INST, 0x8c000000) -OP("lwc1", Y_LWC1_OP, FP_I2a_TYPE_INST, 0xc4000000) -OP("lwc2", Y_LWC2_OP, I2a_TYPE_INST, 0xc8000000) -OP("lwl", Y_LWL_OP, I2a_TYPE_INST, 0x88000000) -OP("lwr", Y_LWR_OP, I2a_TYPE_INST, 0x98000000) -OP("lwxc1", Y_LWXC1_OP, FP_R3_TYPE_INST, 0x4c000000) /* MIPS32 Rev 2 */ - -OP("madd", Y_MADD_OP, R2st_TYPE_INST, 0x70000000) /* MIPS32 */ -OP("madd.d", Y_MADD_D_OP, FP_R4_TYPE_INST, 0x4c000001) /* MIPS32 Rev 2 */ -OP("madd.ps", Y_MADD_PS_OP, FP_R4_TYPE_INST, 0x4c000006) /* MIPS32 Rev 2 */ -OP("madd.s", Y_MADD_S_OP, FP_R4_TYPE_INST, 0x4c000000) /* MIPS32 Rev 2 */ -OP("maddu", Y_MADDU_OP, R2st_TYPE_INST, 0x70000001) /* MIPS32 */ - -OP("mfc0", Y_MFC0_OP, R2td_TYPE_INST, 0x40000000) -OP("mfc1", Y_MFC1_OP, FP_R2ts_TYPE_INST, 0x44000000) -OP("mfc1.d", Y_MFC1_D_POP, PSEUDO_OP, -1) -OP("mfc2", Y_MFC2_OP, R2td_TYPE_INST, 0x48000000) -OP("mfhc1", Y_MFHC1_OP, FP_R2ts_TYPE_INST, 0x44600000) /* MIPS32 Rev 2 */ -OP("mfhc2", Y_MFHC2_OP, R2td_TYPE_INST, 0x48600000) /* MIPS32 Rev 2 */ -OP("mfhi", Y_MFHI_OP, R1d_TYPE_INST, 0x00000010) -OP("mflo", Y_MFLO_OP, R1d_TYPE_INST, 0x00000012) - -OP("mov.d", Y_MOV_D_OP, FP_R2ds_TYPE_INST, 0x46200006) -OP("mov.ps", Y_MOV_PS_OP, FP_R2ds_TYPE_INST, 0x46c00006) /* MIPS32 Rev 2 */ -OP("mov.s", Y_MOV_S_OP, FP_R2ds_TYPE_INST, 0x46000006) -OP("move", Y_MOVE_POP, PSEUDO_OP, -1) - -OP("movf", Y_MOVF_OP, MOVC_TYPE_INST, 0x00000001) /* MIPS32 */ -OP("movf.d", Y_MOVF_D_OP, FP_MOVC_TYPE_INST, 0x46200011) /* MIPS32 */ -OP("movf.ps", Y_MOVF_PS_OP, FP_MOVC_TYPE_INST, 0x46c00011) /* MIPS32 Rev 2 */ -OP("movf.s", Y_MOVF_S_OP, FP_MOVC_TYPE_INST, 0x46000011) /* MIPS32 */ - -OP("movn", Y_MOVN_OP, R3_TYPE_INST, 0x0000000b) /* MIPS32 */ -OP("movn.d", Y_MOVN_D_OP, FP_MOVC_TYPE_INST, 0x46200013) /* MIPS32 */ -OP("movn.ps", Y_MOVN_PS_OP, FP_MOVC_TYPE_INST, 0x46c00013) /* MIPS32 Rev 2 */ -OP("movn.s", Y_MOVN_S_OP, FP_MOVC_TYPE_INST, 0x46000013) /* MIPS32 */ - -OP("movt", Y_MOVT_OP, MOVC_TYPE_INST, 0x00010001) /* MIPS32 */ -OP("movt.d", Y_MOVT_D_OP, FP_MOVC_TYPE_INST, 0x46210011) /* MIPS32 */ -OP("movt.ps", Y_MOVT_PS_OP, FP_MOVC_TYPE_INST, 0x46c10011) /* MIPS32 Rev 2 */ -OP("movt.s", Y_MOVT_S_OP, FP_MOVC_TYPE_INST, 0x46010011) /* MIPS32 */ - -OP("movz", Y_MOVZ_OP, R3_TYPE_INST, 0x0000000a) /* MIPS32 */ -OP("movz.d", Y_MOVZ_D_OP, FP_MOVC_TYPE_INST, 0x46200012) /* MIPS32 */ -OP("movz.ps", Y_MOVZ_PS_OP, FP_MOVC_TYPE_INST, 0x46c00012) /* MIPS32 Rev 2 */ -OP("movz.s", Y_MOVZ_S_OP, FP_MOVC_TYPE_INST, 0x46000012) /* MIPS32 */ - -OP("msub", Y_MSUB_OP, R2st_TYPE_INST, 0x70000004) /* MIPS32 */ -OP("msub.d", Y_MSUB_D_OP, FP_R4_TYPE_INST, 0x4c000021) /* MIPS32 Rev 2 */ -OP("msub.ps", Y_MSUB_PS_OP, FP_R4_TYPE_INST, 0x4c000026) /* MIPS32 Rev 2 */ -OP("msub.s", Y_MSUB_S_OP, FP_R4_TYPE_INST, 0x4c000020) /* MIPS32 Rev 2 */ -OP("msubu", Y_MSUBU_OP, R2st_TYPE_INST, 0x70000005) /* MIPS32 */ - -OP("mtc0", Y_MTC0_OP, R2td_TYPE_INST, 0x40800000) -OP("mtc1", Y_MTC1_OP, FP_R2ts_TYPE_INST, 0x44800000) -OP("mtc1.d", Y_MTC1_D_POP, PSEUDO_OP, -1) -OP("mtc2", Y_MTC2_OP, R2td_TYPE_INST, 0x48800000) -OP("mthc1", Y_MTHC1_OP, FP_R2ts_TYPE_INST, 0x44e00000) /* MIPS32 Rev 2 */ -OP("mthc2", Y_MTHC2_OP, R2td_TYPE_INST, 0x48e00000) /* MIPS32 Rev 2 */ - -OP("mthi", Y_MTHI_OP, R1s_TYPE_INST, 0x00000011) -OP("mtlo", Y_MTLO_OP, R1s_TYPE_INST, 0x00000013) - -OP("mul", Y_MUL_OP, R3_TYPE_INST, 0x70000002) /* MIPS32 */ -OP("mul.d", Y_MUL_D_OP, FP_R3_TYPE_INST, 0x46200002) -OP("mul.ps", Y_MUL_PS_OP, FP_R3_TYPE_INST, 0x46c00002) /* MIPS32 Rev 2 */ -OP("mul.s", Y_MUL_S_OP, FP_R3_TYPE_INST, 0x46000002) -OP("mulo", Y_MULO_POP, PSEUDO_OP, -1) -OP("mulou", Y_MULOU_POP, PSEUDO_OP, -1) -OP("mult", Y_MULT_OP, R2st_TYPE_INST, 0x00000018) -OP("multu", Y_MULTU_OP, R2st_TYPE_INST, 0x00000019) - -OP("neg", Y_NEG_POP, PSEUDO_OP, -1) -OP("neg.d", Y_NEG_D_OP, FP_R2ds_TYPE_INST, 0x46200007) -OP("neg.ps", Y_NEG_PS_OP, FP_R2ds_TYPE_INST, 0x46c00007) /* MIPS32 Rev 2 */ -OP("neg.s", Y_NEG_S_OP, FP_R2ds_TYPE_INST, 0x46000007) -OP("negu", Y_NEGU_POP, PSEUDO_OP, -1) - -OP("nmadd.d", Y_NMADD_D_OP, FP_R4_TYPE_INST, 0x4c000031) /* MIPS32 Rev 2 */ -OP("nmadd.ps", Y_NMADD_PS_OP, FP_R4_TYPE_INST, 0x4c000036) /* MIPS32 Rev 2 */ -OP("nmadd.s", Y_NMADD_S_OP, FP_R4_TYPE_INST, 0x4c000030) /* MIPS32 Rev 2 */ -OP("nmsub.d", Y_NMSUB_D_OP, FP_R4_TYPE_INST, 0x4c000039) /* MIPS32 Rev 2 */ -OP("nmsub.ps", Y_NMSUB_PS_OP, FP_R4_TYPE_INST, 0x4c00003e) /* MIPS32 Rev 2 */ -OP("nmsub.s", Y_NMSUB_S_OP, FP_R4_TYPE_INST, 0x4c000038) /* MIPS32 Rev 2 */ - -OP("nop", Y_NOP_POP, PSEUDO_OP, -1) -OP("nor", Y_NOR_OP, R3_TYPE_INST, 0x00000027) -OP("not", Y_NOT_POP, PSEUDO_OP, -1) -OP("or", Y_OR_OP, R3_TYPE_INST, 0x00000025) -OP("ori", Y_ORI_OP, I2_TYPE_INST, 0x34000000) - -OP("pll.ps", Y_PLL_PS_OP, FP_R3_TYPE_INST, 0x46c0002c) /* MIPS32 Rev 2 */ -OP("plu.ps", Y_PLU_PS_OP, FP_R3_TYPE_INST, 0x46c0002d) /* MIPS32 Rev 2 */ - -OP("pref", Y_PREF_OP, I2_TYPE_INST, 0xcc000000) /* MIPS32 */ -OP("prefx", Y_PREFX_OP, R2st_TYPE_INST, 0x4600000f) /* MIPS32 Rev 2 */ -OP("pul.ps", Y_PUL_PS_OP, FP_R3_TYPE_INST, 0x46c0002e) /* MIPS32 Rev 2 */ -OP("puu.ps", Y_PUU_PS_OP, FP_R3_TYPE_INST, 0x46c0002f) /* MIPS32 Rev 2 */ - -OP("rdhwr", Y_RDHWR_OP, R3_TYPE_INST, 0x7c00003b) /* MIPS32 Rev 2 */ -OP("rdpgpr", Y_RDPGPR_OP, R2td_TYPE_INST, 0x41400000) /* MIPS32 Rev 2 */ - -OP("recip.d", Y_RECIP_D_OP, FP_R2ds_TYPE_INST, 0x46200015) /* MIPS32 Rev 2 */ -OP("recip.s", Y_RECIP_S_OP, FP_R2ds_TYPE_INST, 0x46000015) /* MIPS32 Rev 2 */ - -OP("rem", Y_REM_POP, PSEUDO_OP, -1) -OP("remu", Y_REMU_POP, PSEUDO_OP, -1) - -OP("rfe", Y_RFE_OP, NOARG_TYPE_INST, 0x42000010) - -OP("rol", Y_ROL_POP, PSEUDO_OP, -1) -OP("ror", Y_ROR_POP, PSEUDO_OP, -1) -OP("rotr", Y_ROTR_OP, R2sh_TYPE_INST, 0x00200002) /* MIPS32 Rev 2 */ -OP("rotrv", Y_ROTRV_OP, R2sh_TYPE_INST, 0x00200003) /* MIPS32 Rev 2 */ - -OP("round.l.d", Y_ROUND_L_D_OP, FP_R2ds_TYPE_INST, 0x46200008) /* MIPS32 Rev 2 */ -OP("round.l.s", Y_ROUND_L_S_OP, FP_R2ds_TYPE_INST, 0x46000008) /* MIPS32 Rev 2 */ -OP("round.w.d", Y_ROUND_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000c) /* MIPS32 */ -OP("round.w.s", Y_ROUND_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000c) /* MIPS32 */ - -OP("rsqrt.d", Y_RSQRT_D_OP, FP_R2ds_TYPE_INST, 0x46200016) /* MIPS32 Rev 2 */ -OP("rsqrt.s", Y_RSQRT_S_OP, FP_R2ds_TYPE_INST, 0x46000016) /* MIPS32 Rev 2 */ - -OP("s.d", Y_S_D_POP, PSEUDO_OP, -1) -OP("s.s", Y_S_S_POP, PSEUDO_OP, -1) - -OP("sb", Y_SB_OP, I2a_TYPE_INST, 0xa0000000) -OP("sc", Y_SC_OP, I2a_TYPE_INST, 0xe0000000) /* MIPS32 */ -OP("sd", Y_SD_POP, PSEUDO_OP, -1) -OP("sdbbp", Y_SDBBP_OP, NOARG_TYPE_INST, 0x7000003f) /* MIPS32 Rev 2*/ -OP("sdc1", Y_SDC1_OP, FP_I2a_TYPE_INST, 0xf4000000) /* MIPS32 */ -OP("sdc2", Y_SDC2_OP, I2a_TYPE_INST, 0xf8000000) /* MIPS32 */ -OP("sdxc1", Y_SDXC1_OP, FP_R3_TYPE_INST, 0x46000009) /* MIPS32 Rev 2 */ - -OP("seb", Y_SEB_OP, R2td_TYPE_INST, 0x7c000420) /* MIPS32 Rev 2 */ -OP("seh", Y_SEH_OP, R2td_TYPE_INST, 0x7c000620) /* MIPS32 Rev 2 */ -OP("seq", Y_SEQ_POP, PSEUDO_OP, -1) -OP("sge", Y_SGE_POP, PSEUDO_OP, -1) -OP("sgeu", Y_SGEU_POP, PSEUDO_OP, -1) -OP("sgt", Y_SGT_POP, PSEUDO_OP, -1) -OP("sgtu", Y_SGTU_POP, PSEUDO_OP, -1) - -OP("sh", Y_SH_OP, I2a_TYPE_INST, 0xa4000000) -OP("sle", Y_SLE_POP, PSEUDO_OP, -1) -OP("sleu", Y_SLEU_POP, PSEUDO_OP, -1) -OP("sll", Y_SLL_OP, R2sh_TYPE_INST, 0x00000000) -OP("sllv", Y_SLLV_OP, R3sh_TYPE_INST, 0x00000004) - -OP("slt", Y_SLT_OP, R3_TYPE_INST, 0x0000002a) -OP("slti", Y_SLTI_OP, I2_TYPE_INST, 0x28000000) -OP("sltiu", Y_SLTIU_OP, I2_TYPE_INST, 0x2c000000) -OP("sltu", Y_SLTU_OP, R3_TYPE_INST, 0x0000002b) -OP("sne", Y_SNE_POP, PSEUDO_OP, -1) - -OP("sqrt.d", Y_SQRT_D_OP, FP_R2ds_TYPE_INST, 0x46200004) /* MIPS32 */ -OP("sqrt.s", Y_SQRT_S_OP, FP_R2ds_TYPE_INST, 0x46000004) /* MIPS32 */ - -OP("sra", Y_SRA_OP, R2sh_TYPE_INST, 0x00000003) -OP("srav", Y_SRAV_OP, R3sh_TYPE_INST, 0x00000007) -OP("srl", Y_SRL_OP, R2sh_TYPE_INST, 0x00000002) -OP("srlv", Y_SRLV_OP, R3sh_TYPE_INST, 0x00000006) - -OP("ssnop", Y_SSNOP_OP, R2sh_TYPE_INST, 0x00000040) /* MIPS32 */ - -OP("sub", Y_SUB_OP, R3_TYPE_INST, 0x00000022) -OP("sub.d", Y_SUB_D_OP, FP_R3_TYPE_INST, 0x46200001) -OP("sub.ps", Y_SUB_PS_OP, FP_R3_TYPE_INST, 0x46600001) /* MIPS32 Rev 2 */ -OP("sub.s", Y_SUB_S_OP, FP_R3_TYPE_INST, 0x46000001) -OP("subu", Y_SUBU_OP, R3_TYPE_INST, 0x00000023) - -OP("suxc1", Y_SUXC1_OP, FP_R3_TYPE_INST, 0x4600000d) /* MIPS32 Rev 2 */ - -OP("sw", Y_SW_OP, I2a_TYPE_INST, 0xac000000) -OP("swc1", Y_SWC1_OP, FP_I2a_TYPE_INST, 0xe4000000) -OP("swc2", Y_SWC2_OP, I2a_TYPE_INST, 0xe8000000) -OP("swl", Y_SWL_OP, I2a_TYPE_INST, 0xa8000000) -OP("swr", Y_SWR_OP, I2a_TYPE_INST, 0xb8000000) -OP("swxc1", Y_SWXC1_OP, FP_R3_TYPE_INST, 0x46000008) /* MIPS32 Rev 2 */ - -OP("sync", Y_SYNC_OP, NOARG_TYPE_INST, 0x0000000f) /* MIPS32 */ -OP("synci", Y_SYNCI_OP, I2_TYPE_INST, 0x04140000) /* MIPS32 Rev 2 */ -OP("syscall", Y_SYSCALL_OP, NOARG_TYPE_INST, 0x0000000c) - -OP("teq", Y_TEQ_OP, R2st_TYPE_INST, 0x00000034) /* MIPS32 */ -OP("teqi", Y_TEQI_OP, I1s_TYPE_INST, 0x040c0000) /* MIPS32 */ -OP("tge", Y_TGE_OP, R2st_TYPE_INST, 0x00000030) /* MIPS32 */ -OP("tgei", Y_TGEI_OP, I1s_TYPE_INST, 0x04080000) /* MIPS32 */ -OP("tgeiu", Y_TGEIU_OP, I1s_TYPE_INST, 0x04090000) /* MIPS32 */ -OP("tgeu", Y_TGEU_OP, R2st_TYPE_INST, 0x00000031) /* MIPS32 */ - -OP("tlbp", Y_TLBP_OP, NOARG_TYPE_INST, 0x42000008) -OP("tlbr", Y_TLBR_OP, NOARG_TYPE_INST, 0x42000001) -OP("tlbwi", Y_TLBWI_OP, NOARG_TYPE_INST, 0x42000002) -OP("tlbwr", Y_TLBWR_OP, NOARG_TYPE_INST, 0x42000006) - -OP("tlt", Y_TLT_OP, R2st_TYPE_INST, 0x00000032) /* MIPS32 */ -OP("tlti", Y_TLTI_OP, I1s_TYPE_INST, 0x040a0000) /* MIPS32 */ -OP("tltiu", Y_TLTIU_OP, I1s_TYPE_INST, 0x040b0000) /* MIPS32 */ -OP("tltu", Y_TLTU_OP, R2st_TYPE_INST, 0x00000033) /* MIPS32 */ -OP("tne", Y_TNE_OP, R2st_TYPE_INST, 0x00000036) /* MIPS32 */ -OP("tnei", Y_TNEI_OP, I1s_TYPE_INST, 0x040e0000) /* MIPS32 */ - -OP("trunc.l.d", Y_TRUNC_L_D_OP, FP_R2ds_TYPE_INST, 0x46200009) /* MIPS32 Rev 2 */ -OP("trunc.l.s", Y_TRUNC_L_S_OP, FP_R2ds_TYPE_INST, 0x46000009) /* MIPS32 Rev 2 */ -OP("trunc.w.d", Y_TRUNC_W_D_OP, FP_R2ds_TYPE_INST, 0x4620000d) /* MIPS32 */ -OP("trunc.w.s", Y_TRUNC_W_S_OP, FP_R2ds_TYPE_INST, 0x4600000d) /* MIPS32 */ - -OP("ulh", Y_ULH_POP, PSEUDO_OP, -1) -OP("ulhu", Y_ULHU_POP, PSEUDO_OP, -1) -OP("ulw", Y_ULW_POP, PSEUDO_OP, -1) -OP("ush", Y_USH_POP, PSEUDO_OP, -1) -OP("usw", Y_USW_POP, PSEUDO_OP, -1) - -OP("wrpgpr", Y_WRPGPR_OP, R2td_TYPE_INST, 0x41c00000) /* MIPS32 Rev 2 */ -OP("wsbh", Y_WSBH_OP, R2td_TYPE_INST, 0x7c0000a0) /* MIPS32 Rev 2 */ - -OP("xor", Y_XOR_OP, R3_TYPE_INST, 0x00000026) -OP("xori", Y_XORI_OP, I2_TYPE_INST, 0x38000000) diff --git a/spim-qtspimbot/CPU/parser.h b/spim-qtspimbot/CPU/parser.h deleted file mode 100755 index 0e120f8..0000000 --- a/spim-qtspimbot/CPU/parser.h +++ /dev/null @@ -1,50 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to parser for instructions and assembler directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -void fix_current_label_address (mem_addr new_addr); -int imm_op_to_op (int opcode); -void initialize_parser (char *file_name); -int op_to_imm_op (int opcode); -void yyerror (char *s); -int yyparse (); - - -/* Exported Variables: */ - -extern bool data_dir; /* => item in data segment */ - -extern bool text_dir; /* => item in text segment */ - -extern bool parse_error_occurred; /* => parse resulted in error */ diff --git a/spim-qtspimbot/CPU/parser.y b/spim-qtspimbot/CPU/parser.y deleted file mode 100755 index 62b98c5..0000000 --- a/spim-qtspimbot/CPU/parser.y +++ /dev/null @@ -1,2957 +0,0 @@ -/* SPIM S20 MIPS simulator. - Parser for instructions and assembler directives. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -%expect 25 /* Supress warning about 25 shift-reduce conflicts */ - -%start LINE - -%token Y_EOF - -%token Y_NL -%token Y_INT -%token Y_ID -%token Y_REG -%token Y_FP_REG -%token Y_STR -%token Y_FP - -/* MIPS instructions op codes: */ - -%token Y_ABS_D_OP -%token Y_ABS_PS_OP -%token Y_ABS_S_OP -%token Y_ADD_D_OP -%token Y_ADD_OP -%token Y_ADD_PS_OP -%token Y_ADD_S_OP -%token Y_ADDI_OP -%token Y_ADDIU_OP -%token Y_ADDU_OP -%token Y_ALNV_PS_OP -%token Y_AND_OP -%token Y_ANDI_OP -%token Y_BC1F_OP -%token Y_BC1FL_OP -%token Y_BC1T_OP -%token Y_BC1TL_OP -%token Y_BC2F_OP -%token Y_BC2FL_OP -%token Y_BC2T_OP -%token Y_BC2TL_OP -%token Y_BEQ_OP -%token Y_BEQL_OP -%token Y_BGEZ_OP -%token Y_BGEZAL_OP -%token Y_BGEZALL_OP -%token Y_BGEZL_OP -%token Y_BGTZ_OP -%token Y_BGTZL_OP -%token Y_BLEZ_OP -%token Y_BLEZL_OP -%token Y_BLTZ_OP -%token Y_BLTZAL_OP -%token Y_BLTZALL_OP -%token Y_BLTZL_OP -%token Y_BNE_OP -%token Y_BNEL_OP -%token Y_BREAK_OP -%token Y_C_EQ_D_OP -%token Y_C_EQ_PS_OP -%token Y_C_EQ_S_OP -%token Y_C_F_D_OP -%token Y_C_F_PS_OP -%token Y_C_F_S_OP -%token Y_C_LE_D_OP -%token Y_C_LE_PS_OP -%token Y_C_LE_S_OP -%token Y_C_LT_D_OP -%token Y_C_LT_PS_OP -%token Y_C_LT_S_OP -%token Y_C_NGE_D_OP -%token Y_C_NGE_PS_OP -%token Y_C_NGE_S_OP -%token Y_C_NGL_D_OP -%token Y_C_NGL_PS_OP -%token Y_C_NGL_S_OP -%token Y_C_NGLE_D_OP -%token Y_C_NGLE_PS_OP -%token Y_C_NGLE_S_OP -%token Y_C_NGT_D_OP -%token Y_C_NGT_PS_OP -%token Y_C_NGT_S_OP -%token Y_C_OLE_D_OP -%token Y_C_OLE_PS_OP -%token Y_C_OLE_S_OP -%token Y_C_OLT_D_OP -%token Y_C_OLT_PS_OP -%token Y_C_OLT_S_OP -%token Y_C_SEQ_D_OP -%token Y_C_SEQ_PS_OP -%token Y_C_SEQ_S_OP -%token Y_C_SF_D_OP -%token Y_C_SF_PS_OP -%token Y_C_SF_S_OP -%token Y_C_UEQ_D_OP -%token Y_C_UEQ_PS_OP -%token Y_C_UEQ_S_OP -%token Y_C_ULE_D_OP -%token Y_C_ULE_PS_OP -%token Y_C_ULE_S_OP -%token Y_C_ULT_D_OP -%token Y_C_ULT_PS_OP -%token Y_C_ULT_S_OP -%token Y_C_UN_D_OP -%token Y_C_UN_PS_OP -%token Y_C_UN_S_OP -%token Y_CACHE_OP -%token Y_CEIL_L_D_OP -%token Y_CEIL_L_S_OP -%token Y_CEIL_W_D_OP -%token Y_CEIL_W_S_OP -%token Y_CFC0_OP -%token Y_CFC1_OP -%token Y_CFC2_OP -%token Y_CLO_OP -%token Y_CLZ_OP -%token Y_COP2_OP -%token Y_CTC0_OP -%token Y_CTC1_OP -%token Y_CTC2_OP -%token Y_CVT_D_L_OP -%token Y_CVT_D_S_OP -%token Y_CVT_D_W_OP -%token Y_CVT_L_D_OP -%token Y_CVT_L_S_OP -%token Y_CVT_PS_S_OP -%token Y_CVT_S_D_OP -%token Y_CVT_S_L_OP -%token Y_CVT_S_PL_OP -%token Y_CVT_S_PU_OP -%token Y_CVT_S_W_OP -%token Y_CVT_W_D_OP -%token Y_CVT_W_S_OP -%token Y_DERET_OP -%token Y_DI_OP -%token Y_DIV_D_OP -%token Y_DIV_OP -%token Y_DIV_S_OP -%token Y_DIVU_OP -%token Y_EHB_OP -%token Y_EI_OP -%token Y_ERET_OP -%token Y_EXT_OP -%token Y_FLOOR_L_D_OP -%token Y_FLOOR_L_S_OP -%token Y_FLOOR_W_D_OP -%token Y_FLOOR_W_S_OP -%token Y_INS_OP -%token Y_J_OP -%token Y_JAL_OP -%token Y_JALR_HB_OP -%token Y_JALR_OP -%token Y_JR_HB_OP -%token Y_JR_OP -%token Y_LB_OP -%token Y_LBU_OP -%token Y_LDC1_OP -%token Y_LDC2_OP -%token Y_LDXC1_OP -%token Y_LH_OP -%token Y_LHU_OP -%token Y_LL_OP -%token Y_LUI_OP -%token Y_LUXC1_OP -%token Y_LW_OP -%token Y_LWC1_OP -%token Y_LWC2_OP -%token Y_LWL_OP -%token Y_LWR_OP -%token Y_LWXC1_OP -%token Y_MADD_D_OP -%token Y_MADD_OP -%token Y_MADD_PS_OP -%token Y_MADD_S_OP -%token Y_MADDU_OP -%token Y_MFC0_OP -%token Y_MFC1_OP -%token Y_MFC2_OP -%token Y_MFHC1_OP -%token Y_MFHC2_OP -%token Y_MFHI_OP -%token Y_MFLO_OP -%token Y_MOV_D_OP -%token Y_MOV_PS_OP -%token Y_MOV_S_OP -%token Y_MOVF_D_OP -%token Y_MOVF_OP -%token Y_MOVF_PS_OP -%token Y_MOVF_S_OP -%token Y_MOVN_D_OP -%token Y_MOVN_OP -%token Y_MOVN_PS_OP -%token Y_MOVN_S_OP -%token Y_MOVT_D_OP -%token Y_MOVT_OP -%token Y_MOVT_PS_OP -%token Y_MOVT_S_OP -%token Y_MOVZ_D_OP -%token Y_MOVZ_OP -%token Y_MOVZ_PS_OP -%token Y_MOVZ_S_OP -%token Y_MSUB_D_OP -%token Y_MSUB_OP -%token Y_MSUB_PS_OP -%token Y_MSUB_S_OP -%token Y_MSUBU_OP -%token Y_MTC0_OP -%token Y_MTC1_OP -%token Y_MTC2_OP -%token Y_MTHC1_OP -%token Y_MTHC2_OP -%token Y_MTHI_OP -%token Y_MTLO_OP -%token Y_MUL_D_OP -%token Y_MUL_PS_OP -%token Y_MUL_S_OP -%token Y_MUL_OP -%token Y_MULT_OP -%token Y_MULTU_OP -%token Y_NEG_D_OP -%token Y_NEG_PS_OP -%token Y_NEG_S_OP -%token Y_NMADD_D_OP -%token Y_NMADD_PS_OP -%token Y_NMADD_S_OP -%token Y_NMSUB_D_OP -%token Y_NMSUB_PS_OP -%token Y_NMSUB_S_OP -%token Y_NOR_OP -%token Y_OR_OP -%token Y_ORI_OP -%token Y_PFW_OP -%token Y_PLL_PS_OP -%token Y_PLU_PS_OP -%token Y_PREF_OP -%token Y_PREFX_OP -%token Y_PUL_PS_OP -%token Y_PUU_PS_OP -%token Y_RDHWR_OP -%token Y_RDPGPR_OP -%token Y_RECIP_D_OP -%token Y_RECIP_S_OP -%token Y_RFE_OP -%token Y_ROTR_OP -%token Y_ROTRV_OP -%token Y_ROUND_L_D_OP -%token Y_ROUND_L_S_OP -%token Y_ROUND_W_D_OP -%token Y_ROUND_W_S_OP -%token Y_RSQRT_D_OP -%token Y_RSQRT_S_OP -%token Y_SB_OP -%token Y_SC_OP -%token Y_SDBBP_OP -%token Y_SDC1_OP -%token Y_SDC2_OP -%token Y_SDXC1_OP -%token Y_SEB_OP -%token Y_SEH_OP -%token Y_SH_OP -%token Y_SLL_OP -%token Y_SLLV_OP -%token Y_SLT_OP -%token Y_SLTI_OP -%token Y_SLTIU_OP -%token Y_SLTU_OP -%token Y_SQRT_D_OP -%token Y_SQRT_S_OP -%token Y_SRA_OP -%token Y_SRAV_OP -%token Y_SRL_OP -%token Y_SRLV_OP -%token Y_SSNOP_OP -%token Y_SUB_D_OP -%token Y_SUB_OP -%token Y_SUB_PS_OP -%token Y_SUB_S_OP -%token Y_SUBU_OP -%token Y_SUXC1_OP -%token Y_SW_OP -%token Y_SWC1_OP -%token Y_SWC2_OP -%token Y_SWL_OP -%token Y_SWR_OP -%token Y_SWXC1_OP -%token Y_SYNC_OP -%token Y_SYNCI_OP -%token Y_SYSCALL_OP -%token Y_TEQ_OP -%token Y_TEQI_OP -%token Y_TGE_OP -%token Y_TGEI_OP -%token Y_TGEIU_OP -%token Y_TGEU_OP -%token Y_TLBP_OP -%token Y_TLBR_OP -%token Y_TLBWI_OP -%token Y_TLBWR_OP -%token Y_TLT_OP -%token Y_TLTI_OP -%token Y_TLTIU_OP -%token Y_TLTU_OP -%token Y_TNE_OP -%token Y_TNEI_OP -%token Y_TRUNC_L_D_OP -%token Y_TRUNC_L_S_OP -%token Y_TRUNC_W_D_OP -%token Y_TRUNC_W_S_OP -%token Y_WRPGPR_OP -%token Y_WSBH_OP -%token Y_XOR_OP -%token Y_XORI_OP - - -/* Assembler pseudo operations op codes: */ - -%token Y_ABS_POP -%token Y_B_POP -%token Y_BAL_POP -%token Y_BEQZ_POP -%token Y_BGE_POP -%token Y_BGEU_POP -%token Y_BGT_POP -%token Y_BGTU_POP -%token Y_BLE_POP -%token Y_BLEU_POP -%token Y_BLT_POP -%token Y_BLTU_POP -%token Y_BNEZ_POP -%token Y_LA_POP -%token Y_LD_POP -%token Y_L_D_POP -%token Y_L_S_POP -%token Y_LI_D_POP -%token Y_LI_POP -%token Y_LI_S_POP -%token Y_MFC1_D_POP -%token Y_MOVE_POP -%token Y_MTC1_D_POP -%token Y_MULO_POP -%token Y_MULOU_POP -%token Y_NEG_POP -%token Y_NEGU_POP -%token Y_NOP_POP -%token Y_NOT_POP -%token Y_REM_POP -%token Y_REMU_POP -%token Y_ROL_POP -%token Y_ROR_POP -%token Y_S_D_POP -%token Y_S_S_POP -%token Y_SD_POP -%token Y_SEQ_POP -%token Y_SGE_POP -%token Y_SGEU_POP -%token Y_SGT_POP -%token Y_SGTU_POP -%token Y_SLE_POP -%token Y_SLEU_POP -%token Y_SNE_POP -%token Y_ULH_POP -%token Y_ULHU_POP -%token Y_ULW_POP -%token Y_USH_POP -%token Y_USW_POP - -/* Assembler directives: */ - -%token Y_ALIAS_DIR -%token Y_ALIGN_DIR -%token Y_ASCII_DIR -%token Y_ASCIIZ_DIR -%token Y_ASM0_DIR -%token Y_BGNB_DIR -%token Y_BYTE_DIR -%token Y_COMM_DIR -%token Y_DATA_DIR -%token Y_DOUBLE_DIR -%token Y_END_DIR -%token Y_ENDB_DIR -%token Y_ENDR_DIR -%token Y_ENT_DIR -%token Y_ERR_DIR -%token Y_EXTERN_DIR -%token Y_FILE_DIR -%token Y_FLOAT_DIR -%token Y_FMASK_DIR -%token Y_FRAME_DIR -%token Y_GLOBAL_DIR -%token Y_HALF_DIR -%token Y_K_DATA_DIR -%token Y_K_TEXT_DIR -%token Y_LABEL_DIR -%token Y_LCOMM_DIR -%token Y_LIVEREG_DIR -%token Y_LOC_DIR -%token Y_MASK_DIR -%token Y_NOALIAS_DIR -%token Y_OPTIONS_DIR -%token Y_RDATA_DIR -%token Y_REPEAT_DIR -%token Y_SDATA_DIR -%token Y_SET_DIR -%token Y_SPACE_DIR -%token Y_STRUCT_DIR -%token Y_TEXT_DIR -%token Y_VERSTAMP_DIR -%token Y_VREG_DIR -%token Y_WORD_DIR - -%{ -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "data.h" -#include "scanner.h" -#include "parser.h" - -#define YYDEBUG 1 - -/* return (0) */ -#define LINE_PARSE_DONE YYACCEPT - -/* return (1) */ -#define FILE_PARSE_DONE YYABORT - -typedef struct ll -{ - label *head; - struct ll *tail; -} label_list; - - -/* Exported Variables: */ - -bool data_dir; /* => item in data segment */ - -bool text_dir; /* => item in text segment */ - -bool parse_error_occurred; /* => parse resulted in error */ - - -/* Local functions: */ - -static imm_expr *branch_offset (int n_inst); -static int cc_to_rt (int cc, int nd, int tf); -static void check_imm_range (imm_expr*, int32, int32); -static void check_uimm_range (imm_expr*, uint32, uint32); -static void clear_labels (); -static label_list *cons_label (label *head, label_list *tail); -static void div_inst (int op, int rd, int rs, int rt, int const_divisor); -static void mips32_r2_inst (); -static void mult_inst (int op, int rd, int rs, int rt); -static void nop_inst (); -static void set_eq_inst (int op, int rd, int rs, int rt); -static void set_ge_inst (int op, int rd, int rs, int rt); -static void set_gt_inst (int op, int rd, int rs, int rt); -static void set_le_inst (int op, int rd, int rs, int rt); -static void store_word_data (int value); -static void trap_inst (); -static void yywarn (char*); - - -/* Local variables: */ - -static bool null_term; /* => string terminate by \0 */ - -static void (*store_op) (void*); /* Function to store items in an EXPR_LST */ - -static label_list *this_line_labels = NULL; /* List of label for curent line */ - -static bool noat_flag = 0; /* => program can use $1 */ - -static char *input_file_name; /* Name of file being parsed */ - -%} - - - -%% - -LINE: {parse_error_occurred = false; scanner_start_line (); } LBL_CMD ; - -LBL_CMD: OPT_LBL CMD - | CMD - ; - - -OPT_LBL: ID ':' { - /* Call outside of cons_label, since an error sets that variable to NULL. */ - label* l = record_label ((char*)$1.p, - text_dir ? current_text_pc () : current_data_pc (), - 0); - this_line_labels = cons_label (l, this_line_labels); - free ((char*)$1.p); - } - - | ID '=' EXPR - { - label *l = record_label ((char*)$1.p, (mem_addr)$3.i, 1); - free ((char*)$1.p); - - l->const_flag = 1; - clear_labels (); - } - ; - - -CMD: ASM_CODE - { - clear_labels (); - } - TERM - - | ASM_DIRECTIVE - { - clear_labels (); - } - TERM - - | TERM - ; - - -TERM: Y_NL - { - LINE_PARSE_DONE; - } - - | Y_EOF - { - clear_labels (); - FILE_PARSE_DONE; - } - ; - - - -ASM_CODE: LOAD_OPS DEST ADDRESS - { - i_type_inst ($1.i == Y_LD_POP ? Y_LW_OP : $1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - if ($1.i == Y_LD_POP) - i_type_inst_free (Y_LW_OP, - $2.i + 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 4)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADC_OPS COP_REG ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADFP_OPS F_SRC1 ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - | LOADI_OPS DEST UIMM16 - { - i_type_inst_free ($1.i, $2.i, 0, (imm_expr *)$3.p); - } - - - | Y_LA_POP DEST ADDRESS - { - if (addr_expr_reg ((addr_expr *)$3.p)) - i_type_inst (Y_ADDI_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - else - i_type_inst (Y_ORI_OP, $2.i, 0, - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_LI_POP DEST IMM32 - { - i_type_inst_free (Y_ORI_OP, $2.i, 0, (imm_expr *)$3.p); - } - - - | Y_LI_D_POP F_DEST Y_FP - { - int *x = (int *) $3.p; - - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*x)); - r_co_type_inst (Y_MTC1_OP, 0, $2.i, 1); - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*(x+1))); - r_co_type_inst (Y_MTC1_OP, 0, $2.i + 1, 1); - } - - - | Y_LI_S_POP F_DEST Y_FP - { - float x = (float) *((double *) $3.p); - int *y = (int *) &x; - - i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*y)); - r_co_type_inst (Y_MTC1_OP, 0, $2.i, 1); - } - - - | Y_ULW_POP DEST ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (Y_LWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_LWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); -#else - i_type_inst_free (Y_LWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); - i_type_inst (Y_LWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | ULOADH_POPS DEST ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (($1.i == Y_ULH_POP ? Y_LB_OP : Y_LBU_OP), - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_LBU_OP, 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); -#else - i_type_inst_free (($1.i == Y_ULH_POP ? Y_LB_OP : Y_LBU_OP), - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); - i_type_inst (Y_LBU_OP, 1, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - r_sh_type_inst (Y_SLL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | LOADFP_INDEX_OPS F_DEST ADDRESS - { - mips32_r2_inst (); - } - - - | STORE_OPS SRC1 ADDRESS - { - i_type_inst ($1.i == Y_SD_POP ? Y_SW_OP : $1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - if ($1.i == Y_SD_POP) - i_type_inst_free (Y_SW_OP, $2.i + 1, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 4)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREC_OPS COP_REG ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_USW_POP SRC1 ADDRESS - { -#ifdef SPIM_BIGENDIAN - i_type_inst (Y_SWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - i_type_inst_free (Y_SWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); -#else - i_type_inst_free (Y_SWL_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 3)); - i_type_inst (Y_SWR_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); -#endif - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | Y_USH_POP SRC1 ADDRESS - { - i_type_inst (Y_SB_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - - /* ROL SRC, SRC, 8 */ - r_sh_type_inst (Y_SLL_OP, 1, $2.i, 24); - r_sh_type_inst (Y_SRL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - - i_type_inst_free (Y_SB_OP, $2.i, - addr_expr_reg ((addr_expr *)$3.p), - incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), - 1)); - /* ROR SRC, SRC, 8 */ - r_sh_type_inst (Y_SRL_OP, 1, $2.i, 24); - r_sh_type_inst (Y_SLL_OP, $2.i, $2.i, 8); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREFP_OPS F_SRC1 ADDRESS - { - i_type_inst ($1.i, - $2.i, - addr_expr_reg ((addr_expr *)$3.p), - addr_expr_imm ((addr_expr *)$3.p)); - free (((addr_expr *)$3.p)->imm); - free ((addr_expr *)$3.p); - } - - - | STOREFP_INDEX_OPS F_DEST ADDRESS - { - mips32_r2_inst (); - } - - - | SYS_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | PREFETCH_OPS ADDRESS - { - mips32_r2_inst (); - } - - - | CACHE_OPS Y_INT ADDRESS - { - i_type_inst_free ($1.i, $2.i, 0, (imm_expr *)$3.p); - } - - - | TLB_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | Y_SYNC_OP - { - r_type_inst ($1.i, 0, 0, 0); - } - - | Y_SYNC_OP Y_INT - { - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | Y_BREAK_OP Y_INT - { - if ($2.i == 1) - yyerror ("Breakpoint 1 is reserved for debugger"); - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | Y_NOP_POP - { - nop_inst (); - } - - - | Y_SSNOP_OP - { - r_sh_type_inst (Y_SLL_OP, 0, 0, 1); /* SLL r0 r0 1 */ - } - - - | Y_ABS_POP DEST SRC1 - { - if ($2.i != $3.i) - r_type_inst (Y_ADDU_OP, $2.i, 0, $3.i); - - i_type_inst_free (Y_BGEZ_OP, 0, $3.i, branch_offset (2)); - r_type_inst (Y_SUB_OP, $2.i, 0, $3.i); - } - - - | Y_NEG_POP DEST SRC1 - { - r_type_inst (Y_SUB_OP, $2.i, 0, $3.i); - } - - - | Y_NEGU_POP DEST SRC1 - { - r_type_inst (Y_SUBU_OP, $2.i, 0, $3.i); - } - - - | Y_NOT_POP DEST SRC1 - { - r_type_inst (Y_NOR_OP, $2.i, $3.i, 0); - } - - - | Y_MOVE_POP DEST SRC1 - { - r_type_inst (Y_ADDU_OP, $2.i, 0, $3.i); - } - - - | NULLARY_OPS - { - r_type_inst ($1.i, 0, 0, 0); - } - - - | NULLARY_OPS_REV2 - { - mips32_r2_inst (); - } - - - | COUNT_LEADING_OPS DEST SRC1 - { - /* RT must be equal to RD */ - r_type_inst ($1.i, $2.i, $3.i, $2.i); - } - - - | UNARY_OPS_REV2 DEST - { - mips32_r2_inst (); - } - - - | BINARYI_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | BINARYI_OPS DEST SRC1 IMM32 - { - i_type_inst_free (op_to_imm_op ($1.i), $2.i, $3.i, - (imm_expr *)$4.p); - } - - | BINARYI_OPS DEST IMM32 - { - i_type_inst_free (op_to_imm_op ($1.i), $2.i, $2.i, - (imm_expr *)$3.p); - } - - - | BINARYIR_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $4.i, $3.i); - } - - | BINARYIR_OPS DEST SRC1 Y_INT - { - r_sh_type_inst (op_to_imm_op ($1.i), $2.i, $3.i, $4.i); - } - - | BINARYIR_OPS DEST Y_INT - { - r_sh_type_inst (op_to_imm_op ($1.i), $2.i, $2.i, $3.i); - } - - - | BINARY_ARITHI_OPS DEST SRC1 IMM16 - { - i_type_inst_free ($1.i, $2.i, $3.i, (imm_expr *)$4.p); - } - - | BINARY_ARITHI_OPS DEST IMM16 - { - i_type_inst_free ($1.i, $2.i, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_LOGICALI_OPS DEST SRC1 UIMM16 - { - i_type_inst_free ($1.i, $2.i, $3.i, (imm_expr *)$4.p); - } - - | BINARY_LOGICALI_OPS DEST UIMM16 - { - i_type_inst_free ($1.i, $2.i, $2.i, (imm_expr *)$3.p); - } - - - | SHIFT_OPS DEST SRC1 Y_INT - { - if (($4.i < 0) || (31 < $4.i)) - yywarn ("Shift distance can only be in the range 0..31"); - r_sh_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SHIFT_OPS DEST SRC1 SRC2 - { - r_type_inst (imm_op_to_op ($1.i), $2.i, $4.i, $3.i); - } - - - | SHIFT_OPS_REV2 DEST SRC1 Y_INT - { - mips32_r2_inst (); - } - - | SHIFTV_OPS_REV2 DEST SRC1 SRC2 - { - mips32_r2_inst (); - } - - - | BINARY_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | BINARY_OPS DEST SRC1 IMM32 - { - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - r_type_inst ($1.i, - $2.i, - $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - } - free ((imm_expr *)$4.p); - } - - | BINARY_OPS DEST IMM32 - { - check_uimm_range ((imm_expr *)$3.p, UIMM_MIN, UIMM_MAX); - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (!is_zero_imm ((imm_expr *)$3.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - r_type_inst ($1.i, - $2.i, - $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1)); - } - free ((imm_expr *)$3.p); - } - - - | BINARY_OPS_REV2 DEST SRC1 - { - mips32_r2_inst (); - } - - - | SUB_OPS DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SUB_OPS DEST SRC1 IMM32 - { - int val = eval_imm_expr ((imm_expr *)$4.p); - - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - i_type_inst ($1.i == Y_SUB_OP ? Y_ADDI_OP - : $1.i == Y_SUBU_OP ? Y_ADDIU_OP - : (fatal_error ("Bad SUB_OP\n"), 0), - $2.i, - $3.i, - make_imm_expr (-val, NULL, false)); - free ((imm_expr *)$4.p); - } - - | SUB_OPS DEST IMM32 - { - int val = eval_imm_expr ((imm_expr *)$3.p); - - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - i_type_inst ($1.i == Y_SUB_OP ? Y_ADDI_OP - : $1.i == Y_SUBU_OP ? Y_ADDIU_OP - : (fatal_error ("Bad SUB_OP\n"), 0), - $2.i, - $2.i, - make_imm_expr (-val, NULL, false)); - free ((imm_expr *)$3.p); - } - - - | DIV_POPS DEST SRC1 - { - /* The hardware divide operation (ignore 1st arg) */ - if ($1.i != Y_DIV_OP && $1.i != Y_DIVU_OP) - yyerror ("REM requires 3 arguments"); - else - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - | DIV_POPS DEST SRC1 SRC2 - { - /* Pseudo divide operations */ - div_inst ($1.i, $2.i, $3.i, $4.i, 0); - } - - | DIV_POPS DEST SRC1 IMM32 - { - if (is_zero_imm ((imm_expr *)$4.p)) - yyerror ("Divide by zero"); - else - { - /* Use $at */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - div_inst ($1.i, $2.i, $3.i, 1, 1); - } - } - - - | MUL_POPS DEST SRC1 SRC2 - { - mult_inst ($1.i, $2.i, $3.i, $4.i); - } - - | MUL_POPS DEST SRC1 IMM32 - { - if (is_zero_imm ((imm_expr *)$4.p)) - /* Optimize: n * 0 == 0 */ - i_type_inst_free (Y_ORI_OP, $2.i, 0, (imm_expr *)$4.p); - else - { - /* Use $at */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - mult_inst ($1.i, $2.i, $3.i, 1); - } - } - - - | MULT_OPS SRC1 SRC2 - { - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - - | MULT_OPS3 DEST SRC1 SRC2 - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - | MULT_OPS3 DEST SRC1 IMM32 - { - /* Special case, for backward compatibility with pseudo-op - MULT instruction */ - i_type_inst_free (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); /* Use $at */ - r_type_inst ($1.i, $2.i, $3.i, 1); - } - - - | Y_ROR_POP DEST SRC1 SRC2 - { - r_type_inst (Y_SUBU_OP, 1, 0, $4.i); - r_type_inst (Y_SLLV_OP, 1, 1, $3.i); - r_type_inst (Y_SRLV_OP, $2.i, $4.i, $3.i); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - } - - - | Y_ROL_POP DEST SRC1 SRC2 - { - r_type_inst (Y_SUBU_OP, 1, 0, $4.i); - r_type_inst (Y_SRLV_OP, 1, 1, $3.i); - r_type_inst (Y_SLLV_OP, $2.i, $4.i, $3.i); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - } - - - | Y_ROR_POP DEST SRC1 IMM32 - { - long dist = eval_imm_expr ((imm_expr *)$4.p); - - check_imm_range ((imm_expr *)$4.p, 0, 31); - r_sh_type_inst (Y_SLL_OP, 1, $3.i, -dist); - r_sh_type_inst (Y_SRL_OP, $2.i, $3.i, dist); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free ((imm_expr *)$4.p); - } - - - | Y_ROL_POP DEST SRC1 IMM32 - { - long dist = eval_imm_expr ((imm_expr *)$4.p); - - check_imm_range ((imm_expr *)$4.p, 0, 31); - r_sh_type_inst (Y_SRL_OP, 1, $3.i, -dist); - r_sh_type_inst (Y_SLL_OP, $2.i, $3.i, dist); - r_type_inst (Y_OR_OP, $2.i, $2.i, 1); - free ((imm_expr *)$4.p); - } - - - | BF_OPS_REV2 F_DEST F_SRC2 Y_INT Y_INT - { - mips32_r2_inst (); - } - - - | SET_LE_POPS DEST SRC1 SRC2 - { - set_le_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_LE_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_le_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | SET_GT_POPS DEST SRC1 SRC2 - { - set_gt_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_GT_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_gt_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - - | SET_GE_POPS DEST SRC1 SRC2 - { - set_ge_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_GE_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_ge_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | SET_EQ_POPS DEST SRC1 SRC2 - { - set_eq_inst ($1.i, $2.i, $3.i, $4.i); - } - - | SET_EQ_POPS DEST SRC1 IMM32 - { - if (!is_zero_imm ((imm_expr *)$4.p)) - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$4.p); - set_eq_inst ($1.i, $2.i, $3.i, - (is_zero_imm ((imm_expr *)$4.p) ? 0 : 1)); - free ((imm_expr *)$4.p); - } - - - | BR_COP_OPS LABEL - { - /* RS and RT fields contain information on test */ - int nd = opcode_is_nullified_branch ($1.i) ? 1 : 0; - int tf = opcode_is_true_branch ($1.i) ? 1 : 0; - i_type_inst_free ($1.i, - cc_to_rt (0, nd, tf), - BIN_RS ($1.i), - (imm_expr *)$2.p); - } - - | BR_COP_OPS CC_REG LABEL - { - /* RS and RT fields contain information on test */ - int nd = opcode_is_nullified_branch ($1.i) ? 1 : 0; - int tf = opcode_is_true_branch ($1.i) ? 1 : 0; - i_type_inst_free ($1.i, - cc_to_rt ($2.i, nd, tf), - BIN_RS ($1.i), - (imm_expr *)$3.p); - } - - - | UNARY_BR_OPS SRC1 LABEL - { - i_type_inst_free ($1.i, 0, $2.i, (imm_expr *)$3.p); - } - - - | UNARY_BR_POPS SRC1 LABEL - { - i_type_inst_free ($1.i == Y_BEQZ_POP ? Y_BEQ_OP : Y_BNE_OP, - 0, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_BR_OPS SRC1 SRC2 LABEL - { - i_type_inst_free ($1.i, $3.i, $2.i, (imm_expr *)$4.p); - } - - | BINARY_BR_OPS SRC1 BR_IMM32 LABEL - { - if (bare_machine && !accept_pseudo_insts) - yyerror ("Immediate form not allowed in bare machine"); - else - { - if (is_zero_imm ((imm_expr *)$3.p)) - i_type_inst ($1.i, $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1), - (imm_expr *)$4.p); - else - { - /* Use $at */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst ($1.i, $2.i, - (is_zero_imm ((imm_expr *)$3.p) ? 0 : 1), - (imm_expr *)$4.p); - } - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | BR_GT_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BGT_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $3.i, $2.i); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_GT_POPS SRC1 BR_IMM32 LABEL - { - if ($1.i == Y_BGT_POP) - { - /* Use $at */ - i_type_inst_free (Y_SLTI_OP, 1, $2.i, - incr_expr_offset ((imm_expr *)$3.p, 1)); - i_type_inst (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - else - { - /* Use $at */ - /* Can't add 1 to immediate since 0xffffffff+1 = 0 < 1 */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst_free (Y_BEQ_OP, $2.i, 1, branch_offset (3)); - r_type_inst (Y_SLTU_OP, 1, $2.i, 1); - i_type_inst (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | BR_GE_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BGE_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $2.i, $3.i); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_GE_POPS SRC1 BR_IMM32 LABEL - { - i_type_inst ($1.i == Y_BGE_POP ? Y_SLTI_OP : Y_SLTIU_OP, - 1, $2.i, (imm_expr *)$3.p); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - free ((imm_expr *)$3.p); - } - - - | BR_LT_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BLT_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $2.i, $3.i); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_LT_POPS SRC1 BR_IMM32 LABEL - { - i_type_inst ($1.i == Y_BLT_POP ? Y_SLTI_OP : Y_SLTIU_OP, - 1, $2.i, (imm_expr *)$3.p); /* Use $at */ - i_type_inst_free (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - free ((imm_expr *)$3.p); - } - - - | BR_LE_POPS SRC1 SRC2 LABEL - { - r_type_inst ($1.i == Y_BLE_POP ? Y_SLT_OP : Y_SLTU_OP, - 1, $3.i, $2.i); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, (imm_expr *)$4.p); - } - - | BR_LE_POPS SRC1 BR_IMM32 LABEL - { - if ($1.i == Y_BLE_POP) - { - /* Use $at */ - i_type_inst_free (Y_SLTI_OP, 1, $2.i, - incr_expr_offset ((imm_expr *)$3.p, 1)); - i_type_inst (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - else - { - /* Use $at */ - /* Can't add 1 to immediate since 0xffffffff+1 = 0 < 1 */ - i_type_inst (Y_ORI_OP, 1, 0, (imm_expr *)$3.p); - i_type_inst (Y_BEQ_OP, $2.i, 1, (imm_expr *)$4.p); - r_type_inst (Y_SLTU_OP, 1, $2.i, 1); - i_type_inst (Y_BNE_OP, 0, 1, (imm_expr *)$4.p); - } - free ((imm_expr *)$3.p); - free ((imm_expr *)$4.p); - } - - - | J_OPS LABEL - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - j_type_inst (Y_J_OP, (imm_expr *)$2.p); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - j_type_inst (Y_JAL_OP, (imm_expr *)$2.p); - free ((imm_expr *)$2.p); - } - - | J_OPS SRC1 - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - r_type_inst (Y_JR_OP, 0, $2.i, 0); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - r_type_inst (Y_JALR_OP, 31, $2.i, 0); - } - - | J_OPS DEST SRC1 - { - if (($1.i == Y_J_OP) || ($1.i == Y_JR_OP)) - r_type_inst (Y_JR_OP, 0, $3.i, 0); - else if (($1.i == Y_JAL_OP) || ($1.i == Y_JALR_OP)) - r_type_inst (Y_JALR_OP, $2.i, $3.i, 0); - } - - - | B_OPS LABEL - { - i_type_inst_free (($1.i == Y_BAL_POP ? Y_BGEZAL_OP : Y_BGEZ_OP), - 0, 0, (imm_expr *)$2.p); - } - - - | BINARYI_TRAP_OPS SRC1 IMM16 - { - i_type_inst_free ($1.i, 0, $2.i, (imm_expr *)$3.p); - } - - - | BINARY_TRAP_OPS SRC1 SRC2 - { - r_type_inst ($1.i, 0, $2.i, $3.i); - } - - - | FP_MOVE_OPS F_DEST F_SRC1 - { - r_co_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_MOVE_OPS_REV2 F_DEST F_SRC1 - { - mips32_r2_inst (); - } - - - | MOVEC_OPS DEST SRC1 REG - { - r_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | MOVECC_OPS DEST SRC1 Y_INT - { - r_type_inst ($1.i, - $2.i, - $3.i, - (($4.i & 0x7) << 2)); - } - - - | FP_MOVEC_OPS F_DEST F_SRC1 REG - { - r_co_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | FP_MOVEC_OPS_REV2 F_DEST F_SRC1 REG - { - mips32_r2_inst (); - } - - - | FP_MOVECC_OPS F_DEST F_SRC1 - { - r_co_type_inst ($1.i, $2.i, $3.i, cc_to_rt (0, 0, 0)); - } - - - | FP_MOVECC_OPS F_DEST F_SRC1 CC_REG - { - r_co_type_inst ($1.i, $2.i, $3.i, cc_to_rt ($4.i, 0, 0)); - } - - - | FP_MOVECC_OPS_REV2 F_DEST F_SRC1 CC_REG - { - mips32_r2_inst (); - } - - - | MOVE_FROM_HILO_OPS REG - { - r_type_inst ($1.i, $2.i, 0, 0); - } - - - | MOVE_TO_HILO_OPS REG - { - r_type_inst ($1.i, 0, $2.i, 0); - } - - - - | MOVE_COP_OPS REG COP_REG - { - if ($1.i == Y_MFC1_D_POP) - { - r_co_type_inst (Y_MFC1_OP, 0, $3.i, $2.i); - r_co_type_inst (Y_MFC1_OP, 0, $3.i + 1, $2.i + 1); - } - else if ($1.i == Y_MTC1_D_POP) - { - r_co_type_inst (Y_MTC1_OP, 0, $3.i, $2.i); - r_co_type_inst (Y_MTC1_OP, 0, $3.i + 1, $2.i + 1); - } - else - r_co_type_inst ($1.i, 0, $3.i, $2.i); - } - - - | MOVE_COP_OPS_REV2 REG COP_REG - { - mips32_r2_inst (); - } - - - | CTL_COP_OPS REG COP_REG - { - r_co_type_inst ($1.i, 0, $3.i, $2.i); - } - - - | FP_UNARY_OPS F_DEST F_SRC2 - { - r_co_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_UNARY_OPS_REV2 F_DEST F_SRC2 - { - mips32_r2_inst (); - } - - - | FP_BINARY_OPS F_DEST F_SRC1 F_SRC2 - { - r_co_type_inst ($1.i, $2.i, $3.i, $4.i); - } - - - | FP_BINARY_OPS_REV2 F_DEST F_SRC1 F_SRC2 - { - mips32_r2_inst (); - } - - - | FP_TERNARY_OPS_REV2 F_DEST F_SRC1 F_SRC2 FP_REGISTER - { - mips32_r2_inst (); - } - - - | FP_CMP_OPS F_SRC1 F_SRC2 - { - r_cond_type_inst ($1.i, $2.i, $3.i, 0); - } - - - | FP_CMP_OPS CC_REG F_SRC1 F_SRC2 - { - r_cond_type_inst ($1.i, $3.i, $4.i, $2.i); - } - - - | FP_CMP_OPS_REV2 F_SRC1 F_SRC2 - { - mips32_r2_inst (); - } - - - | Y_COP2_OP IMM32 - { - i_type_inst_free ($1.i, 0, 0, (imm_expr *)$2.p); - } - ; - - - -LOAD_OPS: Y_LB_OP - | Y_LBU_OP - | Y_LH_OP - | Y_LHU_OP - | Y_LL_OP - | Y_LW_OP - | Y_LWL_OP - | Y_LWR_OP - | Y_PFW_OP - | Y_LD_POP - ; - -LOADI_OPS: Y_LUI_OP - ; - -ULOADH_POPS: Y_ULH_POP - | Y_ULHU_POP - ; - -LOADC_OPS: Y_LDC2_OP - | Y_LWC2_OP - ; - -LOADFP_OPS: Y_LDC1_OP - | Y_LWC1_OP - | Y_L_D_POP { $$.i = Y_LDC1_OP; } - | Y_L_S_POP { $$.i = Y_LWC1_OP; } - ; - -LOADFP_INDEX_OPS: Y_LDXC1_OP - | Y_LUXC1_OP - | Y_LWXC1_OP - ; - -STORE_OPS: Y_SB_OP - | Y_SC_OP - | Y_SH_OP - | Y_SW_OP - | Y_SWL_OP - | Y_SWR_OP - | Y_SD_POP - ; - -STOREC_OPS: Y_SWC2_OP - | Y_SDC2_OP - | Y_S_D_POP { $$.i = Y_SDC1_OP; } - | Y_S_S_POP { $$.i = Y_SWC1_OP; } - ; - -STOREFP_OPS: Y_SWC1_OP - | Y_SDC1_OP - ; - -STOREFP_INDEX_OPS: Y_SDXC1_OP - | Y_SUXC1_OP - | Y_SWXC1_OP - ; - -SYS_OPS: Y_RFE_OP - { -#ifdef MIPS1 - yywarn ("RFE should only be used when SPIM is compiled as a MIPS-I processor"); -#endif - } - | Y_SYSCALL_OP - ; - -PREFETCH_OPS: Y_PREFX_OP - | Y_SYNCI_OP - ; - -CACHE_OPS: Y_CACHE_OP - | Y_PREF_OP - ; - -TLB_OPS: Y_TLBP_OP - | Y_TLBR_OP - | Y_TLBWI_OP - | Y_TLBWR_OP - ; - -NULLARY_OPS: Y_ERET_OP - { -#ifdef MIPS1 - yywarn ("ERET should only be used when SPIM is compiled as a MIPS32 processor"); -#endif - } - ; - -NULLARY_OPS_REV2: Y_DERET_OP - | Y_EHB_OP - | Y_SDBBP_OP - ; - -COUNT_LEADING_OPS: Y_CLO_OP - | Y_CLZ_OP - ; - -UNARY_OPS_REV2: Y_DI_OP - | Y_EI_OP - ; - -/* These binary operations have immediate analogues. */ - -BINARYI_OPS: Y_ADD_OP - | Y_ADDU_OP - | Y_AND_OP - | Y_XOR_OP - | Y_OR_OP - | Y_SLT_OP - | Y_SLTU_OP - ; - -BINARYIR_OPS: Y_SLLV_OP - | Y_SRAV_OP - | Y_SRLV_OP - ; - -BINARY_ARITHI_OPS: Y_ADDI_OP - | Y_ADDIU_OP - | Y_SLTI_OP - | Y_SLTIU_OP - ; - -BINARY_LOGICALI_OPS: Y_ANDI_OP - | Y_ORI_OP - | Y_XORI_OP - ; - -SHIFT_OPS: Y_SLL_OP - | Y_SRA_OP - | Y_SRL_OP - ; - -SHIFT_OPS_REV2: Y_ROTR_OP - ; - -SHIFTV_OPS_REV2: Y_ROTRV_OP - ; - - -/* These binary operations do not have immediate analogues. */ - -BINARY_OPS: Y_NOR_OP - ; - -BINARY_OPS_REV2: Y_RDHWR_OP - | Y_RDPGPR_OP - | Y_SEB_OP - | Y_SEH_OP - | Y_WRPGPR_OP - | Y_WSBH_OP - ; - -SUB_OPS: Y_SUB_OP - | Y_SUBU_OP - ; - -DIV_POPS: Y_DIV_OP - | Y_DIVU_OP - | Y_REM_POP - | Y_REMU_POP - ; - -MUL_POPS: Y_MULO_POP - | Y_MULOU_POP - ; - -SET_LE_POPS: Y_SLE_POP - | Y_SLEU_POP - ; - -SET_GT_POPS: Y_SGT_POP - | Y_SGTU_POP - ; - -SET_GE_POPS: Y_SGE_POP - | Y_SGEU_POP - ; - -SET_EQ_POPS: Y_SEQ_POP - | Y_SNE_POP - ; - -MULT_OPS: Y_MULT_OP - | Y_MULTU_OP - | Y_MADD_OP - | Y_MADDU_OP - | Y_MSUB_OP - | Y_MSUBU_OP - ; - -MULT_OPS3: Y_MUL_OP - ; - -BF_OPS_REV2: Y_EXT_OP - | Y_INS_OP - ; - -BR_COP_OPS: Y_BC1F_OP - | Y_BC1FL_OP - | Y_BC1T_OP - | Y_BC1TL_OP - | Y_BC2F_OP - | Y_BC2FL_OP - | Y_BC2T_OP - | Y_BC2TL_OP - ; - -UNARY_BR_OPS: Y_BGEZ_OP - | Y_BGEZL_OP - | Y_BGEZAL_OP - | Y_BGEZALL_OP - | Y_BGTZ_OP - | Y_BGTZL_OP - | Y_BLEZ_OP - | Y_BLEZL_OP - | Y_BLTZ_OP - | Y_BLTZL_OP - | Y_BLTZAL_OP - | Y_BLTZALL_OP - ; - -UNARY_BR_POPS: Y_BEQZ_POP - | Y_BNEZ_POP - ; - -BINARY_BR_OPS: Y_BEQ_OP - | Y_BEQL_OP - | Y_BNE_OP - | Y_BNEL_OP - ; - -BR_GT_POPS: Y_BGT_POP - | Y_BGTU_POP - -BR_GE_POPS: Y_BGE_POP - | Y_BGEU_POP - -BR_LT_POPS: Y_BLT_POP - | Y_BLTU_POP - -BR_LE_POPS: Y_BLE_POP - | Y_BLEU_POP - ; - -J_OPS: Y_J_OP - | Y_JR_OP - | Y_JR_HB_OP { yywarn ("Warning:IPS32 Rev 2 '.HB' extension is not implemented and is ignored"); } - | Y_JAL_OP - | Y_JALR_OP - | Y_JALR_HB_OP { yywarn ("Warning:IPS32 Rev 2 '.HB' extension is not implemented and is ignored"); } - ; - -B_OPS: Y_B_POP - | Y_BAL_POP - ; - - -BINARYI_TRAP_OPS: Y_TEQI_OP - | Y_TGEI_OP - | Y_TGEIU_OP - | Y_TLTI_OP - | Y_TLTIU_OP - | Y_TNEI_OP - ; - -BINARY_TRAP_OPS: Y_TEQ_OP - | Y_TGE_OP - | Y_TGEU_OP - | Y_TLT_OP - | Y_TLTU_OP - | Y_TNE_OP - ; - - -MOVE_FROM_HILO_OPS: Y_MFHI_OP - | Y_MFLO_OP - ; - -MOVE_TO_HILO_OPS: Y_MTHI_OP - | Y_MTLO_OP - ; - -MOVEC_OPS: Y_MOVN_OP - | Y_MOVZ_OP - ; - -MOVE_COP_OPS: Y_MFC0_OP - | Y_MFC1_OP - | Y_MFC1_D_POP - | Y_MFC2_OP - | Y_MTC0_OP - | Y_MTC1_OP - | Y_MTC1_D_POP - | Y_MTC2_OP - ; - -MOVE_COP_OPS_REV2: Y_MFHC1_OP - | Y_MFHC2_OP - | Y_MTHC1_OP - | Y_MTHC2_OP - ; - -CTL_COP_OPS: Y_CFC0_OP - | Y_CFC1_OP - | Y_CFC2_OP - | Y_CTC0_OP - | Y_CTC1_OP - | Y_CTC2_OP - ; - -/* Floating point operations */ - -FP_MOVE_OPS: Y_MOV_S_OP - | Y_MOV_D_OP - ; - -FP_MOVE_OPS_REV2: Y_MOV_PS_OP - ; - - -MOVECC_OPS: Y_MOVF_OP - | Y_MOVT_OP - ; - - -FP_MOVEC_OPS: Y_MOVN_D_OP - | Y_MOVN_S_OP - | Y_MOVZ_D_OP - | Y_MOVZ_S_OP - ; - -FP_MOVEC_OPS_REV2: Y_MOVN_PS_OP - | Y_MOVZ_PS_OP - ; - - -FP_MOVECC_OPS: Y_MOVF_D_OP - | Y_MOVF_S_OP - | Y_MOVT_D_OP - | Y_MOVT_S_OP - ; - -FP_MOVECC_OPS_REV2: Y_MOVF_PS_OP - | Y_MOVT_PS_OP - ; - -FP_UNARY_OPS: Y_ABS_S_OP - | Y_ABS_D_OP - | Y_CEIL_W_D_OP - | Y_CEIL_W_S_OP - | Y_CVT_D_S_OP - | Y_CVT_D_W_OP - | Y_CVT_S_D_OP - | Y_CVT_S_W_OP - | Y_CVT_W_D_OP - | Y_CVT_W_S_OP - | Y_FLOOR_W_D_OP - | Y_FLOOR_W_S_OP - | Y_NEG_S_OP - | Y_NEG_D_OP - | Y_ROUND_W_D_OP - | Y_ROUND_W_S_OP - | Y_SQRT_D_OP - | Y_SQRT_S_OP - | Y_TRUNC_W_D_OP - | Y_TRUNC_W_S_OP - ; - -FP_UNARY_OPS_REV2: Y_ABS_PS_OP - | Y_CEIL_L_D_OP - | Y_CEIL_L_S_OP - | Y_CVT_D_L_OP - | Y_CVT_L_D_OP - | Y_CVT_L_S_OP - | Y_CVT_PS_S_OP - | Y_CVT_S_L_OP - | Y_CVT_S_PL_OP - | Y_CVT_S_PU_OP - | Y_FLOOR_L_D_OP - | Y_FLOOR_L_S_OP - | Y_NEG_PS_OP - | Y_RECIP_D_OP - | Y_RECIP_S_OP - | Y_ROUND_L_D_OP - | Y_ROUND_L_S_OP - | Y_RSQRT_D_OP - | Y_RSQRT_S_OP - | Y_TRUNC_L_D_OP - | Y_TRUNC_L_S_OP - ; - -FP_BINARY_OPS: Y_ADD_S_OP - | Y_ADD_D_OP - | Y_DIV_S_OP - | Y_DIV_D_OP - | Y_MUL_S_OP - | Y_MUL_D_OP - | Y_SUB_S_OP - | Y_SUB_D_OP - ; - -FP_BINARY_OPS_REV2: Y_ADD_PS_OP - | Y_MUL_PS_OP - | Y_PLL_PS_OP - | Y_PLU_PS_OP - | Y_PUL_PS_OP - | Y_PUU_PS_OP - ; - -FP_TERNARY_OPS_REV2: Y_ALNV_PS_OP - | Y_MADD_D_OP - | Y_MADD_PS_OP - | Y_MADD_S_OP - | Y_MSUB_D_OP - | Y_MSUB_PS_OP - | Y_MSUB_S_OP - | Y_NMADD_D_OP - | Y_NMADD_PS_OP - | Y_NMADD_S_OP - | Y_NMSUB_D_OP - | Y_NMSUB_PS_OP - | Y_NMSUB_S_OP - ; - -FP_CMP_OPS: Y_C_F_S_OP - | Y_C_UN_S_OP - | Y_C_EQ_S_OP - | Y_C_UEQ_S_OP - | Y_C_OLT_S_OP - | Y_C_OLE_S_OP - | Y_C_ULT_S_OP - | Y_C_ULE_S_OP - | Y_C_SF_S_OP - | Y_C_NGLE_S_OP - | Y_C_SEQ_S_OP - | Y_C_NGL_S_OP - | Y_C_LT_S_OP - | Y_C_NGE_S_OP - | Y_C_LE_S_OP - | Y_C_NGT_S_OP - | Y_C_F_D_OP - | Y_C_UN_D_OP - | Y_C_EQ_D_OP - | Y_C_UEQ_D_OP - | Y_C_OLT_D_OP - | Y_C_OLE_D_OP - | Y_C_ULT_D_OP - | Y_C_ULE_D_OP - | Y_C_SF_D_OP - | Y_C_NGLE_D_OP - | Y_C_SEQ_D_OP - | Y_C_NGL_D_OP - | Y_C_LT_D_OP - | Y_C_NGE_D_OP - | Y_C_LE_D_OP - | Y_C_NGT_D_OP - ; - -FP_CMP_OPS_REV2: Y_C_EQ_PS_OP - | Y_C_F_PS_OP - | Y_C_LT_PS_OP - | Y_C_LE_PS_OP - | Y_C_NGE_PS_OP - | Y_C_NGL_PS_OP - | Y_C_NGLE_PS_OP - | Y_C_NGT_PS_OP - | Y_C_OLE_PS_OP - | Y_C_OLT_PS_OP - | Y_C_SEQ_PS_OP - | Y_C_SF_PS_OP - | Y_C_UEQ_PS_OP - | Y_C_ULE_PS_OP - | Y_C_ULT_PS_OP - | Y_C_UN_PS_OP - ; - - - -ASM_DIRECTIVE: Y_ALIAS_DIR Y_REG Y_REG - - | Y_ALIGN_DIR EXPR - { - align_data ($2.i); - } - - | Y_ASCII_DIR {null_term = false;} STR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - | Y_ASCIIZ_DIR {null_term = true;} STR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_ASM0_DIR - - | Y_BGNB_DIR Y_INT - - - | Y_BYTE_DIR - {store_op = (void(*)(void*))store_byte;} - EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_COMM_DIR ID EXPR - { - align_data (2); - if (lookup_label ((char*)$2.p)->addr == 0) - { - (void)record_label ((char*)$2.p, current_data_pc (), 1); - free ((char*)$2.p); - } - increment_data_pc ($3.i); - } - - - | Y_DATA_DIR - {user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_DATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_K_DATA_DIR - { - user_kernel_data_segment (true); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_K_DATA_DIR Y_INT - { - user_kernel_data_segment (true); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_DOUBLE_DIR - { - store_op = (void(*)(void*))store_double; - if (data_dir) set_data_alignment (3); - } - FP_EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_END_DIR OPTIONAL_ID - - | Y_ENDB_DIR Y_INT - - | Y_ENDR_DIR - - | Y_ENT_DIR ID - - | Y_ENT_DIR ID Y_INT - - - | Y_EXTERN_DIR ID EXPR - { - extern_directive ((char*)$2.p, $3.i); - } - - - | Y_ERR_DIR - { - fatal_error ("File contains an .err directive\n"); - } - - - | Y_FILE_DIR Y_INT Y_STR - - - | Y_FLOAT_DIR - { - store_op = (void(*)(void*))store_float; - if (data_dir) set_data_alignment (2); - } - FP_EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_FMASK_DIR Y_INT Y_INT - - | Y_FRAME_DIR REGISTER Y_INT REGISTER - - - | Y_GLOBAL_DIR ID - { - (void)make_label_global ((char*)$2.p); - free ((char*)$2.p); - } - - - | Y_HALF_DIR - { - store_op = (void(*)(void*))store_half; - if (data_dir) set_data_alignment (1); - } - EXPR_LST - { - if (text_dir) - yyerror ("Can't put data in text segment"); - } - - - | Y_LABEL_DIR ID - { - (void)record_label ((char*)$2.p, - text_dir ? current_text_pc () : current_data_pc (), - 1); - free ((char*)$2.p); - } - - - | Y_LCOMM_DIR ID EXPR - { - lcomm_directive ((char*)$2.p, $3.i); - } - - - /* Produced by cc 2.10 */ - | Y_LIVEREG_DIR Y_INT Y_INT - - - | Y_LOC_DIR Y_INT Y_INT - - | Y_MASK_DIR Y_INT Y_INT - - | Y_NOALIAS_DIR Y_REG Y_REG - - | Y_OPTIONS_DIR ID - - | Y_REPEAT_DIR EXPR - { - yyerror ("Warning: repeat directive ignored"); - } - - - | Y_RDATA_DIR - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_RDATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_SDATA_DIR - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - } - - | Y_SDATA_DIR Y_INT - { - user_kernel_data_segment (false); - data_dir = true; text_dir = false; - enable_data_alignment (); - set_data_pc ($2.i); - } - - - | Y_SET_DIR ID - { - if (streq ((char*)$2.p, "noat")) - noat_flag = true; - else if (streq ((char*)$2.p, "at")) - noat_flag = false; - } - - - | Y_SPACE_DIR EXPR - { - if (data_dir) - increment_data_pc ($2.i); - else if (text_dir) - increment_text_pc ($2.i); - } - - - | Y_STRUCT_DIR EXPR - { - yyerror ("Warning: struct directive ignored"); - } - - - | Y_TEXT_DIR - { - user_kernel_text_segment (false); - data_dir = false; text_dir = true; - enable_data_alignment (); - } - - | Y_TEXT_DIR Y_INT - { - user_kernel_text_segment (false); - data_dir = false; text_dir = true; - enable_data_alignment (); - set_text_pc ($2.i); - } - - - | Y_K_TEXT_DIR - { - user_kernel_text_segment (true); - data_dir = false; text_dir = true; - enable_data_alignment (); - } - - | Y_K_TEXT_DIR Y_INT - { - user_kernel_text_segment (true); - data_dir = false; text_dir = true; - enable_data_alignment (); - set_text_pc ($2.i); - } - - - | Y_VERSTAMP_DIR Y_INT Y_INT - - | Y_VREG_DIR REGISTER Y_INT Y_INT - - - | Y_WORD_DIR - { - store_op = (void(*)(void*))store_word_data; - if (data_dir) set_data_alignment (2); - } - EXPR_LST - - ; - - - -ADDRESS: {only_id = 1;} ADDR {only_id = 0; $$ = $2;} - -ADDR: '(' REGISTER ')' - { - $$.p = make_addr_expr (0, NULL, $2.i); - } - - | ABS_ADDR - { - $$.p = make_addr_expr ($1.i, NULL, 0); - } - - | ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr ($1.i, NULL, $3.i); - } - - | Y_ID - { - $$.p = make_addr_expr (0, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | Y_ID '(' REGISTER ')' - { - $$.p = make_addr_expr (0, (char*)$1.p, $3.i); - free ((char*)$1.p); - } - - | Y_ID '+' ABS_ADDR - { - $$.p = make_addr_expr ($3.i, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | ABS_ADDR '+' ID - { - $$.p = make_addr_expr ($1.i, (char*)$3.p, 0); - } - - | Y_ID '-' ABS_ADDR - { - $$.p = make_addr_expr (- $3.i, (char*)$1.p, 0); - free ((char*)$1.p); - } - - | Y_ID '+' ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr ($3.i, (char*)$1.p, $5.i); - free ((char*)$1.p); - } - - | Y_ID '-' ABS_ADDR '(' REGISTER ')' - { - $$.p = make_addr_expr (- $3.i, (char*)$1.p, $5.i); - free ((char*)$1.p); - } - ; - - -BR_IMM32: {only_id = 1;} IMM32 {only_id = 0; $$ = $2;} - -IMM16: IMM32 - { - check_imm_range ((imm_expr*)$1.p, IMM_MIN, IMM_MAX); - $$ = $1; - } - -UIMM16: IMM32 - { - check_uimm_range ((imm_expr*)$1.p, UIMM_MIN, UIMM_MAX); - $$ = $1; - } - - -IMM32: ABS_ADDR - { - $$.p = make_imm_expr ($1.i, NULL, false); - } - - | '(' ABS_ADDR ')' '>' '>' Y_INT - { - $$.p = make_imm_expr ($2.i >> $6.i, NULL, false); - } - - | ID - { - $$.p = make_imm_expr (0, (char*)$1.p, false); - } - - | Y_ID '+' ABS_ADDR - { - $$.p = make_imm_expr ($3.i, (char*)$1.p, false); - free ((char*)$1.p); - } - - | Y_ID '-' ABS_ADDR - { - $$.p = make_imm_expr (- $3.i, (char*)$1.p, false); - free ((char*)$1.p); - } - ; - - -ABS_ADDR: Y_INT - - | Y_INT '+' Y_INT - {$$.i = $1.i + $3.i;} - - | Y_INT Y_INT - { - /* This is actually: Y_INT '-' Y_INT, since the binary - subtract operator gets scanned as a unary negation - operator. */ - if ($2.i >= 0) yyerror ("Syntax error"); - $$.i = $1.i - -$2.i; - } - ; - -SRC1: REGISTER ; - -SRC2: REGISTER ; - -DEST: REGISTER ; - -REG: REGISTER ; - -REGISTER: Y_REG - { - if ($1.i < 0 || $1.i > 31) - yyerror ("Register number out of range"); - if ($1.i == 1 && !bare_machine && !noat_flag) - yyerror ("Register 1 is reserved for assembler"); - $$ = $1; - } - -F_DEST: FP_REGISTER ; - -F_SRC1: FP_REGISTER ; - -F_SRC2: FP_REGISTER ; - -FP_REGISTER: Y_FP_REG - { - if ($1.i < 0 || $1.i > 31) - yyerror ("FP register number out of range"); - $$ = $1; - } - - -CC_REG: Y_INT - { - if ($1.i < 0 || $1.i > 7) - yyerror ("CC register number out of range"); - $$ = $1; - } - - -COP_REG: Y_REG - - | Y_FP_REG - - ; - - -LABEL: ID - { - $$.p = make_imm_expr (-(int)current_text_pc (), (char*)$1.p, true); - } - - -STR_LST: STR_LST STR - | STR - ; - - -STR: Y_STR - { - store_string ((char*)$1.p, strlen((char*)$1.p), null_term); - free ((char*)$1.p); - } - | Y_STR ':' Y_INT - { - int i; - - for (i = 0; i < $3.i; i ++) - store_string ((char*)$1.p, strlen((char*)$1.p), null_term); - free ((char*)$1.p); - } - ; - - -EXPRESSION: {only_id = 1;} EXPR {only_id = 0; $$ = $2;} - -EXPR: - TRM - | - EXPR '+' TRM - { $$.i = $1.i + $3.i; } - | - EXPR '-' TRM - { $$.i = $1.i - $3.i; } - ; - -TRM: - FACTOR - | - TRM '*' FACTOR - { $$.i = $1.i * $3.i; } - | - TRM '/' FACTOR - { $$.i = $1.i / $3.i; } - ; - -FACTOR: Y_INT - - | '(' EXPR ')' - { $$.i = $2.i; } - - | ID - { - label *l = lookup_label ((char*)$1.p); - if (l->addr == 0) - { - record_data_uses_symbol (current_data_pc (), l); - $$.p = NULL; - } - else - $$.i = l->addr; - } - - -EXPR_LST: EXPR_LST EXPRESSION - { - store_op ($2.p); - } - | EXPRESSION - { - store_op ($1.p); - } - | EXPRESSION ':' EXPR - { - int i; - - for (i = 0; i < $3.i; i ++) - store_op ($1.p); - } - ; - - -FP_EXPR_LST: FP_EXPR_LST Y_FP - { - store_op ($2.p); - } - | Y_FP - { - store_op ($1.p); - } - ; - - -OPTIONAL_ID: {only_id = 1;} OPT_ID {only_id = 0; $$ = $2;} - -OPT_ID: ID - | {$$.p = (void*)NULL;} - ; - - -ID: {only_id = 1;} Y_ID {only_id = 0; $$ = $2;} - - -%% - -/* Maintain and update the address of labels for the current line. */ - -void -fix_current_label_address (mem_addr new_addr) -{ - label_list *l; - - for (l = this_line_labels; l != NULL; l = l->tail) - { - l->head->addr = new_addr; - } - clear_labels (); -} - - -static label_list * -cons_label (label *head, label_list *tail) -{ - label_list *c = (label_list *) malloc (sizeof (label_list)); - - c->head = head; - c->tail = tail; - return (c); -} - - -static void -clear_labels () -{ - label_list *n; - - for ( ; this_line_labels != NULL; this_line_labels = n) - { - resolve_label_uses (this_line_labels->head); - n = this_line_labels->tail; - free (this_line_labels); - } - this_line_labels = NULL; -} - - -/* Operations on op codes. */ - -int -op_to_imm_op (int opcode) -{ - switch (opcode) - { - case Y_ADD_OP: return (Y_ADDI_OP); - case Y_ADDU_OP: return (Y_ADDIU_OP); - case Y_AND_OP: return (Y_ANDI_OP); - case Y_OR_OP: return (Y_ORI_OP); - case Y_XOR_OP: return (Y_XORI_OP); - case Y_SLT_OP: return (Y_SLTI_OP); - case Y_SLTU_OP: return (Y_SLTIU_OP); - case Y_SLLV_OP: return (Y_SLL_OP); - case Y_SRAV_OP: return (Y_SRA_OP); - case Y_SRLV_OP: return (Y_SRL_OP); - default: fatal_error ("Can't convert op to immediate op\n"); return (0); - } -} - - -int -imm_op_to_op (int opcode) -{ - switch (opcode) - { - case Y_ADDI_OP: return (Y_ADD_OP); - case Y_ADDIU_OP: return (Y_ADDU_OP); - case Y_ANDI_OP: return (Y_AND_OP); - case Y_ORI_OP: return (Y_OR_OP); - case Y_XORI_OP: return (Y_XOR_OP); - case Y_SLTI_OP: return (Y_SLT_OP); - case Y_SLTIU_OP: return (Y_SLTU_OP); - case Y_J_OP: return (Y_JR_OP); - case Y_LUI_OP: return (Y_ADDU_OP); - case Y_SLL_OP: return (Y_SLLV_OP); - case Y_SRA_OP: return (Y_SRAV_OP); - case Y_SRL_OP: return (Y_SRLV_OP); - default: fatal_error ("Can't convert immediate op to op\n"); return (0); - } -} - - -static void -nop_inst () -{ - r_type_inst (Y_SLL_OP, 0, 0, 0); /* = 0 */ -} - - -static void -trap_inst () -{ - r_type_inst (Y_BREAK_OP, 0, 0, 0); -} - - -static imm_expr * -branch_offset (int n_inst) -{ - return (const_imm_expr (n_inst << 2)); /* Later shifted right 2 places */ -} - - -static void -div_inst (int op, int rd, int rs, int rt, int const_divisor) -{ - if (rd != 0 && !const_divisor) - { - i_type_inst_free (Y_BNE_OP, 0, rt, branch_offset (2)); - trap_inst (); - } - - if (op == Y_DIV_OP || op == Y_REM_POP) - r_type_inst (Y_DIV_OP, 0, rs, rt); - else - r_type_inst (Y_DIVU_OP, 0, rs, rt); - - if (rd != 0) - { - if (op == Y_DIV_OP || op == Y_DIVU_OP) - /* Quotient */ - r_type_inst (Y_MFLO_OP, rd, 0, 0); - else - /* Remainder */ - r_type_inst (Y_MFHI_OP, rd, 0, 0); - } -} - - -static void -mult_inst (int op, int rd, int rs, int rt) -{ - if (op == Y_MULOU_POP) - r_type_inst (Y_MULTU_OP, 0, rs, rt); - else - r_type_inst (Y_MULT_OP, 0, rs, rt); - if (op == Y_MULOU_POP && rd != 0) - { - r_type_inst (Y_MFHI_OP, 1, 0, 0); /* Use $at */ - i_type_inst_free (Y_BEQ_OP, 0, 1, branch_offset (2)); - trap_inst (); - } - else if (op == Y_MULO_POP && rd != 0) - { - r_type_inst (Y_MFHI_OP, 1, 0, 0); /* use $at */ - r_type_inst (Y_MFLO_OP, rd, 0, 0); - r_sh_type_inst (Y_SRA_OP, rd, rd, 31); - i_type_inst_free (Y_BEQ_OP, rd, 1, branch_offset (2)); - trap_inst (); - } - if (rd != 0) - r_type_inst (Y_MFLO_OP, rd, 0, 0); -} - - -static void -set_le_inst (int op, int rd, int rs, int rt) -{ - i_type_inst_free (Y_BNE_OP, rs, rt, branch_offset (3)); - i_type_inst_free (Y_ORI_OP, rd, 0, const_imm_expr (1)); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); - r_type_inst ((op == Y_SLE_POP ? Y_SLT_OP : Y_SLTU_OP), rd, rs, rt); -} - - -static void -set_gt_inst (int op, int rd, int rs, int rt) -{ - r_type_inst (op == Y_SGT_POP ? Y_SLT_OP : Y_SLTU_OP, rd, rt, rs); -} - - -static void -set_ge_inst (int op, int rd, int rs, int rt) -{ - i_type_inst_free (Y_BNE_OP, rs, rt, branch_offset (3)); - i_type_inst_free (Y_ORI_OP, rd, 0, const_imm_expr (1)); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); - r_type_inst (op == Y_SGE_POP ? Y_SLT_OP : Y_SLTU_OP, rd, rt, rs); -} - - -static void -set_eq_inst (int op, int rd, int rs, int rt) -{ - imm_expr *if_eq, *if_neq; - - if (op == Y_SEQ_POP) - if_eq = const_imm_expr (1), if_neq = const_imm_expr (0); - else - if_eq = const_imm_expr (0), if_neq = const_imm_expr (1); - - i_type_inst_free (Y_BEQ_OP, rs, rt, branch_offset (3)); - /* RD <- 0 (if not equal) */ - i_type_inst_free (Y_ORI_OP, rd, 0, if_neq); - i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); /* Branch always */ - /* RD <- 1 */ - i_type_inst_free (Y_ORI_OP, rd, 0, if_eq); -} - - -/* Store the value either as a datum or instruction. */ - -static void -store_word_data (int value) -{ - if (data_dir) - store_word (value); - else if (text_dir) - store_instruction (inst_decode (value)); -} - - - -void -initialize_parser (char *file_name) -{ - input_file_name = file_name; - only_id = 0; - data_dir = false; - text_dir = true; -} - - -static void -check_imm_range (imm_expr* expr, int32 min, int32 max) -{ - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* If expression can be evaluated, compare its value against the limits - and complain if the value is out of bounds. */ - int32 value = eval_imm_expr (expr); - - if (value < min || max < value) - { - char str[200]; - sprintf (str, "immediate value (%d) out of range (%d .. %d)", - value, min, max); - yywarn (str); - } - } -} - - -static void -check_uimm_range (imm_expr* expr, uint32 min, uint32 max) -{ - if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) - { - /* If expression can be evaluated, compare its value against the limits - and complain if the value is out of bounds. */ - uint32 value = (uint32)eval_imm_expr (expr); - - if (value < min || max < value) - { - char str[200]; - sprintf (str, "immediate value (%d) out of range (%d .. %d)", - (int32)value, (int32)min, (int32)max); - yywarn (str); - } - } -} - -void -yyerror (char *s) -{ - parse_error_occurred = true; - clear_labels (); - yywarn (s); -} - - -void -yywarn (char *s) -{ - error ("spim: (parser) %s on line %d of file %s\n%s", s, line_no, input_file_name, erroneous_line ()); -} - - -static void -mips32_r2_inst () -{ - yyerror ("Warning: MIPS32 Rev 2 instruction is not implemented. Instruction ignored."); -} - - -static int -cc_to_rt (int cc, int nd, int tf) -{ - return (cc << 2) | (nd << 1) | tf; -} diff --git a/spim-qtspimbot/CPU/reg.h b/spim-qtspimbot/CPU/reg.h deleted file mode 100755 index 9034c8a..0000000 --- a/spim-qtspimbot/CPU/reg.h +++ /dev/null @@ -1,268 +0,0 @@ -/* SPIM S20 MIPS simulator. - Declarations of registers and code for accessing them. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef REG_H -#define REG_H - - -typedef int32 /*@alt unsigned int @*/ reg_word; -typedef uint32 u_reg_word; - - -/* General purpose registers: */ - -#define R_LENGTH 32 - -typedef struct regimage { - int context; - - int RFE_cycle; - - /* General purpose registers: */ - reg_word R[R_LENGTH]; - reg_word HI, LO; - mem_addr PC, nPC; - - /* Floating Point Coprocessor (1) registers: */ - double *FPR; /* Dynamically allocate so overlay */ - float *FGR; /* is possible */ - int *FWR; /* is possible */ - - /* Coprocessor registers: */ - reg_word CCR[4][32], CPR[4][32]; - - int exception_occurred; - - bool in_kernel; /* => data goes to kdata, not data */ - - mem_addr next_text_pc; - mem_addr next_k_text_pc; - mem_addr next_data_pc; /* Location for next datum in user process */ - mem_addr next_k_data_pc; /* Location for next datum in kernel */ - mem_addr next_gp_item_addr; /* Address of next item accessed off $gp */ - bool auto_alignment; -} reg_image_t; - -extern int cycle; -extern reg_image_t reg_images[2]; -extern size_t num_contexts; - -/* Argument passing registers */ - -#define REG_V0 2 -#define REG_A0 4 -#define REG_A1 5 -#define REG_A2 6 -#define REG_A3 7 -#define REG_FA0 12 -#define REG_SP 29 - - -/* Result registers */ - -#define REG_RES 2 -#define REG_FRES 0 - - -/* $gp registers */ - -#define REG_GP 28 - -extern char *int_reg_names[]; - - - -/* Exeception handling registers (Coprocessor 0): */ - -/* BadVAddr register: */ -#define CP0_BadVAddr_Reg 8 -#define CP0_BadVAddr(REGIMAGE) (REGIMAGE.CPR[0][CP0_BadVAddr_Reg]) - -/* Count register: */ -#define CP0_Count_Reg 9 -#define CP0_Count(REGIMAGE) (REGIMAGE.CPR[0][CP0_Count_Reg]) /* ToDo */ - -/* Compare register: */ -#define CP0_Compare_Reg 11 -#define CP0_Compare(REGIMAGE) (REGIMAGE.CPR[0][CP0_Compare_Reg]) /* ToDo */ - -/* Status register: */ -#define CP0_Status_Reg 12 -#define CP0_Status(REGIMAGE) (REGIMAGE.CPR[0][CP0_Status_Reg]) -/* Implemented fields: */ -#define CP0_Status_CU 0xf0000000 -#define CP0_Status_IM 0x0000ff00 -#define CP0_Status_IM7 0x00008000 /* HW Int 5 */ -#define CP0_Status_IM6 0x00004000 /* HW Int 4 */ -#define CP0_Status_IM5 0x00002000 /* HW Int 3 */ -#define CP0_Status_IM4 0x00001000 /* HW Int 2 */ -#define CP0_Status_IM3 0x00000800 /* HW Int 1 */ -#define CP0_Status_IM2 0x00000400 /* HW Int 0 */ -#define CP0_Status_IM1 0x00000200 /* SW Int 1 */ -#define CP0_Status_IM0 0x00000100 /* SW Int 0 */ -#define CP0_Status_UM 0x00000010 -#define CP0_Status_EXL 0x00000002 -#define CP0_Status_IE 0x00000001 -#define CP0_Status_Mask (CP0_Status_CU \ - | CP0_Status_UM \ - | CP0_Status_IM \ - | CP0_Status_EXL \ - | CP0_Status_IE) - -/* Cause register: */ -#define CP0_Cause_Reg 13 -#define CP0_Cause(REGIMAGE) (REGIMAGE.CPR[0][CP0_Cause_Reg]) -/* Implemented fields: */ -#define CP0_Cause_BD 0x80000000 -#define CP0_Cause_IP 0x0000ff00 -#define CP0_Cause_IP7 0x00008000 /* HW Int 5 */ -#define CP0_Cause_IP6 0x00004000 /* HW Int 4 */ -#define CP0_Cause_IP5 0x00002000 /* HW Int 3 */ -#define CP0_Cause_IP4 0x00001000 /* HW Int 2 */ -#define CP0_Cause_IP3 0x00000800 /* HW Int 1 */ -#define CP0_Cause_IP2 0x00000400 /* HW Int 0 */ -#define CP0_Cause_IP1 0x00000200 /* SW Int 1 */ -#define CP0_Cause_IP0 0x00000100 /* SW Int 0 */ -#define CP0_Cause_ExcCode 0x0000007c -#define CP0_Cause_Mask (CP0_Cause_BD \ - | CP0_Cause_IP \ - | CP0_Cause_IP7 \ - | CP0_Cause_IP6 \ - | CP0_Cause_IP5 \ - | CP0_Cause_IP4 \ - | CP0_Cause_IP3 \ - | CP0_Cause_IP2 \ - | CP0_Cause_ExcCode) -#define CP0_ExCode(REGIMAGE) ((CP0_Cause(REGIMAGE) & CP0_Cause_ExcCode) >> 2) - -/* EPC register: */ -#define CP0_EPC_Reg 14 -#define CP0_EPC(REGIMAGE) (REGIMAGE.CPR[0][CP0_EPC_Reg]) - -/* Config register: */ -#define CP0_Config_Reg 16 -#define CP0_Config(REGIMAGE) (REGIMAGE.CPR[0][CP0_Config_Reg]) -/* Implemented fields: */ -#define CP0_Config_BE 0x000080000 -#define CP0_Config_AT 0x000060000 -#define CP0_Config_AR 0x00001c000 -#define CP0_Config_MT 0x000000380 -#define CP0_Config_Mask (CP0_Config_BE \ - | CP0_Config_AT \ - | CP0_Config_AR \ - | CP0_Config_MT) - - - -/* Floating Point Coprocessor (1) registers. - - This is the MIPS32, Revision 1 FPU register set. It contains 32, 32-bit - registers (either 32 single or 16 double precision), as in the R2010. - The MIPS32, Revision 2 or MIPS64 register set has 32 of each type of - register. */ - -#define FGR_LENGTH 32 -#define FPR_LENGTH 16 - -#define FPR_S(REGIMAGE, REGNO) (REGIMAGE.FGR[REGNO]) - -#define FPR_D(REGIMAGE, REGNO) (((REGNO) & 0x1) \ - ? (run_error ("Odd FP double register number\n") , 0.0) \ - : REGIMAGE.FPR[(REGNO) / 2]) - -#define FPR_W(REGIMAGE, REGNO) (REGIMAGE.FWR[REGNO]) - -#define SET_FPR_S(REGIMAGE, REGNO, VALUE) {REGIMAGE.FGR[REGNO] = (float) (VALUE);} - -#define SET_FPR_D(REGIMAGE, REGNO, VALUE) {if ((REGNO) & 0x1) \ - run_error ("Odd FP double register number\n"); \ - else REGIMAGE.FPR[(REGNO) / 2] = (double) (VALUE);} - -#define SET_FPR_W(REGIMAGE, REGNO, VALUE) {REGIMAGE.FWR[REGNO] = (int32) (VALUE);} - - -/* Floating point control registers: */ - -#define FCR(REGIMAGE) (REGIMAGE.CPR[1]) - - -#define FIR_REG 0 -#define FIR(REGIMAGE) (FCR(REGIMAGE)[FIR_REG]) -/* Implemented fields: */ -#define FIR_W 0x0008000 -#define FIR_D 0x0001000 -#define FIR_S 0x0000800 -#define FIR_MASK (FIR_W | FIR_D | FIR_S) - -#define FCCR_REG 25 -#define FCCR(REGIMAGE) (FCR(REGIMAGE)[FCCR_REG]) -/* Implemented fields: */ -#define FCCR_FCC 0x000000ff -#define FCCR_MASK (FCCR_FCC) - -#define FEXR_REG 26 -#define FEXR(REGIMAGE) (FCR(REGIMAGE)[FEXR_REG]) -/* No implemented fields */ - -#define FENR_REG 28 -#define FENR(REGIMAGE) (FCR(REGIMAGE)[FENR_REG]) -/* No implemented fields */ - -#define FCSR_REG 31 -#define FCSR(REGIMAGE) (FCR(REGIMAGE)[FCSR_REG]) -/* Implemented fields: */ -#define FCSR_FCC 0xfe800000 -#define FCSR_MASK (FCSR_FCC) -/* Floating point Cause (not implemented): */ -#define FCSR_Cause_E 0x00020000 -#define FCSR_Cause_V 0x00010000 -#define FCSR_Cause_Z 0x00008000 -#define FCSR_Cause_O 0x00004000 -#define FCSR_Cause_U 0x00002000 -#define FCSR_Cause_I 0x00001000 -/* Floating point Enables (not implemented): */ -#define FCSR_Enable_V 0x00000800 -#define FCSR_Enable_Z 0x00000400 -#define FCSR_Enable_O 0x00000200 -#define FCSR_Enable_U 0x00000100 -#define FCSR_Enable_I 0x00000080 -/* Floating point Flags (not implemented): */ -#define FCSR_Flag_V 0x00000040 -#define FCSR_Flag_Z 0x00000020 -#define FCSR_Flag_O 0x00000010 -#define FCSR_Flag_U 0x00000008 -#define FCSR_Flag_I 0x00000004 - -#define INTERRUPTS_ON(REGIMAGE) (CP0_Status(REGIMAGE) & CP0_Status_IE) -#define IN_INTERRUPT_HANDLER(REGIMAGE) (CP0_Status(REGIMAGE) & CP0_Status_EXL) - -#endif diff --git a/spim-qtspimbot/CPU/run.cpp b/spim-qtspimbot/CPU/run.cpp deleted file mode 100755 index 2eb875c..0000000 --- a/spim-qtspimbot/CPU/run.cpp +++ /dev/null @@ -1,1731 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM instructions. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifdef mips -#define _IEEE 1 -#include -#else -#define NaN(X) ((X) != (X)) -#endif - -#include -#include - -#ifdef _WIN32 -#define VC_EXTRALEAN -#include -#else -#include -#include -#include -#include -#endif - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "parser_yacc.h" -#include "syscall.h" -#include "run.h" -#include "../Spimbot/robot.h" - -bool force_break = false; /* For the execution env. to force an execution break */ - -#ifdef _MSC_BUILD -/* Disable MS VS warning about constant predicate in conditional. */ -#pragma warning(disable: 4127) -#endif - - -/* Local functions: */ - -static void set_fpu_cc (size_t context, int cond, int cc, int less, int equal, int unordered); -static void signed_multiply (size_t context, reg_word v1, reg_word v2); -static void unsigned_multiply (size_t context, reg_word v1, reg_word v2); - - -#define SIGN_BIT(X) ((X) & 0x80000000) - -#define ARITH_OVFL(RESULT, OP1, OP2) (SIGN_BIT (OP1) == SIGN_BIT (OP2) \ - && SIGN_BIT (OP1) != SIGN_BIT (RESULT)) - - - -/* True when delayed_branches is true and instruction is executing in delay -slot of another instruction. */ -static int running_in_delay_slot = 0; - - -/* Executed delayed branch and jump instructions by running the - instruction from the delay slot before transfering control. Note, - in branches that don't jump, the instruction in the delay slot is - executed by falling through normally. - - We take advantage of the MIPS architecture, which leaves undefined - the result of executing a delayed instruction in a delay slot. Here - we execute the second branch. */ - -#define BRANCH_INST(TEST, TARGET, NULLIFY) \ - { \ - if (TEST) \ - { \ - mem_addr target = (TARGET); \ - if (delayed_branches) \ - { \ - /* +4 since jump in delay slot */ \ - target += BYTES_PER_WORD; \ - } \ - JUMP_INST(target) \ - } \ - else if (NULLIFY) \ - { \ - /* If test fails and nullify bit set, skip\ - instruction in delay slot. */ \ - reg_image.PC += BYTES_PER_WORD; \ - } \ - } - - -#define JUMP_INST(TARGET) \ - { \ - if (delayed_branches) \ - { \ - running_in_delay_slot = 1; \ - run_spim (context, display); \ - running_in_delay_slot = 0; \ - } \ - /* -4 since PC is bumped after this inst */ \ - reg_image.PC = (TARGET) - BYTES_PER_WORD; \ - } - - -/* If the delayed_load flag is false, the result from a load is available - immediate. If the delayed_load flag is true, the result from a load is - not available until the subsequent instruction has executed (as in the - real machine). We need a two element shift register for the value and its - destination, as the instruction following the load can itself be a load - instruction. */ - -#define LOAD_INST(DEST_A, LD, MASK) \ - { \ - LOAD_INST_BASE (DEST_A, (LD & (MASK))) \ - } - - -#define LOAD_INST_BASE(DEST_A, VALUE) \ - { \ - if (delayed_loads) \ - { \ - delayed_load_addr1 = (DEST_A); \ - delayed_load_value1 = (VALUE); \ - } \ - else \ - { \ - *(DEST_A) = (VALUE); \ - } \ - } - - -#define DO_DELAYED_UPDATE() \ - if (delayed_loads) \ - { \ - /* Check for delayed updates */ \ - if (delayed_load_addr2 != NULL) \ - { \ - *delayed_load_addr2 = delayed_load_value2; \ - } \ - delayed_load_addr2 = delayed_load_addr1; \ - delayed_load_value2 = delayed_load_value1; \ - delayed_load_addr1 = NULL; \ - } - - - -/* Run the program stored in memory, starting at address PC for - STEPS_TO_RUN instruction executions. If flag DISPLAY is true, print - each instruction before it executes. Return true if program's - execution can continue. */ - -bool -run_spim (size_t context, bool display) -{ - reg_image_t ®_image = reg_images[context]; - - instruction *inst; - static reg_word *delayed_load_addr1 = NULL, delayed_load_value1; - static reg_word *delayed_load_addr2 = NULL, delayed_load_value2; - - reg_image.R[0] = 0; /* Maintain invariant value */ - - inst = read_mem_inst (context, reg_image.PC); - if (reg_image.exception_occurred) - { - reg_image.exception_occurred = 0; - handle_exception (reg_image); - return true; - } - else if (inst == NULL) - { - run_error ("Attempt to execute non-instruction at 0x%08x\n", reg_image.PC); - return false; - } - else if (EXPR (inst) != NULL - && EXPR (inst)->symbol != NULL - && EXPR (inst)->symbol->addr == 0) - { - run_error ("Instruction references undefined symbol at 0x%08x\n %s", reg_image.PC, inst_to_string(reg_image.PC)); - return false; - } - - if (display) - print_inst (reg_image.PC); - -#ifdef TEST_ASM - test_assembly (inst); -#endif - - DO_DELAYED_UPDATE (); - - switch (OPCODE (inst)) - { - case Y_ADD_OP: - { - reg_word vs = reg_image.R[RS (inst)], vt = reg_image.R[RT (inst)]; - reg_word sum = vs + vt; - - if (ARITH_OVFL (sum, vs, vt)) - RAISE_EXCEPTION (reg_image, ExcCode_Ov, break); - reg_image.R[RD (inst)] = sum; - break; - } - - case Y_ADDI_OP: - { - reg_word vs = reg_image.R[RS (inst)], imm = (short) IMM (inst); - reg_word sum = vs + imm; - - if (ARITH_OVFL (sum, vs, imm)) - RAISE_EXCEPTION (reg_image, ExcCode_Ov, break); - reg_image.R[RT (inst)] = sum; - break; - } - - case Y_ADDIU_OP: - reg_image.R[RT (inst)] = reg_image.R[RS (inst)] + (short) IMM (inst); - break; - - case Y_ADDU_OP: - reg_image.R[RD (inst)] = reg_image.R[RS (inst)] + reg_image.R[RT (inst)]; - break; - - case Y_AND_OP: - reg_image.R[RD (inst)] = reg_image.R[RS (inst)] & reg_image.R[RT (inst)]; - break; - - case Y_ANDI_OP: - reg_image.R[RT (inst)] = reg_image.R[RS (inst)] & (0xffff & IMM (inst)); - break; - - case Y_BC2F_OP: - case Y_BC2FL_OP: - case Y_BC2T_OP: - case Y_BC2TL_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_BEQ_OP: - BRANCH_INST (reg_image.R[RS (inst)] == reg_image.R[RT (inst)], - reg_image.PC + IDISP (inst), - 0); - break; - - case Y_BEQL_OP: - BRANCH_INST (reg_image.R[RS (inst)] == reg_image.R[RT (inst)], - reg_image.PC + IDISP (inst), - 1); - break; - - case Y_BGEZ_OP: - BRANCH_INST (SIGN_BIT (reg_image.R[RS (inst)]) == 0, - reg_image.PC + IDISP (inst), - 0); - break; - - case Y_BGEZL_OP: - BRANCH_INST (SIGN_BIT (reg_image.R[RS (inst)]) == 0, - reg_image.PC + IDISP (inst), - 1); - break; - - case Y_BGEZAL_OP: - reg_image.R[31] = reg_image.PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (reg_image.R[RS (inst)]) == 0, - reg_image.PC + IDISP (inst), - 0); - break; - - case Y_BGEZALL_OP: - reg_image.R[31] = reg_image.PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (reg_image.R[RS (inst)]) == 0, - reg_image.PC + IDISP (inst), - 1); - break; - - case Y_BGTZ_OP: - BRANCH_INST (reg_image.R[RS (inst)] != 0 && SIGN_BIT (reg_image.R[RS (inst)]) == 0, - reg_image.PC + IDISP (inst), - 0); - break; - - case Y_BGTZL_OP: - BRANCH_INST (reg_image.R[RS (inst)] != 0 && SIGN_BIT (reg_image.R[RS (inst)]) == 0, - reg_image.PC + IDISP (inst), - 1); - break; - - case Y_BLEZ_OP: - BRANCH_INST (reg_image.R[RS (inst)] == 0 || SIGN_BIT (reg_image.R[RS (inst)]) != 0, - reg_image.PC + IDISP (inst), - 0); - break; - - case Y_BLEZL_OP: - BRANCH_INST (reg_image.R[RS (inst)] == 0 || SIGN_BIT (reg_image.R[RS (inst)]) != 0, - reg_image.PC + IDISP (inst), - 1); - break; - - case Y_BLTZ_OP: - BRANCH_INST (SIGN_BIT (reg_image.R[RS (inst)]) != 0, - reg_image.PC + IDISP (inst), - 0); - break; - - case Y_BLTZL_OP: - BRANCH_INST (SIGN_BIT (reg_image.R[RS (inst)]) != 0, - reg_image.PC + IDISP (inst), - 1); - break; - - case Y_BLTZAL_OP: - reg_image.R[31] = reg_image.PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (reg_image.R[RS (inst)]) != 0, - reg_image.PC + IDISP (inst), - 0); - break; - - case Y_BLTZALL_OP: - reg_image.R[31] = reg_image.PC + (delayed_branches ? 2 * BYTES_PER_WORD : BYTES_PER_WORD); - BRANCH_INST (SIGN_BIT (reg_image.R[RS (inst)]) != 0, - reg_image.PC + IDISP (inst), - 1); - break; - - case Y_BNE_OP: - BRANCH_INST (reg_image.R[RS (inst)] != reg_image.R[RT (inst)], - reg_image.PC + IDISP (inst), - 0); - break; - - case Y_BNEL_OP: - BRANCH_INST (reg_image.R[RS (inst)] != reg_image.R[RT (inst)], - reg_image.PC + IDISP (inst), - 1); - break; - - case Y_BREAK_OP: - if (RD (inst) == 1) - /* Debugger breakpoint */ - RAISE_EXCEPTION (reg_image, ExcCode_Bp, return true) - else - RAISE_EXCEPTION (reg_image, ExcCode_Bp, break); - - case Y_CACHE_OP: - break; /* Memory details not implemented */ - - case Y_CFC0_OP: - reg_image.R[RT (inst)] = reg_image.CCR[0][RD (inst)]; - break; - - case Y_CFC2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_CLO_OP: - { - reg_word val = reg_image.R[RS (inst)]; - int i; - for (i = 31; 0 <= i; i -= 1) - if (((val >> i) & 0x1) == 0) break; - - reg_image.R[RD (inst) ] = 31 - i; - break; - } - - case Y_CLZ_OP: - { - reg_word val = reg_image.R[RS (inst)]; - int i; - for (i = 31; 0 <= i; i -= 1) - if (((val >> i) & 0x1) == 1) break; - - reg_image.R[RD (inst) ] = 31 - i; - break; - } - - case Y_COP2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_CTC0_OP: - reg_image.CCR[0][RD (inst)] = reg_image.R[RT (inst)]; - break; - - case Y_CTC2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_DIV_OP: - /* The behavior of this instruction is undefined on divide by - zero or overflow. */ - if (reg_image.R[RT (inst)] != 0 - && !(reg_image.R[RS (inst)] == (reg_word)0x80000000 - && reg_image.R[RT (inst)] == (reg_word)0xffffffff)) - { - reg_image.LO = (reg_word) reg_image.R[RS (inst)] / (reg_word) reg_image.R[RT (inst)]; - reg_image.HI = (reg_word) reg_image.R[RS (inst)] % (reg_word) reg_image.R[RT (inst)]; - } - break; - - case Y_DIVU_OP: - /* The behavior of this instruction is undefined on divide by - zero or overflow. */ - if (reg_image.R[RT (inst)] != 0 - && !(reg_image.R[RS (inst)] == (reg_word)0x80000000 - && reg_image.R[RT (inst)] == (reg_word)0xffffffff)) - { - reg_image.LO = (u_reg_word) reg_image.R[RS (inst)] / (u_reg_word) reg_image.R[RT (inst)]; - reg_image.HI = (u_reg_word) reg_image.R[RS (inst)] % (u_reg_word) reg_image.R[RT (inst)]; - } - break; - - case Y_ERET_OP: - { - CP0_Status(reg_image) &= ~CP0_Status_EXL; /* Clear EXL bit */ - JUMP_INST (CP0_EPC(reg_image)); /* Jump to EPC */ - } - break; - - case Y_J_OP: - JUMP_INST (((reg_image.PC & 0xf0000000) | TARGET (inst) << 2)); - break; - - case Y_JAL_OP: - if (delayed_branches) - reg_image.R[31] = reg_image.PC + 2 * BYTES_PER_WORD; - else - reg_image.R[31] = reg_image.PC + BYTES_PER_WORD; - JUMP_INST (((reg_image.PC & 0xf0000000) | (TARGET (inst) << 2))); - break; - - case Y_JALR_OP: - { - mem_addr tmp = reg_image.R[RS (inst)]; - - if (delayed_branches) - reg_image.R[RD (inst)] = reg_image.PC + 2 * BYTES_PER_WORD; - else - reg_image.R[RD (inst)] = reg_image.PC + BYTES_PER_WORD; - JUMP_INST (tmp); - } - break; - - case Y_JR_OP: - { - mem_addr tmp = reg_image.R[RS (inst)]; - - JUMP_INST (tmp); - } - break; - - case Y_LB_OP: - LOAD_INST (®_image.R[RT (inst)], - read_mem_byte (context, reg_image.R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LBU_OP: - LOAD_INST (®_image.R[RT (inst)], - read_mem_byte (context, reg_image.R[BASE (inst)] + IOFFSET (inst)), - 0xff); - break; - - case Y_LH_OP: - LOAD_INST (®_image.R[RT (inst)], - read_mem_half (context, reg_image.R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LHU_OP: - LOAD_INST (®_image.R[RT (inst)], - read_mem_half (context, reg_image.R[BASE (inst)] + IOFFSET (inst)), - 0xffff); - break; - - case Y_LL_OP: - /* Uniprocess, so this instruction is just a load */ - LOAD_INST (®_image.R[RT (inst)], - read_mem_word (context, reg_image.R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LUI_OP: - reg_image.R[RT (inst)] = (IMM (inst) << 16) & 0xffff0000; - break; - - case Y_LW_OP: - LOAD_INST (®_image.R[RT (inst)], - read_mem_word (context, reg_image.R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_LDC2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_LWC2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_LWL_OP: - { - mem_addr addr = reg_image.R[BASE (inst)] + IOFFSET (inst); - reg_word word; /* Can't be register */ - int byte = addr & 0x3; - reg_word reg_val = reg_image.R[RT (inst)]; - - word = read_mem_word (context, addr & 0xfffffffc); - if (!reg_image.exception_occurred) -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - word = word; - break; - - case 1: - word = ((word & 0xffffff) << 8) | (reg_val & 0xff); - break; - - case 2: - word = ((word & 0xffff) << 16) | (reg_val & 0xffff); - break; - - case 3: - word = ((word & 0xff) << 24) | (reg_val & 0xffffff); - break; - } -#else - switch (byte) - { - case 0: - word = ((word & 0xff) << 24) | (reg_val & 0xffffff); - break; - - case 1: - word = ((word & 0xffff) << 16) | (reg_val & 0xffff); - break; - - case 2: - word = ((word & 0xffffff) << 8) | (reg_val & 0xff); - break; - - case 3: - break; - } -#endif - LOAD_INST_BASE (®_image.R[RT (inst)], word); - break; - } - - case Y_LWR_OP: - { - mem_addr addr = reg_image.R[BASE (inst)] + IOFFSET (inst); - reg_word word; /* Can't be register */ - int byte = addr & 0x3; - reg_word reg_val = reg_image.R[RT (inst)]; - - word = read_mem_word (context, addr & 0xfffffffc); - if (!reg_image.exception_occurred) -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - word = (reg_val & 0xffffff00) | ((unsigned)(word & 0xff000000) >> 24); - break; - - case 1: - word = (reg_val & 0xffff0000) | ((unsigned)(word & 0xffff0000) >> 16); - break; - - case 2: - word = (reg_val & 0xff000000) | ((unsigned)(word & 0xffffff00) >> 8); - break; - - case 3: - word = word; - break; - } -#else - switch (byte) - { - case 0: - break; - - case 1: - word = (reg_val & 0xff000000) | ((word & 0xffffff00) >> 8); - break; - - case 2: - word = (reg_val & 0xffff0000) | ((word & 0xffff0000) >> 16); - break; - - case 3: - word = (reg_val & 0xffffff00) | ((word & 0xff000000) >> 24); - break; - } -#endif - LOAD_INST_BASE (®_image.R[RT (inst)], word); - break; - } - - case Y_MADD_OP: - case Y_MADDU_OP: - { - reg_word lo = reg_image.LO, hi = reg_image.HI; - reg_word tmp; - if (OPCODE (inst) == Y_MADD_OP) - { - signed_multiply(context, reg_image.R[RS (inst)], reg_image.R[RT (inst)]); - } - else /* Y_MADDU_OP */ - { - unsigned_multiply(context, reg_image.R[RS (inst)], reg_image.R[RT (inst)]); - } - tmp = lo + reg_image.LO; - if ((unsigned)tmp < (unsigned)reg_image.LO || (unsigned)tmp < (unsigned)lo) - { - /* Addition of low-order word overflows */ - hi += 1; - } - reg_image.LO = tmp; - reg_image.HI = hi + reg_image.HI; - break; - } - - case Y_MFC0_OP: - reg_image.R[RT (inst)] = reg_image.CPR[0][FS (inst)]; - break; - - case Y_MFC2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_MFHI_OP: - reg_image.R[RD (inst)] = reg_image.HI; - break; - - case Y_MFLO_OP: - reg_image.R[RD (inst)] = reg_image.LO; - break; - - case Y_MOVN_OP: - if (reg_image.R[RT (inst)] != 0) - reg_image.R[RD (inst)] = reg_image.R[RS (inst)]; - break; - - case Y_MOVZ_OP: - if (reg_image.R[RT (inst)] == 0) - reg_image.R[RD (inst)] = reg_image.R[RS (inst)]; - break; - - case Y_MSUB_OP: - case Y_MSUBU_OP: - { - reg_word lo = reg_image.LO, hi = reg_image.HI; - reg_word tmp; - - if (OPCODE (inst) == Y_MSUB_OP) - { - signed_multiply(context, reg_image.R[RS (inst)], reg_image.R[RT (inst)]); - } - else /* Y_MSUBU_OP */ - { - unsigned_multiply(context, reg_image.R[RS (inst)], reg_image.R[RT (inst)]); - } - - tmp = lo - reg_image.LO; - if ((unsigned)reg_image.LO > (unsigned)lo) - { - /* Subtraction of low-order word borrows */ - hi -= 1; - } - reg_image.LO = tmp; - reg_image.HI = hi - reg_image.HI; - break; - } - - case Y_MTC0_OP: - reg_image.CPR[0][FS (inst)] = reg_image.R[RT (inst)]; - switch (FS (inst)) - { - case CP0_Compare_Reg: - CP0_Cause(reg_image) &= ~CP0_Cause_IP7; /* Writing clears HW interrupt 5 */ - break; - - case CP0_Status_Reg: - CP0_Status(reg_image) &= CP0_Status_Mask; - CP0_Status(reg_image) |= ((CP0_Status_CU & 0x30000000) | CP0_Status_UM); - break; - - case CP0_Cause_Reg: - reg_image.CPR[0][FS (inst)] &= CP0_Cause_Mask; - break; - - case CP0_Config_Reg: - reg_image.CPR[0][FS (inst)] &= CP0_Config_Mask; - break; - - default: - break; - } - break; - - case Y_MTC2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_MTHI_OP: - reg_image.HI = reg_image.R[RS (inst)]; - break; - - case Y_MTLO_OP: - reg_image.LO = reg_image.R[RS (inst)]; - break; - - case Y_MUL_OP: - signed_multiply(context, reg_image.R[RS (inst)], reg_image.R[RT (inst)]); - reg_image.R[RD (inst)] = reg_image.LO; - break; - - case Y_MULT_OP: - signed_multiply(context, reg_image.R[RS (inst)], reg_image.R[RT (inst)]); - break; - - case Y_MULTU_OP: - unsigned_multiply (context, reg_image.R[RS (inst)], reg_image.R[RT (inst)]); - break; - - case Y_NOR_OP: - reg_image.R[RD (inst)] = ~ (reg_image.R[RS (inst)] | reg_image.R[RT (inst)]); - break; - - case Y_OR_OP: - reg_image.R[RD (inst)] = reg_image.R[RS (inst)] | reg_image.R[RT (inst)]; - break; - - case Y_ORI_OP: - reg_image.R[RT (inst)] = reg_image.R[RS (inst)] | (0xffff & IMM (inst)); - break; - - case Y_PREF_OP: - break; /* Memory details not implemented */ - - case Y_RFE_OP: -#ifdef MIPS1 - /* This is MIPS-I, not compatible with MIPS32 or the - definition of the bits in the CP0 Status register in that - architecture. */ - CP0_Status(reg_image) = (CP0_Status(reg_image) & 0xfffffff0) | ((CP0_Status(reg_image) & 0x3c) >> 2); -#else - RAISE_EXCEPTION (reg_image, ExcCode_RI, {}); /* Not MIPS32 instruction */ -#endif - break; - - case Y_SB_OP: - set_mem_byte (context, reg_image.R[BASE (inst)] + IOFFSET (inst), reg_image.R[RT (inst)]); - break; - - case Y_SC_OP: - /* Uniprocessor, so instruction is just a store */ - set_mem_word (context, reg_image.R[BASE (inst)] + IOFFSET (inst), reg_image.R[RT (inst)]); - break; - - case Y_SDC2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_SH_OP: - set_mem_half (context, reg_image.R[BASE (inst)] + IOFFSET (inst), reg_image.R[RT (inst)]); - break; - - case Y_SLL_OP: - { - int shamt = SHAMT (inst); - - if (shamt >= 0 && shamt < 32) - reg_image.R[RD (inst)] = reg_image.R[RT (inst)] << shamt; - else - reg_image.R[RD (inst)] = reg_image.R[RT (inst)]; - break; - } - - case Y_SLLV_OP: - { - int shamt = (reg_image.R[RS (inst)] & 0x1f); - - if (shamt >= 0 && shamt < 32) - reg_image.R[RD (inst)] = reg_image.R[RT (inst)] << shamt; - else - reg_image.R[RD (inst)] = reg_image.R[RT (inst)]; - break; - } - - case Y_SLT_OP: - if (reg_image.R[RS (inst)] < reg_image.R[RT (inst)]) - reg_image.R[RD (inst)] = 1; - else - reg_image.R[RD (inst)] = 0; - break; - - case Y_SLTI_OP: - if (reg_image.R[RS (inst)] < (short) IMM (inst)) - reg_image.R[RT (inst)] = 1; - else - reg_image.R[RT (inst)] = 0; - break; - - case Y_SLTIU_OP: - { - int x = (short) IMM (inst); - - if ((u_reg_word) reg_image.R[RS (inst)] < (u_reg_word) x) - reg_image.R[RT (inst)] = 1; - else - reg_image.R[RT (inst)] = 0; - break; - } - - case Y_SLTU_OP: - if ((u_reg_word) reg_image.R[RS (inst)] < (u_reg_word) reg_image.R[RT (inst)]) - reg_image.R[RD (inst)] = 1; - else - reg_image.R[RD (inst)] = 0; - break; - - case Y_SRA_OP: - { - int shamt = SHAMT (inst); - reg_word val = reg_image.R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - reg_image.R[RD (inst)] = val >> shamt; - else - reg_image.R[RD (inst)] = val; - break; - } - - case Y_SRAV_OP: - { - int shamt = reg_image.R[RS (inst)] & 0x1f; - reg_word val = reg_image.R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - reg_image.R[RD (inst)] = val >> shamt; - else - reg_image.R[RD (inst)] = val; - break; - } - - case Y_SRL_OP: - { - int shamt = SHAMT (inst); - u_reg_word val = reg_image.R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - reg_image.R[RD (inst)] = val >> shamt; - else - reg_image.R[RD (inst)] = val; - break; - } - - case Y_SRLV_OP: - { - int shamt = reg_image.R[RS (inst)] & 0x1f; - u_reg_word val = reg_image.R[RT (inst)]; - - if (shamt >= 0 && shamt < 32) - reg_image.R[RD (inst)] = val >> shamt; - else - reg_image.R[RD (inst)] = val; - break; - } - - case Y_SUB_OP: - { - reg_word vs = reg_image.R[RS (inst)], vt = reg_image.R[RT (inst)]; - reg_word diff = vs - vt; - - if (SIGN_BIT (vs) != SIGN_BIT (vt) - && SIGN_BIT (vs) != SIGN_BIT (diff)) - RAISE_EXCEPTION (reg_image, ExcCode_Ov, break); - reg_image.R[RD (inst)] = diff; - break; - } - - case Y_SUBU_OP: - reg_image.R[RD (inst)] = (u_reg_word)reg_image.R[RS (inst)]-(u_reg_word)reg_image.R[RT (inst)]; - break; - - case Y_SW_OP: - set_mem_word (context, reg_image.R[BASE (inst)] + IOFFSET (inst), reg_image.R[RT (inst)]); - break; - - case Y_SWC2_OP: - RAISE_EXCEPTION (reg_image, ExcCode_CpU, {}); /* No Coprocessor 2 */ - break; - - case Y_SWL_OP: - { - mem_addr addr = reg_image.R[BASE (inst)] + IOFFSET (inst); - mem_word data; - reg_word reg = reg_image.R[RT (inst)]; - int byte = addr & 0x3; - - data = read_mem_word (context, addr & 0xfffffffc); -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - data = reg; - break; - - case 1: - data = (data & 0xff000000) | (reg >> 8 & 0xffffff); - break; - - case 2: - data = (data & 0xffff0000) | (reg >> 16 & 0xffff); - break; - - case 3: - data = (data & 0xffffff00) | (reg >> 24 & 0xff); - break; - } -#else - switch (byte) - { - case 0: - data = (data & 0xffffff00) | (reg >> 24 & 0xff); - break; - - case 1: - data = (data & 0xffff0000) | (reg >> 16 & 0xffff); - break; - - case 2: - data = (data & 0xff000000) | (reg >> 8 & 0xffffff); - break; - - case 3: - data = reg; - break; - } -#endif - set_mem_word (context, addr & 0xfffffffc, data); - break; - } - - case Y_SWR_OP: - { - mem_addr addr = reg_image.R[BASE (inst)] + IOFFSET (inst); - mem_word data; - reg_word reg = reg_image.R[RT (inst)]; - int byte = addr & 0x3; - - data = read_mem_word (context, addr & 0xfffffffc); -#ifdef SPIM_BIGENDIAN - switch (byte) - { - case 0: - data = ((reg << 24) & 0xff000000) | (data & 0xffffff); - break; - - case 1: - data = ((reg << 16) & 0xffff0000) | (data & 0xffff); - break; - - case 2: - data = ((reg << 8) & 0xffffff00) | (data & 0xff) ; - break; - - case 3: - data = reg; - break; - } -#else - switch (byte) - { - case 0: - data = reg; - break; - - case 1: - data = ((reg << 8) & 0xffffff00) | (data & 0xff) ; - break; - - case 2: - data = ((reg << 16) & 0xffff0000) | (data & 0xffff); - break; - - case 3: - data = ((reg << 24) & 0xff000000) | (data & 0xffffff); - break; - } -#endif - set_mem_word (context, addr & 0xfffffffc, data); - break; - } - - case Y_SYNC_OP: - break; /* Memory details not implemented */ - - case Y_SYSCALL_OP: - if (!do_syscall (context)) - return false; - break; - - case Y_TEQ_OP: - if (reg_image.R[RS (inst)] == reg_image.R[RT (inst)]) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TEQI_OP: - if (reg_image.R[RS (inst)] == IMM (inst)) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TGE_OP: - if (reg_image.R[RS (inst)] >= reg_image.R[RT (inst)]) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TGEI_OP: - if (reg_image.R[RS (inst)] >= IMM (inst)) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TGEIU_OP: - if ((u_reg_word)reg_image.R[RS (inst)] >= (u_reg_word)IMM (inst)) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TGEU_OP: - if ((u_reg_word)reg_image.R[RS (inst)] >= (u_reg_word)reg_image.R[RT (inst)]) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TLBP_OP: - RAISE_EXCEPTION(reg_image, ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBR_OP: - RAISE_EXCEPTION(reg_image, ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBWI_OP: - RAISE_EXCEPTION(reg_image, ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLBWR_OP: - RAISE_EXCEPTION(reg_image, ExcCode_RI, {}); /* TLB not implemented */ - break; - - case Y_TLT_OP: - if (reg_image.R[RS (inst)] < reg_image.R[RT (inst)]) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TLTI_OP: - if (reg_image.R[RS (inst)] < IMM (inst)) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TLTIU_OP: - if ((u_reg_word)reg_image.R[RS (inst)] < (u_reg_word)IMM (inst)) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TLTU_OP: - if ((u_reg_word)reg_image.R[RS (inst)] < (u_reg_word)reg_image.R[RT (inst)]) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TNE_OP: - if (reg_image.R[RS (inst)] != reg_image.R[RT (inst)]) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_TNEI_OP: - if (reg_image.R[RS (inst)] != IMM (inst)) - RAISE_EXCEPTION(reg_image, ExcCode_Tr, {}); - break; - - case Y_XOR_OP: - reg_image.R[RD (inst)] = reg_image.R[RS (inst)] ^ reg_image.R[RT (inst)]; - break; - - case Y_XORI_OP: - reg_image.R[RT (inst)] = reg_image.R[RS (inst)] ^ (0xffff & IMM (inst)); - break; - - - /* FPA Operations */ - - case Y_ABS_S_OP: - SET_FPR_S (reg_image, FD (inst), fabs (FPR_S (reg_image, FS (inst)))); - break; - - case Y_ABS_D_OP: - SET_FPR_D (reg_image, FD (inst), fabs (FPR_D (reg_image, FS (inst)))); - break; - - case Y_ADD_S_OP: - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst)) + FPR_S (reg_image, FT (inst))); - /* Should trap on inexact/overflow/underflow */ - break; - - case Y_ADD_D_OP: - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst)) + FPR_D (reg_image, FT (inst))); - /* Should trap on inexact/overflow/underflow */ - break; - - case Y_BC1F_OP: - case Y_BC1FL_OP: - case Y_BC1T_OP: - case Y_BC1TL_OP: - { - int cc = CC (inst); - int nd = ND (inst); /* 1 => nullify */ - int tf = TF (inst); /* 0 => BC1F, 1 => BC1T */ - BRANCH_INST ((FCCR(reg_image) & (1 << cc)) == (tf << cc), - reg_image.PC + IDISP (inst), - nd); - break; - } - - case Y_C_F_S_OP: - case Y_C_UN_S_OP: - case Y_C_EQ_S_OP: - case Y_C_UEQ_S_OP: - case Y_C_OLT_S_OP: - case Y_C_OLE_S_OP: - case Y_C_ULT_S_OP: - case Y_C_ULE_S_OP: - case Y_C_SF_S_OP: - case Y_C_NGLE_S_OP: - case Y_C_SEQ_S_OP: - case Y_C_NGL_S_OP: - case Y_C_LT_S_OP: - case Y_C_NGE_S_OP: - case Y_C_LE_S_OP: - case Y_C_NGT_S_OP: - { - float v1 = FPR_S (reg_image, FS (inst)), v2 = FPR_S (reg_image, FT (inst)); - double dv1 = v1, dv2 = v2; - int cond = COND (inst); - int cc = FD (inst); - - if (NaN (dv1) || NaN (dv2)) - { - if (cond & COND_IN) - { - RAISE_EXCEPTION (reg_image, ExcCode_FPE, break); - } - set_fpu_cc (context, cond, cc, 0, 0, 1); - } - else - { - set_fpu_cc (context, cond, cc, v1 < v2, v1 == v2, 0); - } - } - break; - - case Y_C_F_D_OP: - case Y_C_UN_D_OP: - case Y_C_EQ_D_OP: - case Y_C_UEQ_D_OP: - case Y_C_OLT_D_OP: - case Y_C_OLE_D_OP: - case Y_C_ULT_D_OP: - case Y_C_ULE_D_OP: - case Y_C_SF_D_OP: - case Y_C_NGLE_D_OP: - case Y_C_SEQ_D_OP: - case Y_C_NGL_D_OP: - case Y_C_LT_D_OP: - case Y_C_NGE_D_OP: - case Y_C_LE_D_OP: - case Y_C_NGT_D_OP: - { - double v1 = FPR_D (reg_image, FS (inst)), v2 = FPR_D (reg_image, FT (inst)); - int cond = COND (inst); - int cc = FD (inst); - - if (NaN (v1) || NaN (v2)) - { - if (cond & COND_IN) - { - RAISE_EXCEPTION (reg_image, ExcCode_FPE, break); - } - set_fpu_cc (context, cond, cc, 0, 0, 1); - } - else - { - set_fpu_cc (context, cond, cc, v1 < v2, v1 == v2, 0); - } - } - break; - - case Y_CFC1_OP: - reg_image.R[RT (inst)] = FCR(reg_image)[FS (inst)]; - break; - - case Y_CTC1_OP: - FCR(reg_image)[FS (inst)] = reg_image.R[RT (inst)]; - - if (FIR_REG == FS (inst)) - { - /* Read only register */ - FIR(reg_image) = FIR_MASK; - } - else if (FCCR_REG == FS (inst)) - { - /* FCC bits in FCSR and FCCR linked */ - FCSR(reg_image) = (FCSR(reg_image) & ~0xfe400000) - | ((FCCR(reg_image) & 0xfe) << 24) - | ((FCCR(reg_image) & 0x1) << 23); - FCCR(reg_image) &= FCCR_MASK; - } - else if (FCSR_REG == FS (inst)) - { - /* FCC bits in FCSR and FCCR linked */ - FCCR(reg_image) = ((FCSR(reg_image) >> 24) & 0xfe) | ((FCSR(reg_image) >> 23) & 0x1); - FCSR(reg_image) &= FCSR_MASK; - if ((reg_image.R[RT (inst)] & ~FCSR_MASK) != 0) - /* Trying to set unsupported mode */ - RAISE_EXCEPTION (reg_image, ExcCode_FPE, {}); - } - break; - - case Y_CEIL_W_D_OP: - { - double val = FPR_D (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), (int32)ceil (val)); - break; - } - - case Y_CEIL_W_S_OP: - { - double val = (double)FPR_S (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), (int32)ceil (val)); - break; - } - - case Y_CVT_D_S_OP: - { - double val = FPR_S (reg_image, FS (inst)); - - SET_FPR_D (reg_image, FD (inst), val); - break; - } - - case Y_CVT_D_W_OP: - { - double val = (double)FPR_W (reg_image, FS (inst)); - - SET_FPR_D (reg_image, FD (inst), val); - break; - } - - case Y_CVT_S_D_OP: - { - float val = (float)FPR_D (reg_image, FS (inst)); - - SET_FPR_S (reg_image, FD (inst), val); - break; - } - - case Y_CVT_S_W_OP: - { - float val = (float)FPR_W (reg_image, FS (inst)); - - SET_FPR_S (reg_image, FD (inst), val); - break; - } - - case Y_CVT_W_D_OP: - { - int val = (int32)FPR_D (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), val); - break; - } - - case Y_CVT_W_S_OP: - { - int val = (int32)FPR_S (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), val); - break; - } - - case Y_DIV_S_OP: - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst)) / FPR_S (reg_image, FT (inst))); - break; - - case Y_DIV_D_OP: - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst)) / FPR_D (reg_image, FT (inst))); - break; - - case Y_FLOOR_W_D_OP: - { - double val = FPR_D (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), (int32)floor (val)); - break; - } - - case Y_FLOOR_W_S_OP: - { - double val = (double)FPR_S (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), (int32)floor (val)); - break; - } - - case Y_LDC1_OP: - { - mem_addr addr = reg_image.R[BASE (inst)] + IOFFSET (inst); - if ((addr & 0x3) != 0) - RAISE_EXCEPTION (reg_image, ExcCode_AdEL, CP0_BadVAddr(reg_image) = addr); - - LOAD_INST ((reg_word *) &FPR_S(reg_image, FT (inst)), - read_mem_word (context, addr), - 0xffffffff); - LOAD_INST ((reg_word *) &FPR_S(reg_image, FT (inst) + 1), - read_mem_word (context, addr + sizeof(mem_word)), - 0xffffffff); - break; - } - - case Y_LWC1_OP: - LOAD_INST ((reg_word *) &FPR_S(reg_image, FT (inst)), - read_mem_word (context, reg_image.R[BASE (inst)] + IOFFSET (inst)), - 0xffffffff); - break; - - case Y_MFC1_OP: - { - float val = FPR_S(reg_image, FS (inst)); - reg_word *vp = (reg_word *) &val; - - reg_image.R[RT (inst)] = *vp; /* Fool coercion */ - break; - } - - case Y_MOV_S_OP: - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst))); - break; - - case Y_MOV_D_OP: - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst))); - break; - - case Y_MOVF_OP: - { - int cc = CC (inst); - if ((FCCR(reg_image) & (1 << cc)) == 0) - reg_image.R[RD (inst)] = reg_image.R[RS (inst)]; - break; - } - - case Y_MOVF_D_OP: - { - int cc = CC (inst); - if ((FCCR(reg_image) & (1 << cc)) == 0) - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst))); - break; - } - - case Y_MOVF_S_OP: - { - int cc = CC (inst); - if ((FCCR(reg_image) & (1 << cc)) == 0) - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst))); - break; - - } - - case Y_MOVN_D_OP: - { - if (reg_image.R[RT (inst)] != 0) - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst))); - break; - } - - case Y_MOVN_S_OP: - { - if (reg_image.R[RT (inst)] != 0) - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst))); - break; - } - - case Y_MOVT_OP: - { - int cc = CC (inst); - if ((FCCR(reg_image) & (1 << cc)) != 0) - reg_image.R[RD (inst)] = reg_image.R[RS (inst)]; - break; - } - - case Y_MOVT_D_OP: - { - int cc = CC (inst); - if ((FCCR(reg_image) & (1 << cc)) != 0) - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst))); - break; - } - - case Y_MOVT_S_OP: - { - int cc = CC (inst); - if ((FCCR(reg_image) & (1 << cc)) != 0) - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst))); - break; - - } - - case Y_MOVZ_D_OP: - { - if (reg_image.R[RT (inst)] == 0) - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst))); - break; - } - - case Y_MOVZ_S_OP: - { - if (reg_image.R[RT (inst)] == 0) - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst))); - break; - - } - - case Y_MTC1_OP: - { - reg_word word = reg_image.R[RT (inst)]; - float *wp = (float *) &word; - - SET_FPR_S(reg_image, FS (inst), *wp); /* fool coercion */ - break; - } - - case Y_MUL_S_OP: - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst)) * FPR_S (reg_image, FT (inst))); - break; - - case Y_MUL_D_OP: - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst)) * FPR_D (reg_image, FT (inst))); - break; - - case Y_NEG_S_OP: - SET_FPR_S (reg_image, FD (inst), -FPR_S (reg_image, FS (inst))); - break; - - case Y_NEG_D_OP: - SET_FPR_D (reg_image, FD (inst), -FPR_D (reg_image, FS (inst))); - break; - - case Y_ROUND_W_D_OP: - { - double val = FPR_D (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), (int32)(val + 0.5)); /* Casting truncates */ - break; - } - - case Y_ROUND_W_S_OP: - { - double val = (double)FPR_S (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), (int32)(val + 0.5)); /* Casting truncates */ - break; - } - - case Y_SDC1_OP: - { - double val = FPR_D (reg_image, RT (inst)); - reg_word *vp = (reg_word*)&val; - mem_addr addr = reg_image.R[BASE (inst)] + IOFFSET (inst); - if ((addr & 0x3) != 0) - RAISE_EXCEPTION (reg_image, ExcCode_AdEL, CP0_BadVAddr(reg_image) = addr); - - set_mem_word (context, addr, *vp); - set_mem_word (context, addr + sizeof(mem_word), *(vp + 1)); - break; - } - - case Y_SQRT_D_OP: - SET_FPR_D (reg_image, FD (inst), sqrt (FPR_D (reg_image, FS (inst)))); - break; - - case Y_SQRT_S_OP: - SET_FPR_S (reg_image, FD (inst), sqrt (FPR_S (reg_image, FS (inst)))); - break; - - case Y_SUB_S_OP: - SET_FPR_S (reg_image, FD (inst), FPR_S (reg_image, FS (inst)) - FPR_S (reg_image, FT (inst))); - break; - - case Y_SUB_D_OP: - SET_FPR_D (reg_image, FD (inst), FPR_D (reg_image, FS (inst)) - FPR_D (reg_image, FT (inst))); - break; - - case Y_SWC1_OP: - { - float val = FPR_S(reg_image, RT (inst)); - reg_word *vp = (reg_word *) &val; - - set_mem_word (context, reg_image.R[BASE (inst)] + IOFFSET (inst), *vp); - break; - } - - case Y_TRUNC_W_D_OP: - { - double val = FPR_D (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), (int32)val); /* Casting truncates */ - break; - } - - case Y_TRUNC_W_S_OP: - { - double val = (double)FPR_S (reg_image, FS (inst)); - - SET_FPR_W (reg_image, FD (inst), (int32)val); /* Casting truncates */ - break; - } - - default: - fatal_error ("Unknown instruction type: %d\n", OPCODE (inst)); - break; - } - - /* After instruction executes: */ - reg_image.PC += BYTES_PER_WORD; - - if (reg_image.exception_occurred) - { - if ((CP0_Cause(reg_image) >> 2) > LAST_REAL_EXCEPT) - CP0_EPC(reg_image) = reg_image.PC - BYTES_PER_WORD; - handle_exception (reg_image); - } - - return true; -} - - -/* Multiply two 32-bit numbers, V1 and V2, to produce a 64 bit result in - the HI/LO registers. The algorithm is high-school math: - - A B - x C D - ------ - AD || BD - AC || CB || 0 - - where A and B are the high and low short words of V1, C and D are the short - words of V2, AD is the product of A and D, and X || Y is (X << 16) + Y. - Since the algorithm is programmed in C, we need to be careful not to - overflow. */ - -static void -unsigned_multiply (size_t context, reg_word v1, reg_word v2) -{ - reg_image_t ®_image = reg_images[context]; - - u_reg_word a, b, c, d; - u_reg_word bd, ad, cb, ac; - u_reg_word mid, mid2, carry_mid = 0; - - a = (v1 >> 16) & 0xffff; - b = v1 & 0xffff; - c = (v2 >> 16) & 0xffff; - d = v2 & 0xffff; - - bd = b * d; - ad = a * d; - cb = c * b; - ac = a * c; - - mid = ad + cb; - if (mid < ad || mid < cb) - /* Arithmetic overflow or carry-out */ - carry_mid = 1; - - mid2 = mid + ((bd >> 16) & 0xffff); - if (mid2 < mid || mid2 < ((bd >> 16) & 0xffff)) - /* Arithmetic overflow or carry-out */ - carry_mid += 1; - - reg_image.LO = (bd & 0xffff) | ((mid2 & 0xffff) << 16); - reg_image.HI = ac + (carry_mid << 16) + ((mid2 >> 16) & 0xffff); -} - - -static void -signed_multiply (size_t context, reg_word v1, reg_word v2) -{ - reg_image_t ®_image = reg_images[context]; - - int neg_sign = 0; - - if (v1 < 0) - { - v1 = - v1; - neg_sign = 1; - } - if (v2 < 0) - { - v2 = - v2; - neg_sign = ! neg_sign; - } - - unsigned_multiply (context, v1, v2); - if (neg_sign) - { - reg_image.LO = ~ reg_image.LO; - reg_image.HI = ~ reg_image.HI; - reg_image.LO += 1; - if (reg_image.LO == 0) - reg_image.HI += 1; - } -} - -static void -set_fpu_cc (size_t context, int cond, int cc, int less, int equal, int unordered) -{ - reg_image_t ®_image = reg_images[context]; - - int result; - int fcsr_bit; - - result = 0; - if (cond & COND_LT) result |= less; - if (cond & COND_EQ) result |= equal; - if (cond & COND_UN) result |= unordered; - - FCCR(reg_image) = (FCCR(reg_image) & ~(1 << cc)) | (result << cc); - if (0 == cc) - { - fcsr_bit = 23; - } - else - { - fcsr_bit = 24 + cc; - } - FCSR(reg_image) = (FCSR(reg_image) & ~(1 << fcsr_bit)) | (result << fcsr_bit); -} - - -void -raise_exception (size_t context, int excode) -{ - reg_image_t ®_image = reg_images[context]; - - if (ExcCode_Int != excode - || ((CP0_Status(reg_image) & CP0_Status_IE) /* Allow interrupt if IE and !EXL */ - && !(CP0_Status(reg_image) & CP0_Status_EXL))) - { - /* Ignore interrupt exception when interrupts disabled. */ - reg_image.exception_occurred = 1; - last_exception_addr = reg_image.PC; - if (running_in_delay_slot) - { - /* In delay slot */ - if ((CP0_Status(reg_image) & CP0_Status_EXL) == 0) - { - /* Branch's addr */ - CP0_EPC(reg_image) = ROUND_DOWN (reg_image.PC - BYTES_PER_WORD, BYTES_PER_WORD); - /* Set BD bit to record that instruction is in delay slot */ - CP0_Cause(reg_image) |= CP0_Cause_BD; - } - } - else - { - /* Not in delay slot */ - if ((CP0_Status(reg_image) & CP0_Status_EXL) == 0) - { - /* Faulting instruction's address */ - CP0_EPC(reg_image) = ROUND_DOWN (reg_image.PC, BYTES_PER_WORD); - } - } - /* ToDo: set CE field of Cause register to coprocessor causing exception */ - - /* Record cause of exception */ - CP0_Cause(reg_image) = (CP0_Cause(reg_image) & ~CP0_Cause_ExcCode) | (excode << 2); - - /* Turn on EXL bit to prevent subsequent interrupts from affecting EPC */ - CP0_Status(reg_image) |= CP0_Status_EXL; - -#ifdef MIPS1 - CP0_Status(reg_image) = (CP0_Status(reg_image) & 0xffffffc0) | ((CP0_Status(reg_image) & 0xf) << 2); -#endif - } -} diff --git a/spim-qtspimbot/CPU/run.h b/spim-qtspimbot/CPU/run.h deleted file mode 100755 index 54ddcb4..0000000 --- a/spim-qtspimbot/CPU/run.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM instructions. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions: */ - -bool run_spim (size_t context, bool display); diff --git a/spim-qtspimbot/CPU/scanner.h b/spim-qtspimbot/CPU/scanner.h deleted file mode 100755 index 6231de2..0000000 --- a/spim-qtspimbot/CPU/scanner.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to lexical scanner. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions (besides yylex): */ - -void initialize_scanner (FILE *in_file, char *in_file_name); -void push_scanner (FILE *in_file); -void pop_scanner (); -char* erroneous_line (); -void scanner_start_line (); -int register_name_to_number (char *name); -char *source_line (); -int yylex (); - -/* Exported Variables: */ - -/* This flag tells the scanner to treat the next sequence of letters - etc as an identifier and not look it up as an opcode. It permits us - to use opcodes as symbols in most places. However, because of the - LALR(1) lookahead, it does not work for labels. */ - -extern int only_id; - -typedef intptr_union yylval_t; -#define YYSTYPE yylval_t -extern YYSTYPE yylval; /* Value of token from YYLEX */ - -extern int line_no; /* Line number in input file*/ diff --git a/spim-qtspimbot/CPU/scanner.l b/spim-qtspimbot/CPU/scanner.l deleted file mode 100755 index 136522e..0000000 --- a/spim-qtspimbot/CPU/scanner.l +++ /dev/null @@ -1,738 +0,0 @@ -%{ -/* SPIM S20 MIPS simulator. - Lexical scanner. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "sym-tbl.h" -#include "parser.h" -#include "scanner.h" -#include "parser_yacc.h" - -#ifdef _WIN32 -#include -#else -#include -#endif - -#define YY_NO_UNISTD_H - -/* Exported Variables: */ - -int only_id; -int line_no; /* Line number in input file*/ - - -/* Local Variables: */ -static char *file_name; /* The name of the current file */ -static int file_name_len; /* To avoid recomputing for each source line */ - -/* Track which line we are reading and where it began in the buffer. */ -static int current_line_no = 0; - -static char *current_line = NULL; - - -static double scan_float; /* Where FP values are kept */ - -static int line_returned = 0; /* Returned current line yet? */ - -static int eof_returned = 0; /* Return EOF token yet? */ - - -/* Local functions: */ - -static int check_keyword (char *id, int allow_pseudo_ops); -static char *copy_str (char *str, int chop); -static char scan_escape (char **str); - - -#undef yywrap - -%} - -%% - -[ \t] { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - } - - -[\n] { - line_no += 1; - return (Y_NL); - } - -[\r] { /* Ignore carrage returns */ } - -[;] { - return (Y_NL); - } - - -[\001] { /* Marker character inserted to allow scanner to - return Y_EOF before returning hard EOF. */ - return (Y_EOF); - } - -"#".* { - /* Ignore comments */ - } - - -(-[0-9]+)|([0-9]+) { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.i = atoi (yytext); - return (Y_INT); - } - - -((0x)|(-0x))[0-9A-Fa-f]+ { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - if (*yytext == '-') - { - sscanf(yytext+3, "%x", (unsigned int*)&(yylval.i)); - yylval.i = -yylval.i; - } - else - { - sscanf(yytext+2, "%x", (unsigned int*)&(yylval.i)); - } - return (Y_INT); - } - - -(\+|\-)?[0-9]+[\.\,\'][0-9]+(e)?(\+|\-)?[0-9]* { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - scan_float = atof (yytext); - yylval.p = (double*) &scan_float; - return (Y_FP); - } - - -[a-zA-Z_\.][a-zA-Z0-9_\.]* { - int token = check_keyword (yytext, - !bare_machine - && accept_pseudo_insts); - label *l; - - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (!only_id && token != 0) - { - /* Keyword */ - yylval.i = token; - current_line = yytext; - return (token); - } - - if (only_id && token != 0) - yyerror ("Cannot use opcodes as labels"); - - if ((l = label_is_defined (yytext)) != NULL - && l->const_flag) - { - /* Defined label */ - yylval.i = (int) l->addr; - return (Y_INT); - } - else - { - /* Not-yet defined label */ - yylval.p = (char*) str_copy (yytext); - return (Y_ID); - } - } - - -\$[a-zA-Z0-9_\.$]+ { - int reg_no = register_name_to_number (yytext + 1); - - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (reg_no != -1 - && *(yytext + 1) == 'f' - && *(yytext + 2) != 'p') - { - /* Floating point register ($f0) */ - yylval.i = reg_no; - return (Y_FP_REG); - } - - if (0 <= reg_no && reg_no < R_LENGTH) - { - /* Register ($r0) */ - yylval.i = reg_no; - return (Y_REG); - } - else - { - /* Otherwise, an integer or identifier */ - label *l = label_is_defined (yytext); - - if (l != NULL && l->const_flag) - { - yylval.i = (int) l->addr; - return (Y_INT); - } - else - { - yylval.p = (char*) str_copy (yytext); - return (Y_ID); - } - } - } - - -[\*\/:()+-]|">"|"=" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - return (*yytext); - } - - -"," { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - /* Skip commas */ - } - -"?" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.p = (char*) str_copy (yytext); - /* For top level */ - return (Y_ID); - } - - -\"(([^""])|(\\\"))*\" { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yylval.p = (char*) copy_str (yytext + 1, 1); - return (Y_STR); - } - -\'(([^''])|(\\[^'']))\' { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - - if (*(yytext + 1) == '\\') - { - char *escape = yytext + 2; - yylval.i = (int) scan_escape (&escape); - } - else - { - yylval.i = (int) *(yytext + 1); - } - - return (Y_INT); - } - -. { - if (current_line == NULL) - { - current_line_no = line_no; - current_line = yytext; - } - yyerror ("Unknown character"); - } - - -%% - - - -void -initialize_scanner (FILE *in_file, char *in_file_name) -{ - if (yyin != in_file) - { - push_scanner (in_file); - } - yyin = in_file; - -#ifdef FLEX_SCANNER - yyrestart(in_file); -#define YY_FLEX_VERSION (YY_FLEX_MAJOR_VERSION * 1000 + YY_FLEX_MINOR_VERSION * 100 + YY_FLEX_SUBMINOR_VERSION) -#if YY_FLEX_VERSION >= 2533 - /* flex 2.5.33 flipped the polarity of this flag (sigh) */ - yy_init = 0; -#else - yy_init = 1; -#endif -#endif - - line_no = 1; - current_line = NULL; - line_returned = 0; - eof_returned = 0; - file_name = strdup(in_file_name); /* will leak some memory */ - file_name_len = strlen(file_name); -} - -void -push_scanner (FILE *in_file) -{ - YY_BUFFER_STATE buf = yy_create_buffer (in_file, YY_BUF_SIZE); - yypush_buffer_state (buf); -} - -void -pop_scanner () -{ - yypop_buffer_state (); -} - -void -scanner_start_line () -{ - current_line = NULL; - line_returned = 0; -} - - -/* This is a work-around for a bug in flex v 2.5.31 (but not earlier or - later versions such as 2.5.4) that left this symbol undefined. */ - -#ifndef yytext_ptr -#define yytext_ptr yytext -#endif - - -/* Use yywrap to insert a marker character, which causes the - scanner to return Y_EOF, before return a hard EOF. This - wouldn't be necessary, except that bison does not allow - the parser to use EOF (= 0) as a non-terminal */ - -int yywrap() -{ - if (eof_returned) - return (1); - else - { - unput ('\001'); - eof_returned = 1; -#ifdef FLEX_SCANNER - yy_did_buffer_switch_on_eof = 1; -#endif - return (0); - } -} - - -/* A backslash has just been read, return the character designated by *STR. */ - -static char -scan_escape (char **str) -{ - char first = **str; - *str += 1; - switch (first) - { - case 'a': return '\a'; - case 'b': return '\b'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case '\\': return '\\'; - case '"': return '"'; - case '\'': return '\''; - - case 'x': - case 'X': - { - char c1 = **str, c2 = *(*str + 1); - int b = 0; - - if ('0' <= c1 && c1 <= '9') b = c1 - '0'; - else if ('A' <= c1 && c1 <= 'F') b = c1 - 'A' + 10; - else if ('a' <= c1 && c1 <= 'f') b = c1 - 'a' + 10; - else yyerror ("Bad character in \\X construct in string"); - - b <<= 4; - if ('0' <= c2 && c2 <= '9') b += c2 - '0'; - else if ('A' <= c2 && c2 <= 'F') b += c2 - 'A' + 10; - else if ('a' <= c2 && c2 <= 'f') b += c2 - 'a' + 10; - else yyerror ("Bad character in \\X construct in string"); - - *str += 2; - return (char) b; - } - - default: - { - char message[] = "Bad character \\X"; - message[strlen (message) - 1] = first; - yyerror (message); - return '\0'; - } - } -} - - -/* Return a freshly-allocated copy of STRING with the last CHOP - characters removed. */ - -static char * -copy_str (char *str, int chop) -{ - int new_len = strlen (str) - chop; - char *new_str = (char *) xmalloc (new_len + 1), *n; - - for (n = new_str; *str != '\0' && new_len > 0; new_len -= 1) - if (*str == '\\') - switch (*(str + 1)) - { - case 'n': - { - *n ++ = '\n'; - str += 2; - new_len -= 1; - continue; - } - case 't': - { - *n ++ = '\t'; - str += 2; - new_len -= 1; - continue; - } - case '"': - { - *n ++ = '"'; - str += 2; - new_len -= 1; - continue; - } - case '0': /* \nnn */ - case '1': - case '2': - case '3': - { - char c2 = *(str + 2), c3 = *(str + 3); - int b = (*(str + 1) - '0') << 3; - - if ('0' <= c2 && c2 <= '7') - b += (c2 - '0') << 3; - else - yyerror ("Bad character in \\ooo construct in string"); - - if ('0' <= c3 && c3 <= '7') - b += c3 - '0'; - else - yyerror ("Bad character in \\ooo construct in string"); - - *n ++ = (char) b; - str += 4; - new_len -= 3; - continue; - } - case 'X': - { - char c2 = *(str + 2), c3 = *(str + 3); - int b = 0; - - if ('0' <= c2 && c2 <= '9') - b = c2 - '0'; - else if ('A' <= c2 && c2 <= 'F') - b = c2 - 'A' + 10; - else - yyerror ("Bad character in \\X construct in string"); - - b <<= 4; - if ('0' <= c3 && c3 <= '9') - b += c3 - '0'; - else if ('A' <= c3 && c3 <= 'F') - b += c3 - 'A' + 10; - else - yyerror ("Bad character in \\X construct in string"); - - *n ++ = (char) b; - str += 4; - new_len -= 3; - continue; - } - default: - { - *n ++ = *str ++; - continue; - } - } - else - *n ++ = *str ++; - - *n = '\0'; - return (new_str); -} - - -/* On a parse error, write out the current line and print a caret (^) - below the point at which the error occured. Also, reset the input - stream to the begining of the next line. */ - -char* -erroneous_line () -{ - int prefix_length = yytext - current_line; - int i, c; - str_stream ss; - - ss_init (&ss); - - if (current_line == NULL) return ss_to_string (&ss); - - /* Print part of line that has been consumed. */ - ss_printf (&ss, " "); - if (0 <= prefix_length) - { - /* yytext and current_line point to same line */ - c = *(current_line + prefix_length); - *(current_line + prefix_length) = '\0'; - ss_printf (&ss, "%s", current_line); - *(current_line + prefix_length) = (char)c; - ss_printf (&ss, "%s", yytext); - } - else - { - /* yytext and current_line point to different lines */ - ss_printf (&ss, "%s", current_line); - prefix_length = strlen(current_line); - } - - /* Flush the rest of the line (not consumed) from lex input. */ - if (*yytext != '\n') - { -#ifdef __cplusplus - while ((c = yyinput ()) != '\n' && c != EOF && c != 1) -#else - while ((c = input ()) != '\n' && c != EOF && c != 1) -#endif - { - ss_printf (&ss, "%c", c); - } - if (c == '\n') unput ('\n'); - current_line = NULL; - } - - /* Print marker to point at which consumption stopped. */ - ss_printf (&ss, "\n "); - for (i = 0; i < prefix_length; i ++) ss_printf (&ss, " "); - ss_printf (&ss, "^\n"); - - return ss_to_string (&ss); -} - - -static name_val_val keyword_tbl [] = { -#undef OP -#define OP(NAME, OPCODE, TYPE, R_OPCODE) {NAME, OPCODE, TYPE}, -#include "op.h" -}; - - -static int -check_keyword (char *id, int allow_pseudo_ops) -{ - name_val_val *entry = - map_string_to_name_val_val (keyword_tbl, - sizeof(keyword_tbl) / sizeof (name_val_val), - id); - if (entry == NULL) - return (0); - else if (!allow_pseudo_ops && entry->value2 == PSEUDO_OP) - return (0); - else - return (entry->value1); -} - - -static name_val_val register_tbl [] = { - {"a0", 4, 0}, - {"a1", 5, 0}, - {"a2", 6, 0}, - {"a3", 7, 0}, - {"at", 1, 0}, - {"fp", 30, 0}, - {"gp", 28, 0}, - {"k0", 26, 0}, - {"k1", 27, 0}, - {"kt0", 26, 0}, - {"kt1", 27, 0}, - {"ra", 31, 0}, - {"s0", 16, 0}, - {"s1", 17, 0}, - {"s2", 18, 0}, - {"s3", 19, 0}, - {"s4", 20, 0}, - {"s5", 21, 0}, - {"s6", 22, 0}, - {"s7", 23, 0}, - {"s8", 30, 0}, - {"sp", 29, 0}, - {"t0", 8, 0}, - {"t1", 9, 0}, - {"t2", 10, 0}, - {"t3", 11, 0}, - {"t4", 12, 0}, - {"t5", 13, 0}, - {"t6", 14, 0}, - {"t7", 15, 0}, - {"t8", 24, 0}, - {"t9", 25, 0}, - {"v0", 2, 0}, - {"v1", 3, 0}, - {"zero", 0, 0} -}; - -int -register_name_to_number (char *name) -{ - int c1 = *name, c2 = *(name + 1); - - if ('0' <= c1 && c1 <= '9' - && (c2 == '\0' || (('0' <= c2 && c2 <= '9') && *(name + 2) == '\0'))) - return (atoi (name)); - else if (c1 == 'f' && c2 >= '0' && c2 <= '9') - return atoi (name + 1); - else - { - name_val_val *entry = - map_string_to_name_val_val (register_tbl, - sizeof (register_tbl) / sizeof (name_val_val), - name); - if (entry == NULL) - return (-1); - else - return (entry->value1); - } -} - - -/* Exactly once, return the current source line, as a printable string - with a line number. Subsequent calls receive NULL instead of the - line. */ - -char * -source_line () -{ - if (line_returned) - return (NULL); - else if (current_line == NULL) /* Error on line */ - return (NULL); - else - { - char *eol1, c1; - char *null1 = NULL; - char *r; - - /* Find end of line: */ - for (eol1 = current_line; *eol1 != '\0' && *eol1 != '\n'; ) eol1 += 1; - -#ifdef FLEX_SCANNER - /* Ran into null byte, inserted by yylex. In necessary, look further - for newline. (This only works for scanners produced by flex. Other - versions of lex need similar code, or source code lines will end - early. */ - if (*eol1 == '\0' && yy_hold_char != '\n') - { - null1 = eol1; - *eol1 = yy_hold_char; - for ( ; *eol1 != '\0' && *eol1 != '\n'; ) - eol1 += 1; - } -#endif - - /* Save end-of-line character and null terminate string so it can - be printed. */ - c1 = *eol1; - *eol1 = '\0'; - - r = (char *) xmalloc (eol1 - current_line + 11 + file_name_len); - sprintf (r, "%s:%d: %s", file_name, current_line_no, current_line); - - /* Restore end-of-line character and, if necessary, yylex's null byte. */ - *eol1 = c1; - if (null1 != NULL) - { - *null1 = '\0'; - } - line_returned = 1; - return ((char *) r); - } -} diff --git a/spim-qtspimbot/CPU/spim-syscall.h b/spim-qtspimbot/CPU/spim-syscall.h deleted file mode 100644 index f350f07..0000000 --- a/spim-qtspimbot/CPU/spim-syscall.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPIM S20 MIPS simulator. - System calls implemented by simulator. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#define PRINT_INT_SYSCALL 1 -#define PRINT_FLOAT_SYSCALL 2 -#define PRINT_DOUBLE_SYSCALL 3 -#define PRINT_STRING_SYSCALL 4 -#define READ_INT_SYSCALL 5 -#define READ_FLOAT_SYSCALL 6 -#define READ_DOUBLE_SYSCALL 7 -#define READ_STRING_SYSCALL 8 -#define SBRK_SYSCALL 9 -#define EXIT_SYSCALL 10 -#define PRINT_CHARACTER_SYSCALL 11 -#define READ_CHARACTER_SYSCALL 12 - -#define OPEN_SYSCALL 13 -#define READ_SYSCALL 14 -#define WRITE_SYSCALL 15 -#define CLOSE_SYSCALL 16 - -#define EXIT2_SYSCALL 17 diff --git a/spim-qtspimbot/CPU/spim-utils.cpp b/spim-qtspimbot/CPU/spim-utils.cpp deleted file mode 100755 index 170cd6d..0000000 --- a/spim-qtspimbot/CPU/spim-utils.cpp +++ /dev/null @@ -1,658 +0,0 @@ -/* SPIM S20 MIPS simulator. - Misc. routines for SPIM. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include -#include -#include - -#include "spim.h" -#include "version.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "data.h" -#include "reg.h" -#include "mem.h" -#include "scanner.h" -#include "parser.h" -#include "parser_yacc.h" -#include "run.h" -#include "sym-tbl.h" - -#include "../Spimbot/robot.h" - -bkpt *bkpts = NULL; - -size_t num_contexts = 1; -size_t current_image = 0; -void set_current_image(size_t i) { current_image = i; } - -/* Internal functions: */ - -static mem_addr copy_int_to_stack (size_t context, int n); -static mem_addr copy_str_to_stack (size_t context, char *s); -static void delete_all_breakpoints (); - - -int exception_occurred; - -int initial_text_size = TEXT_SIZE; - -int initial_data_size = DATA_SIZE; - -mem_addr initial_data_limit = DATA_LIMIT; - -int initial_stack_size = STACK_SIZE; - -mem_addr initial_stack_limit = STACK_LIMIT; - -int initial_k_text_size = K_TEXT_SIZE; - -int initial_k_data_size = K_DATA_SIZE; - -mem_addr initial_k_data_limit = K_DATA_LIMIT; - - - -/* Initialize or reinitialize the state of the machine. */ - -void -initialize_world (size_t context, char* exception_file_paths, - char *exception_file_name, bool free_labels) -{ - reg_image_t ®_image = reg_images[context]; - reg_image.context = context; - reg_image.auto_alignment = 1; - - /* Allocate the floating point registers */ - if (reg_image.FGR == NULL) - reg_image.FPR = (double *) xmalloc (FPR_LENGTH * sizeof (double)); - /* Allocate the memory */ - make_memory (context, - initial_text_size, - initial_data_size, initial_data_limit, - initial_stack_size, initial_stack_limit, - initial_k_text_size, - initial_k_data_size, initial_k_data_limit); - initialize_registers (context); - initialize_inst_tables (); - initialize_symbol_table (free_labels); - k_text_begins_at_point (context, K_TEXT_BOT); - k_data_begins_at_point (context, K_DATA_BOT); - data_begins_at_point (context, DATA_BOT); - text_begins_at_point (context, TEXT_BOT); - - if (exception_file_paths != NULL) - { - bool old_bare = bare_machine; - bool old_accept = accept_pseudo_insts; - char *filename; - char *files; - - /* Save machine state */ - bare_machine = false; /* Exception handler uses extended machine */ - accept_pseudo_insts = true; - - /* strtok modifies the string, so we must back up the string prior to use. */ - if ((files = strdup (exception_file_paths)) == NULL) - fatal_error ("Insufficient memory to complete.\n"); - - for (filename = strtok (files, ";"); filename != NULL; filename = strtok (NULL, ";")) - { - /* if you pass in non-NULL second parameter, I assume one exception file */ - if (!read_assembly_file (filename, exception_file_name)) - fatal_error ("Cannot read exception handler: %s\n", filename); - - write_output (message_out, "Loaded: %s\n", filename); - } - - free (files); - - /* Restore machine state */ - bare_machine = old_bare; - accept_pseudo_insts = old_accept; - - if (!bare_machine) - { - (void)make_label_global ("main"); /* In case .globl main forgotten */ - (void)record_label ("main", 0, 0); - } - } - initialize_scanner (stdin, ""); - delete_all_breakpoints (); -} - - -void -write_startup_message () -{ - write_output (message_out, "SPIM %s\n", SPIM_VERSION); - write_output (message_out, "Copyright 1990-2017 by James Larus.\n"); - write_output (message_out, "All Rights Reserved.\n"); - write_output (message_out, "SPIM is distributed under a BSD license.\n"); - write_output (message_out, "See the file README for a full copyright notice.\n"); -} - - - -void -initialize_registers (size_t context) -{ - reg_image_t ®_image = reg_images[context]; - - memclr (reg_image.FPR, FPR_LENGTH * sizeof (double)); - reg_image.FGR = (float *) reg_image.FPR; - reg_image.FWR = (int *) reg_image.FPR; - - memclr (reg_image.R, R_LENGTH * sizeof (reg_word)); - reg_image.R[REG_SP] = STACK_TOP - BYTES_PER_WORD - 4096; /* Initialize $sp */ - reg_image.HI = reg_image.LO = 0; - reg_image.PC = TEXT_BOT; - - CP0_BadVAddr(reg_image) = 0; - CP0_Count(reg_image) = 0; - CP0_Compare(reg_image) = 0; - CP0_Status(reg_image) = (CP0_Status_CU & 0x30000000) | CP0_Status_IM | CP0_Status_UM; - CP0_Cause(reg_image) = 0; - CP0_EPC(reg_image) = 0; -#ifdef SPIM_BIGENDIAN - CP0_Config = CP0_Config_BE; -#else - CP0_Config(reg_image) = 0; -#endif - - FIR(reg_image) = FIR_W | FIR_D | FIR_S; /* Word, double, & single implemented */ - FCSR(reg_image) = 0x0; - FCCR(reg_image) = 0x0; - FEXR(reg_image) = 0x0; - FENR(reg_image) = 0x0; - - reg_image.RFE_cycle = 0; -} - - -/* Read file NAME, which should contain assembly code. Return true if - successful and false otherwise. */ - -bool -read_assembly_file (char *fpath, char *file_name) -{ - FILE *file = fopen (fpath, "rt"); - - if (file == NULL) - { - error ("Cannot open file: `%s'\n", fpath); - return false; - } - else - { - if (file_name == NULL) { - file_name = strrchr(fpath, '/'); - file_name = file_name == NULL ? fpath : file_name + 1; - } - initialize_scanner (file, file_name); - initialize_parser (fpath); - - while (!yyparse ()) ; - - fclose (file); - flush_local_labels (!parse_error_occurred); - end_of_assembly_file (); - return true; - } -} - - -mem_addr -starting_address () -{ - return (find_symbol_address (DEFAULT_RUN_LOCATION)); -} - - -#define MAX_ARGS 10000 - -/* Initialize the SPIM stack from a string containing the command line. */ - -void -initialize_stack(const char *command_line) -{ - int argc = 0; - char *argv[MAX_ARGS]; - char *a; - char *args = str_copy((char*)command_line); /* Destructively modify string */ - char *orig_args = args; - - while (*args != '\0') - { - /* Skip leading blanks */ - while (*args == ' ' || *args == '\t') args++; - - /* First non-blank char */ - a = args; - - /* Last non-blank, non-null char */ - while (*args != ' ' && *args != '\t' && *args != '\0') args++; - - /* Terminate word */ - if (a != args) - { - if (*args != '\0') - *args++ = '\0'; /* Null terminate */ - - argv[argc++] = a; - - if (MAX_ARGS == argc) - { - break; /* If too many, ignore rest of list */ - } - } - } - - initialize_run_stack (argc, argv); - free (orig_args); -} - - -/* Initialize the SPIM stack with ARGC, ARGV, and ENVP data. */ - -#ifdef _MSC_VER -#define environ _environ -#endif - -void -initialize_run_stack (int argc, char **argv) -{ - //FIXME: eventually run for both or neither - int context = 0; - reg_image_t ®_image = reg_images[context]; - - char **p; - extern char **environ; - int i, j = 0, env_j; - mem_addr addrs[10000]; - - - reg_image.R[REG_SP] = STACK_TOP - 1; /* Initialize $sp */ - - /* Put strings on stack: */ - /* env: */ - for (p = environ; *p != NULL; p++) - addrs[j++] = copy_str_to_stack (context, *p); - env_j = j; - - /* argv; */ - for (i = 0; i < argc; i++) - addrs[j++] = copy_str_to_stack (context, argv[i]); - - /* Align stack pointer for word-size data */ - reg_image.R[REG_SP] = reg_image.R[REG_SP] & ~3; /* Round down to nearest word */ - reg_image.R[REG_SP] -= BYTES_PER_WORD; /* First free word on stack */ - reg_image.R[REG_SP] = reg_image.R[REG_SP] & ~7; /* Double-word align stack-pointer*/ - - /* Build vectors on stack: */ - /* env: */ - (void)copy_int_to_stack (context, 0); /* Null-terminate vector */ - for (i = env_j - 1; i >= 0; i--) - reg_image.R[REG_A2] = copy_int_to_stack (context, addrs[i]); - - /* argv: */ - (void)copy_int_to_stack (context, 0); /* Null-terminate vector */ - for (i = j - 1; i >= env_j; i--) - reg_image.R[REG_A1] = copy_int_to_stack (context, addrs[i]); - - /* argc: */ - reg_image.R[REG_A0] = argc; - set_mem_word (context, reg_image.R[REG_SP], argc); /* Leave argc on stack */ -} - - -static mem_addr -copy_str_to_stack (size_t context, char *s) -{ - reg_image_t ®_image = reg_images[context]; - - int i = (int)strlen (s); - while (i >= 0) - { - set_mem_byte (context, reg_image.R[REG_SP], s[i]); - reg_image.R[REG_SP] -= 1; - i -= 1; - } - return ((mem_addr) reg_image.R[REG_SP] + 1); /* Leaves stack pointer byte-aligned!! */ -} - - -static mem_addr -copy_int_to_stack (size_t context, int n) -{ - reg_image_t ®_image = reg_images[context]; - - set_mem_word (context, reg_image.R[REG_SP], n); - reg_image.R[REG_SP] -= BYTES_PER_WORD; - return ((mem_addr) reg_image.R[REG_SP] + BYTES_PER_WORD); -} - - -/* Run the program, starting at PC, for STEPS instructions. Display each - instruction before executing if DISPLAY is true. If CONT_BKPT is - true, then step through a breakpoint. CONTINUABLE is true if - execution can continue. Return true if breakpoint is encountered. */ - -bool -run_program (int steps, bool display, bool cont_bkpt, bool* continuable) -{ - if (map_click && !spimbot_tournament) { - return true; - } - - for (int i = 0; i < steps; ++ i) { - for (size_t j = 0; j < num_contexts; ++ j) { - size_t context = (j + steps) % num_contexts; - set_current_image(context); - reg_image_t ®_image = reg_images[context]; - - if (context == 0 && inst_is_breakpoint (reg_image.PC)) { - if (cont_bkpt) { - mem_addr addr = reg_image.PC; - - delete_breakpoint (addr); - reg_image.exception_occurred = false; - run_spim (context, display); - add_breakpoint (addr); - } else { - return true; - } - } else { - if (!run_spim (context, display)) { - *continuable = false; - world_update(); - return false; - } - } - } - cont_bkpt = false; - int spimbot_break = world_update(); - if (spimbot_break >= 0) { - if (spimbot_break == 0) { - *continuable = false; - return false; - } - else if (spimbot_break == 1) { - return true; - } - } - - if (force_break) { - return false; - } - } - - return false; -} - - -/* Set a breakpoint at memory location ADDR. */ - -void -add_breakpoint (mem_addr addr) -{ - bkpt *rec = (bkpt *) xmalloc (sizeof (bkpt)); - - rec->next = bkpts; - rec->addr = addr; - - bkpts = rec; -} - - -/* Delete all breakpoints at memory location ADDR. */ - -void -delete_breakpoint (mem_addr addr) -{ - bkpt *p, *b; - int deleted_one = 0; - - for (p = NULL, b = bkpts; b != NULL; ) - if (b->addr == addr) - { - bkpt *n; - -// set_mem_inst (addr, b->inst); - if (p == NULL) - bkpts = b->next; - else - p->next = b->next; - n = b->next; - free (b); - b = n; - deleted_one = 1; - } - else - p = b, b = b->next; - if (!deleted_one) - error ("No breakpoint to delete at 0x%08x\n", addr); -} - - -static void -delete_all_breakpoints () -{ - bkpt *b, *n; - - for (b = bkpts, n = NULL; b != NULL; b = n) - { - n = b->next; - free (b); - } - bkpts = NULL; -} - - -/* List all breakpoints. */ - -void -list_breakpoints () -{ - bkpt *b; - - if (bkpts) - for (b = bkpts; b != NULL; b = b->next) - write_output (message_out, "Breakpoint at 0x%08x\n", b->addr); - else - write_output (message_out, "No breakpoints set\n"); -} - - - -/* Utility routines */ - - -/* Return the entry in the linear TABLE of length LENGTH with key STRING. - TABLE must be sorted on the key field. - Return NULL if no such entry exists. */ - -name_val_val * -map_string_to_name_val_val (name_val_val tbl[], int tbl_len, char *id) -{ - int low = 0; - int hi = tbl_len - 1; - - while (low <= hi) - { - int mid = (low + hi) / 2; - char *idp = id, *np = tbl[mid].name; - - while (*idp == *np && *idp != '\0') {idp ++; np ++;} - - if (*np == '\0' && *idp == '\0') /* End of both strings */ - return (& tbl[mid]); - else if (*idp > *np) - low = mid + 1; - else - hi = mid - 1; - } - - return NULL; -} - - -/* Return the entry in the linear TABLE of length LENGTH with VALUE1 field NUM. - TABLE must be sorted on the VALUE1 field. - Return NULL if no such entry exists. */ - -name_val_val * -map_int_to_name_val_val (name_val_val tbl[], int tbl_len, int num) -{ - int low = 0; - int hi = tbl_len - 1; - - while (low <= hi) - { - int mid = (low + hi) / 2; - - if (tbl[mid].value1 == num) - return (&tbl[mid]); - else if (num > tbl[mid].value1) - low = mid + 1; - else - hi = mid - 1; - } - - return NULL; -} - - -#ifdef NEED_VSPRINTF -char * -vsprintf (str, fmt, args) - char *str,*fmt; - va_list *args; -{ - FILE _strbuf; - - _strbuf._flag = _IOWRT+_IOSTRG; - _strbuf._ptr = str; - _strbuf._cnt = 32767; - _doprnt(fmt, args, &_strbuf); - putc('\0', &_strbuf); - return(str); -} -#endif - - -#ifdef NEED_STRTOL -unsigned long -strtol (const char* str, const char** eptr, int base) -{ - long result; - - if (base != 0 && base != 16) - fatal_error ("SPIM's strtol only works for base 16 (not base %d)\n", base); - if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) - { - str += 2; - sscanf (str, "%lx", &result); - } - else if (base == 16) - { - sscanf (str, "%lx", &result); - } - else - { - sscanf (str, "%ld", &result); - } - return (result); -} -#endif - - -#ifdef NEED_STRTOUL -unsigned long -strtoul (const char* str, char** eptr, int base) -{ - unsigned long result; - - if (base != 0 && base != 16) - fatal_error ("SPIM's strtoul only works for base 16 (not base %d)\n", base); - if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) - { - str += 2; - sscanf (str, "%lx", &result); - } - else if (base == 16) - { - sscanf (str, "%lx", &result); - } - else - { - sscanf (str, "%ld", &result); - } - return (result); -} -#endif - - -char * -str_copy (char *str) -{ - return (strcpy ((char*)xmalloc ((int)strlen (str) + 1), str)); -} - - -void * -xmalloc (int size) -{ - void *x = (void *) malloc (size); - - if (x == 0) - fatal_error ("Out of memory at request for %d bytes.\n"); - return (x); -} - - -/* Allocate a zero'ed block of storage. */ - -void * -zmalloc (int size) -{ - void *z = (void *) malloc (size); - - if (z == 0) - fatal_error ("Out of memory at request for %d bytes.\n"); - - memclr (z, size); - return (z); -} diff --git a/spim-qtspimbot/CPU/spim-utils.h b/spim-qtspimbot/CPU/spim-utils.h deleted file mode 100755 index 762c339..0000000 --- a/spim-qtspimbot/CPU/spim-utils.h +++ /dev/null @@ -1,92 +0,0 @@ -/* SPIM S20 MIPS simulator. - Interface to misc. routines for SPIM. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef SPIM_UTILS_H -#define SPIM_UTILS_H - -#include "inst.h" - - -/* Triple containing a string and two integers. Used in tables - mapping from a name to values. */ - -typedef struct -{ - char *name; - int value1; - int value2; -} name_val_val; - -/* Record of where a breakpoint was placed and the instruction previously - in memory. */ - -typedef struct bkptrec -{ - mem_addr addr; - instruction *inst; - struct bkptrec *next; -} bkpt; - - -extern bkpt *bkpts; - -extern size_t num_contexts; - - -/* Exported functions: */ - -extern size_t current_image; -void set_current_image(size_t i); - -void add_breakpoint (mem_addr addr); -void delete_breakpoint (mem_addr addr); -void format_data_segs (str_stream *ss); -void format_insts (str_stream *ss, mem_addr from, mem_addr to); -void format_mem (str_stream *ss, mem_addr from, mem_addr to); -void format_registers (str_stream *ss, int print_gpr_hex, int print_fpr_hex); -void initialize_registers (size_t context); -void initialize_stack (const char *command_line); -void initialize_run_stack (int argc, char **argv); -void initialize_world (size_t context, char* exception_file_paths, - char *exception_file_name, bool free_labels); -void list_breakpoints (); -name_val_val *map_int_to_name_val_val (name_val_val tbl[], int tbl_len, int num); -name_val_val *map_string_to_name_val_val (name_val_val tbl[], int tbl_len, char *id); -bool read_assembly_file (char *fpath, char *file_name); -bool run_program (int steps, bool display, bool cont_bkpt, bool* continuable); -mem_addr starting_address (); -char *str_copy (char *str); -void write_startup_message (); -void *xmalloc (int); -void *zmalloc (int); - -#endif diff --git a/spim-qtspimbot/CPU/spim.h b/spim-qtspimbot/CPU/spim.h deleted file mode 100755 index d0c519b..0000000 --- a/spim-qtspimbot/CPU/spim.h +++ /dev/null @@ -1,267 +0,0 @@ -/* SPIM S20 MIPS simulator. - Definitions for the SPIM S20. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef SPIM_H -#define SPIM_H - -#ifndef NULL -#define NULL 0 -#endif - -/* This declaration must match the endianness of the machine SPIM is running on. You CANNOT - set SPIM to simulate a different endianness than the machine that executes it. Almost - every processor (notably the x86) is little endian today. If your machine is big endian, - define -DSPIM_BIGENDIAN in the Makefile. */ - -#ifndef SPIM_BIGENDIAN -#define SPIM_LITTLENDIAN -#endif - - -/* Type declarations for portability. They work for DEC's Alpha (64 bits) - and 32 bit machines */ - -typedef int int32; -typedef unsigned int uint32; -typedef union {int i; void* p;} intptr_union; - - -#define streq(s1, s2) !strcmp(s1, s2) - - -/* Round V to next greatest B boundary */ -#define ROUND_UP(V, B) (((int) V + (B-1)) & ~(B-1)) -#define ROUND_DOWN(V, B) (((int) V) & ~(B-1)) - -/* Sign-extend an int16 to an int32 */ -#define SIGN_EX(X) (((X) & 0x8000) ? ((X) | 0xffff0000) : (X)) - - -#ifdef MIN /* Some systems define these in system includes */ -#undef MIN -#endif -#ifdef MAX -#undef MAX -#endif -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) - - -/* Useful and pervasive declarations: */ - -#ifdef NEED_MEM_FUNCTIONS -#define memcpy(T, F, S) bcopy((void*)F, (void*)T, S) -#define memclr(B, S) bzero(B, S) -#define memcmp(S1, S2, N) bcmp(S1, S2, N) -#else -#include -#define memclr(B, S) memset((void*)B, 0, S) -#endif - -#include -#include -#define QSORT_FUNC int(*)(const void *, const void *) - - - -#define K 1024 - - -/* Type of a memory address. Must be a 32-bit quantity to match MIPS. */ - -typedef uint32 /*@alt int @*/ mem_addr; - - -#define BYTES_PER_WORD 4 /* On the MIPS processor */ - - -/* Sizes of memory segments. */ - -/* Initial size of text segment. */ - -#ifndef TEXT_SIZE -#define TEXT_SIZE (256*K) /* 1/4 MB */ -#endif - -/* Initial size of k_text segment. */ - -#ifndef K_TEXT_SIZE -#define K_TEXT_SIZE (64*K) /* 64 KB */ -#endif - -/* The data segment must be larger than 64K since we immediate grab - 64K for the small data segment pointed to by $gp. The data segment is - expanded by an sbrk system call. */ - -/* Initial size of data segment. */ - -#ifndef DATA_SIZE -#define DATA_SIZE (256*K) /* 1/4 MB */ -#endif - -/* Maximum size of data segment. */ - -#ifndef DATA_LIMIT -#define DATA_LIMIT (16*K*K) /* 16 MB */ -#endif - -/* Initial size of k_data segment. */ - -#ifndef K_DATA_SIZE -#define K_DATA_SIZE (64*K) /* 64 KB */ -#endif - -/* Maximum size of k_data segment. */ - -#ifndef K_DATA_LIMIT -#define K_DATA_LIMIT (K*K) /* 1 MB */ -#endif - -/* The stack grows down automatically. */ - -/* Initial size of stack segment. */ - -#ifndef STACK_SIZE -#define STACK_SIZE (64*K) /* 64 KB */ -#endif - -/* Maximum size of stack segment. */ - -#ifndef STACK_LIMIT -#define STACK_LIMIT (256*K) /* 1/4 MB */ -#endif - - -/* Name of the function to invoke at start up */ - -#define DEFAULT_RUN_LOCATION "__start" - - -/* Name of the symbol marking the end of the exception handler */ - -#define END_OF_TRAP_HANDLER_SYMBOL "__eoth" - - -/* Default number of instructions to execute. */ - -#define DEFAULT_RUN_STEPS 2147483647 - - -/* Address to branch to when exception occurs */ -#ifdef MIPS1 -/* MIPS R2000 */ -#define EXCEPTION_ADDR 0x80000080 -#else -/* MIPS32 */ -#define EXCEPTION_ADDR 0x80000180 -#endif - -/* Maximum size of object stored in the small data segment pointed to by $gp */ - -#define SMALL_DATA_SEG_MAX_SIZE 8 - -#ifndef DIRECT_MAPPED -#define DIRECT_MAPPED 0 -#define TWO_WAY_SET 1 -#endif - - -/* Interval (in instructions) at which memory-mapped IO registers are - checked and updated. (This is to reduce overhead from making system calls - to check for IO. It can be set as low as 1.) */ - -#define IO_INTERVAL 100 - - -/* Number of IO_INTERVALs that a character remains in receiver buffer, - even if another character is available. */ - -#define RECV_INTERVAL 100 - - -/* Number of IO_INTERVALs that it takes to write a character. */ - -#define TRANS_LATENCY 100 - - -/* Iterval (milliseconds) for the hardware timer in CP0. */ - -#define TIMER_TICK_MS 10 /* 100 times per second */ - - - -/* A port is either a Unix file descriptor (an int) or a FILE* pointer. */ - -#include - -typedef union {int i; FILE* f;} port; - - -/* Exported functions (from spim.c or xspim.c): */ - -int console_input_available (); -void error (char *fmt, ...); -void fatal_error (char *fmt, ...); -char get_console_char (); -void put_console_char (char c); -void read_input (char *str, int n); -void run_error (char *fmt, ...); -void write_output (port, char *fmt, ...); - - -/* Exported variables: */ - -extern bool bare_machine; /* => simulate bare machine */ -extern bool accept_pseudo_insts; /* => parse pseudo instructions */ -extern bool delayed_branches; /* => simulate delayed branches */ -extern bool delayed_loads; /* => simulate delayed loads */ -extern bool quiet; /* => no warning messages */ -extern char *exception_file_name; /* File containing exception handler */ -extern bool force_break; /* => stop interpreter loop */ -extern bool parser_error_occurred; /* => parse resulted in error */ -extern int spim_return_value; /* Value returned when spim exits */ -/* Actual type of structure pointed to depends on X/terminal interface */ -extern port message_out, console_out, console_in; -extern bool mapped_io; /* => activate memory-mapped IO */ -extern int initial_text_size; -extern int initial_data_size; -extern mem_addr initial_data_limit; -extern int initial_stack_size; -extern mem_addr initial_stack_limit; -extern int initial_k_text_size; -extern int initial_k_data_size; -extern mem_addr initial_k_data_limit; - -/* SpimBOT stuff */ -extern bool map_click; - -#endif diff --git a/spim-qtspimbot/CPU/string-stream.cpp b/spim-qtspimbot/CPU/string-stream.cpp deleted file mode 100755 index a083247..0000000 --- a/spim-qtspimbot/CPU/string-stream.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* SPIM S20 MIPS simulator. - Append-only output stream convertable to a string. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include -#include -#include - -#include "spim.h" -#include "string-stream.h" - - -#ifndef SS_BUF_LENGTH -/* Initialize length of buffer */ -#define SS_BUF_LENGTH 256 -#endif - - -void -ss_init (str_stream* ss) -{ - ss->buf = (char *) malloc (SS_BUF_LENGTH); - ss->max_length = SS_BUF_LENGTH; - ss->empty_pos = 0; - ss->initialized = 1; -} - - -void -ss_clear (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - ss->empty_pos = 0; -} - - -void -ss_erase (str_stream* ss, int n) -{ - if (0 == ss->initialized) ss_init (ss); - - ss->empty_pos -= n; - if (ss->empty_pos <0) ss->empty_pos = 0; -} - - -int -ss_length (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - return ss->empty_pos; -} - - -char* -ss_to_string (str_stream* ss) -{ - if (0 == ss->initialized) ss_init (ss); - - if (ss->empty_pos == ss->max_length) - { - /* Not enough room to store output: increase buffer size and try again */ - ss->max_length = ss->max_length + 1; - ss->buf = (char *) realloc (ss->buf, (size_t)ss->max_length); - if (NULL == ss->buf) - fatal_error ("realloc failed\n"); - } - ss->buf[ss->empty_pos] = '\0'; /* Null terminate string */ - ss->empty_pos += 1; - return ss->buf; -} - - -void -ss_printf (str_stream* ss, char* fmt, ...) -{ - int free_space; - int n; - va_list args; - - va_start (args, fmt); - - if (0 == ss->initialized) ss_init (ss); - - free_space = ss->max_length - ss->empty_pos; -#ifdef _WIN32 - /* Returns -1 when buffer is too small */ - while ((n = _vsnprintf (ss->buf + ss->empty_pos, free_space, fmt, args)) < 0) -#else - /* Returns necessary space when buffer is too small */ - while ((n = vsnprintf (ss->buf + ss->empty_pos, free_space, fmt, args)) >= free_space) -#endif - { - /* Not enough room to store output: double buffer size and try again */ - ss->max_length = 2 * ss->max_length; - ss->buf = (char *) realloc (ss->buf, (size_t)ss->max_length); - free_space = ss->max_length - ss->empty_pos; - if (NULL == ss->buf) - fatal_error ("realloc failed\n"); - - va_end (args); /* Restart argument pointer */ - va_start (args, fmt); - } - ss->empty_pos += n; - - /* Null terminate string (for debugging) if there is enough room*/ - if (ss->empty_pos < ss->max_length) - ss->buf[ss->empty_pos] = '\0'; - - va_end (args); -} diff --git a/spim-qtspimbot/CPU/string-stream.h b/spim-qtspimbot/CPU/string-stream.h deleted file mode 100755 index 6121d1a..0000000 --- a/spim-qtspimbot/CPU/string-stream.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPIM S20 MIPS simulator. - Append-only output stream convertable to a string. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef STRING_STREAM_H -#define STRING_STREAM_H - -typedef struct str_stm -{ - char* buf; /* Buffer containing output */ - int max_length; /* Length of buffer */ - int empty_pos; /* Index of empty char in stream*/ - int initialized; /* Stream initialized? */ -} str_stream; - - -void ss_init (str_stream* ss); -void ss_clear (str_stream* ss); -void ss_erase (str_stream* ss, int n); -int ss_length (str_stream* ss); -char* ss_to_string (str_stream* ss); -void ss_printf (str_stream* ss, char* fmt, ...); - -#endif diff --git a/spim-qtspimbot/CPU/sym-tbl.cpp b/spim-qtspimbot/CPU/sym-tbl.cpp deleted file mode 100755 index d899b51..0000000 --- a/spim-qtspimbot/CPU/sym-tbl.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/* SPIM S20 MIPS simulator. - Code to maintain symbol table to resolve symbolic labels. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "data.h" -#include "parser.h" -#include "sym-tbl.h" -#include "parser_yacc.h" - - -/* Local functions: */ - -static void get_hash (char *name, int *slot_no, label **entry); -static void resolve_a_label_sub (label *sym, instruction *inst, mem_addr pc); - - - -/* Keep track of the memory location that a label represents. If we - see a reference to a label that is not yet defined, then record the - reference so that we can patch up the instruction when the label is - defined. - - At the end of a file, we flush the hash table of all non-global - labels so they can't be seen in other files. */ - - -static label *local_labels = NULL; /* Labels local to current file. */ - - -#define HASHBITS 30 - -#define LABEL_HASH_TABLE_SIZE 8191 - - -/* Map from name of a label to a label structure. */ - -static label *label_hash_table [LABEL_HASH_TABLE_SIZE]; - - -/* Initialize the symbol table by removing and freeing old entries. */ - -void -initialize_symbol_table (bool free_labels) -{ - int i; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - { - label *x, *n; - - for (x = label_hash_table [i]; x != NULL; x = n) - { - if (free_labels) { - free (x->name); - } - n = x->next; - if (free_labels) { - free (x); - } - } - label_hash_table [i] = NULL; - } - - local_labels = NULL; -} - - - -/* Lookup for a label with the given NAME. Set the SLOT_NO to be the hash - table bucket that contains (or would contain) the label's record. If the - record is already in the table, set ENTRY to point to it. Otherwise, - set ENTRY to be NULL. */ - -static void -get_hash (char *name, int *slot_no, label **entry) -{ - int hi; - int i; - label *lab; - int len; - - /* Compute length of name in len. */ - for (len = 0; name[len]; len++) ; - - /* Compute hash code */ - hi = len; - for (i = 0; i < len; i++) - hi = ((hi * 613) + (unsigned)(name[i])); - - hi &= (1 << HASHBITS) - 1; - hi %= LABEL_HASH_TABLE_SIZE; - - *slot_no = hi; - /* Search table for entry */ - for (lab = label_hash_table [hi]; lab; lab = lab->next) - if (streq (lab->name, name)) - { - *entry = lab; /* <-- return if found */ - return; - } - *entry = NULL; -} - - -/* Lookup label with NAME. Either return its symbol table entry or NULL - if it is not in the table. */ - -label * -label_is_defined (char *name) -{ - int hi; - label *entry; - - get_hash (name, &hi, &entry); - - return (entry); -} - - -/* Return a label with a given NAME. If an label with that name has - previously been looked-up, the same node is returned this time. */ - -label * -lookup_label (char *name) -{ - int hi; - label *entry, *lab; - - get_hash (name, &hi, &entry); - - if (entry != NULL) - return (entry); - - /* Not found, create one, add to chain */ - lab = (label *) xmalloc (sizeof (label)); - lab->name = str_copy (name); - lab->addr = 0; - lab->global_flag = 0; - lab->const_flag = 0; - lab->gp_flag = 0; - lab->uses = NULL; - - lab->next = label_hash_table [hi]; - label_hash_table [hi] = lab; - return lab; /* <-- return if created */ -} - - -/* Record that the label named NAME refers to ADDRESS. If RESOLVE_USES is - true, resolve all references to it. Return the label structure. */ - -label * -record_label (char *name, mem_addr address, int resolve_uses) -{ - label *l = lookup_label (name); - - if (!l->gp_flag) - { - if (l->addr != 0) - { - yyerror ("Label is defined for the second time"); - return (l); - } - l->addr = address; - } - - if (resolve_uses) - { - resolve_label_uses (l); - } - - if (!l->global_flag) - { - l->next_local = local_labels; - local_labels = l; - } - return (l); -} - - -/* Make the label named NAME global. Return its symbol. */ - -label * -make_label_global (char *name) -{ - label *l = lookup_label (name); - - l->global_flag = 1; - return (l); -} - - -/* Record that an INSTRUCTION uses the as-yet undefined SYMBOL. */ - -void -record_inst_uses_symbol (instruction *inst, label *sym) -{ - label_use *u = (label_use *) xmalloc (sizeof (label_use)); - - if (data_dir) /* Want to free up original instruction */ - { - u->inst = copy_inst (inst); - u->addr = current_data_pc (); - } - else - { - u->inst = inst; - u->addr = current_text_pc (); - } - u->next = sym->uses; - sym->uses = u; -} - - -/* Record that a memory LOCATION uses the as-yet undefined SYMBOL. */ - -void -record_data_uses_symbol (mem_addr location, label *sym) -{ - label_use *u = (label_use *) xmalloc (sizeof (label_use)); - - u->inst = NULL; - u->addr = location; - u->next = sym->uses; - sym->uses = u; -} - - -/* Given a newly-defined LABEL, resolve the previously encountered - instructions and data locations that refer to the label. */ - -void -resolve_label_uses (label *sym) -{ - label_use *use; - label_use *next_use; - - for (use = sym->uses; use != NULL; use = next_use) - { - resolve_a_label_sub (sym, use->inst, use->addr); - if (use->inst != NULL && use->addr >= DATA_BOT && use->addr < mem_images[current_image].stack_bot) - { - set_mem_word (current_image, use->addr, inst_encode (use->inst)); - free_inst (use->inst); - } - next_use = use->next; - free (use); - } - sym->uses = NULL; -} - - -/* Resolve the newly-defined label in INSTRUCTION. */ - -void -resolve_a_label (label *sym, instruction *inst) -{ - resolve_a_label_sub (sym, - inst, - (data_dir ? current_data_pc () : current_text_pc ())); -} - - -static void -resolve_a_label_sub (label *sym, instruction *inst, mem_addr pc) -{ - if (inst == NULL) - { - /* Memory data: */ - set_mem_word (current_image, pc, sym->addr); - } - else - { - /* Instruction: */ - if (EXPR (inst)->pc_relative) - EXPR (inst)->offset = 0 - pc; /* Instruction may have moved */ - - if (EXPR (inst)->symbol == NULL - || SYMBOL_IS_DEFINED (EXPR (inst)->symbol)) - { - int32 value; - int32 field_mask; - - if (opcode_is_branch (OPCODE (inst))) - { - int val; - - /* Drop low two bits since instructions are on word boundaries. */ - val = SIGN_EX (eval_imm_expr (EXPR (inst))); /* 16->32 bits */ - val = (val >> 2) & 0xffff; /* right shift, 32->16 bits */ - - if (delayed_branches) - val -= 1; - - value = val; - field_mask = 0xffff; - } - else if (opcode_is_jump (OPCODE (inst))) - { - value = eval_imm_expr (EXPR (inst)); - if ((value & 0xf0000000) != (pc & 0xf0000000)) - { - error ("Target of jump differs in high-order 4 bits from instruction pc 0x%x\n", pc); - } - /* Drop high four bits, since they come from the PC and the - low two bits since instructions are on word boundaries. */ - value = (value & 0x0fffffff) >> 2; - field_mask = 0xffffffff; /* Already checked that value fits in instruction */ - } - else if (opcode_is_load_store (OPCODE (inst))) - { - /* Label's location is an address */ - value = eval_imm_expr (EXPR (inst)); - field_mask = 0xffff; - - if (value & 0x8000) - { - /* LW/SW sign extends offset. Compensate by adding 1 to high 16 bits. */ - instruction* prev_inst; - instruction* prev_prev_inst; - prev_inst = read_mem_inst (current_image, pc - BYTES_PER_WORD); - prev_prev_inst = read_mem_inst (current_image, pc - 2 * BYTES_PER_WORD); - - if (prev_inst != NULL - && OPCODE (prev_inst) == Y_LUI_OP - && EXPR (inst)->symbol == EXPR (prev_inst)->symbol - && IMM (prev_inst) == 0) - { - /* Check that previous instruction was LUI and it has no immediate, - otherwise it will have compensated for sign-extension */ - EXPR (prev_inst)->offset += 0x10000; - } - /* There is an ADDU instruction before the LUI if the - LW/SW instruction uses an index register: skip over the ADDU. */ - else if (prev_prev_inst != NULL - && OPCODE (prev_prev_inst) == Y_LUI_OP - && EXPR (inst)->symbol == EXPR (prev_prev_inst)->symbol - && IMM (prev_prev_inst) == 0) - { - EXPR (prev_prev_inst)->offset += 0x10000; - } - } - } - else - { - /* Label's location is a value */ - value = eval_imm_expr (EXPR (inst)); - field_mask = 0xffff; - } - - if ((value & ~field_mask) != (int32)0 - && (value & ~field_mask) != (int32)0xffff0000) - { - error ("Immediate value is too large for field: "); - print_inst (pc); - } - if (opcode_is_jump (OPCODE (inst))) - SET_TARGET (inst, value); /* Don't mask so it is sign-extended */ - else - SET_IMM (inst, value); /* Ditto */ - SET_ENCODING (inst, inst_encode (inst)); - } - else - error ("Resolving undefined symbol: %s\n", - (EXPR (inst)->symbol == NULL) ? "" : EXPR (inst)->symbol->name); - } -} - - -/* Remove all local (non-global) label from the table. */ - -void -flush_local_labels (int issue_undef_warnings) -{ - label *l; - - for (l = local_labels; l != NULL; l = l->next_local) - { - int hi; - label *entry, *lab, *p; - - get_hash (l->name, &hi, &entry); - - for (lab = label_hash_table [hi], p = NULL; - lab; - p = lab, lab = lab->next) - if (lab == entry) - { - if (p == NULL) - label_hash_table [hi] = lab->next; - else - p->next = lab->next; - if (issue_undef_warnings && entry->addr == 0 && !entry->const_flag) - error ("Warning: local symbol %s was not defined\n", - entry->name); - /* Can't free label since IMM_EXPR's still reference it */ - break; - } - } - local_labels = NULL; -} - - -/* Return the address of SYMBOL or 0 if it is undefined. */ - -mem_addr -find_symbol_address (char *symbol) -{ - label *l = lookup_label (symbol); - - if (l == NULL || l->addr == 0) - return 0; - else - return (l->addr); -} - - -/* Print all symbols in the table. */ - -void -print_symbols () -{ - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table [i]; l != NULL; l = l->next) - write_output (message_out, "%s%s at 0x%08x\n", - l->global_flag ? "g\t" : "\t", l->name, l->addr); -} - - -/* Print all undefined symbols in the table. */ - -void -print_undefined_symbols () -{ - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table [i]; l != NULL; l = l->next) - if (l->addr == 0) - write_output (message_out, "%s\n", l->name); -} - - -/* Return a string containing the names of all undefined symbols in the - table, seperated by a newline character. Return NULL if no symbols - are undefined. */ - -char * -undefined_symbol_string () -{ - int buffer_length = 128; - int string_length = 0; - char *buffer = (char*)malloc(buffer_length); - - int i; - label *l; - - for (i = 0; i < LABEL_HASH_TABLE_SIZE; i ++) - for (l = label_hash_table[i]; l != NULL; l = l->next) - if (l->addr == 0) - { - int name_length = (int)strlen(l->name); - int after_length = string_length + name_length + 2; - if (buffer_length < after_length) - { - buffer_length = MAX (2 * buffer_length, 2 * after_length); - buffer = (char*)realloc (buffer, buffer_length); - } - memcpy (buffer + string_length, l->name, name_length); - string_length += name_length; - buffer[string_length] = '\n'; - string_length += 1; - buffer[string_length] = '\0'; /* After end of string */ - } - - if (string_length != 0) - return (buffer); - else - { - free (buffer); - return (NULL); - }; -} diff --git a/spim-qtspimbot/CPU/sym-tbl.h b/spim-qtspimbot/CPU/sym-tbl.h deleted file mode 100755 index 402de7c..0000000 --- a/spim-qtspimbot/CPU/sym-tbl.h +++ /dev/null @@ -1,76 +0,0 @@ -/* SPIM S20 MIPS simulator. - Data structures for symbolic addresses. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -typedef struct lab_use -{ - instruction *inst; /* NULL => Data, not code */ - mem_addr addr; - struct lab_use *next; -} label_use; - - -/* Symbol table information on a label. */ - -typedef struct lab -{ - char *name; /* Name of label */ - long addr; /* Address of label or 0 if not yet defined */ - unsigned global_flag : 1; /* Non-zero => declared global */ - unsigned gp_flag : 1; /* Non-zero => referenced off gp */ - unsigned const_flag : 1; /* Non-zero => constant value (in addr) */ - struct lab *next; /* Hash table link */ - struct lab *next_local; /* Link in list of local labels */ - label_use *uses; /* List of instructions that reference */ -} label; /* label that has not yet been defined */ - - -#define SYMBOL_IS_DEFINED(SYM) ((SYM)->addr != 0) - - - -/* Exported functions: */ - -mem_addr find_symbol_address (char *symbol); -void flush_local_labels (int issue_undef_warnings); -void initialize_symbol_table (bool free_labels); -label *label_is_defined (char *name); -label *lookup_label (char *name); -label *make_label_global (char *name); -void print_symbols (); -void print_undefined_symbols (); -label *record_label (char *name, mem_addr address, int resolve_uses); -void record_data_uses_symbol (mem_addr location, label *sym); -void record_inst_uses_symbol (instruction *inst, label *sym); -char *undefined_symbol_string (); -void resolve_a_label (label *sym, instruction *inst); -void resolve_label_uses (label *sym); diff --git a/spim-qtspimbot/CPU/syscall.cpp b/spim-qtspimbot/CPU/syscall.cpp deleted file mode 100755 index 1577a6b..0000000 --- a/spim-qtspimbot/CPU/syscall.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM syscalls, both in simulator and bare mode. - Execute MIPS syscalls in bare mode, when running on MIPS systems. - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef _WIN32 -#include -#endif -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#endif - -#include "spim.h" -#include "string-stream.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "sym-tbl.h" -#include "syscall.h" - -#include "../Spimbot/robot.h" - -#ifdef _WIN32 -/* Windows has an handler that is invoked when an invalid argument is passed to a system - call. https://msdn.microsoft.com/en-us/library/a9yf33zb(v=vs.110).aspx - - All good, except that the handler tries to invoke Watson and then kill spim with an exception. - - Override the handler to just report an error. -*/ - -#include -#include -#include - -void myInvalidParameterHandler(const wchar_t* expression, - const wchar_t* function, - const wchar_t* file, - unsigned int line, - uintptr_t pReserved) -{ - if (function != NULL) - { - run_error ("Bad parameter to system call: %s\n", function); - } - else - { - run_error ("Bad parameter to system call\n"); - } -} - -static _invalid_parameter_handler oldHandler; - -void windowsParameterHandlingControl(int flag ) -{ - static _invalid_parameter_handler oldHandler; - static _invalid_parameter_handler newHandler = myInvalidParameterHandler; - - if (flag == 0) - { - oldHandler = _set_invalid_parameter_handler(newHandler); - _CrtSetReportMode(_CRT_ASSERT, 0); // Disable the message box for assertions. - } - else - { - newHandler = _set_invalid_parameter_handler(oldHandler); - _CrtSetReportMode(_CRT_ASSERT, 1); // Enable the message box for assertions. - } -} -#endif - -/* The address of the last exception. Different from EPC - * if one exception occurs inside another or an interrupt. */ -mem_addr last_exception_addr; - - -/* Decides which syscall to execute or simulate. Returns zero upon - exit syscall and non-zero to continue execution. */ - -int -do_syscall (size_t context) -{ -#ifdef _WIN32 - windowsParameterHandlingControl(0); -#endif - - if (spimbot_tournament) - return 1; - - reg_image_t ®_image = reg_images[context]; - mem_image_t &mem_image = mem_images[context]; - - /* Syscalls for the source-language version of SPIM. These are easier to - use than the real syscall and are portable to non-MIPS operating - systems. */ - - switch (reg_image.R[REG_V0]) - { - case PRINT_INT_SYSCALL: - write_output (console_out, "%d", reg_image.R[REG_A0]); - break; - - case PRINT_FLOAT_SYSCALL: - { - float val = FPR_S (reg_image, REG_FA0); - - write_output (console_out, "%.8f", val); - break; - } - - case PRINT_DOUBLE_SYSCALL: - write_output (console_out, "%.18g", reg_image.FPR[REG_FA0 / 2]); - break; - - case PRINT_STRING_SYSCALL: - write_output (console_out, "%s", mem_reference (context, reg_image.R[REG_A0])); - break; - - case READ_INT_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - reg_image.R[REG_RES] = atol (str); - break; - } - - case READ_FLOAT_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - FPR_S (reg_image, REG_FRES) = (float) atof (str); - break; - } - - case READ_DOUBLE_SYSCALL: - { - static char str [256]; - - read_input (str, 256); - reg_image.FPR [REG_FRES] = atof (str); - break; - } - - case READ_STRING_SYSCALL: - { - read_input ( (char *) mem_reference (context, reg_image.R[REG_A0]), reg_image.R[REG_A1]); - mem_image.data_modified = true; - break; - } - - case SBRK_SYSCALL: - { - mem_addr x = mem_image.data_top; - expand_data (context, reg_image.R[REG_A0]); - reg_image.R[REG_RES] = x; - mem_image.data_modified = true; - break; - } - - case PRINT_CHARACTER_SYSCALL: - write_output (console_out, "%c", reg_image.R[REG_A0]); - break; - - case READ_CHARACTER_SYSCALL: - { - static char str [2]; - - read_input (str, 2); - if (*str == '\0') *str = '\n'; /* makes xspim = spim */ - reg_image.R[REG_RES] = (long) str[0]; - break; - } - - case EXIT_SYSCALL: - spim_return_value = 0; - return (0); - - case EXIT2_SYSCALL: - spim_return_value = reg_image.R[REG_A0]; /* value passed to spim's exit() call */ - return (0); - - case OPEN_SYSCALL: - { - if (spimbot_file_io_enabled) { -#ifdef _WIN32 - reg_image.R[REG_RES] = _open((char*)mem_reference (context, reg_image.R[REG_A0]), reg_image.R[REG_A1], reg_image.R[REG_A2]); -#else - reg_image.R[REG_RES] = open((char*)mem_reference (context, reg_image.R[REG_A0]), reg_image.R[REG_A1], reg_image.R[REG_A2]); -#endif - } else if (spimbot_debug) { - printf("Bot: %zu Failed use syscall open since File IO is disabled.\n", context); - } - break; - } - - case READ_SYSCALL: - { - if (spimbot_file_io_enabled) { - /* Test if address is valid */ - (void)mem_reference (context, reg_image.R[REG_A1] + reg_image.R[REG_A2] - 1); -#ifdef _WIN32 - reg_image.R[REG_RES] = _read(reg_image.R[REG_A0], mem_reference (context, reg_image.R[REG_A1]), reg_image.R[REG_A2]); -#else - reg_image.R[REG_RES] = read(reg_image.R[REG_A0], mem_reference (context, reg_image.R[REG_A1]), reg_image.R[REG_A2]); -#endif - mem_image.data_modified = true; - } else if (spimbot_debug) { - printf("Bot: %zu Failed use syscall read since File IO is disabled.\n", context); - } - break; - } - - case WRITE_SYSCALL: - { - if (spimbot_file_io_enabled) { - /* Test if address is valid */ - (void)mem_reference (context, reg_image.R[REG_A1] + reg_image.R[REG_A2] - 1); -#ifdef _WIN32 - reg_image.R[REG_RES] = _write(reg_image.R[REG_A0], mem_reference (context, reg_image.R[REG_A1]), reg_image.R[REG_A2]); -#else - reg_image.R[REG_RES] = write(reg_image.R[REG_A0], mem_reference (context, reg_image.R[REG_A1]), reg_image.R[REG_A2]); -#endif - } else if (spimbot_debug) { - printf("Bot: %zu Failed use syscall write since File IO is disabled.\n", context); - } - break; - } - - case CLOSE_SYSCALL: - { - if (spimbot_file_io_enabled) { -#ifdef _WIN32 - reg_image.R[REG_RES] = _close(reg_image.R[REG_A0]); -#else - reg_image.R[REG_RES] = close(reg_image.R[REG_A0]); -#endif - } else if (spimbot_debug) { - printf("Bot: %zu Failed use syscall close since File IO is disabled.\n", context); - } - break; - } - - case PRINT_HEX_SYSCALL: - write_output (console_out, "%x", reg_image.R[REG_A0]); - break; - - default: - run_error ("Unknown system call: %d\n", reg_image.R[REG_V0]); - break; - } - -#ifdef _WIN32 - windowsParameterHandlingControl(1); -#endif - return (1); -} - - -void -handle_exception (reg_image_t ®_image) -{ - if (spimbot_tournament && CP0_ExCode(reg_image) != ExcCode_Int) { - robots[reg_image.context].done = 1; - return; - } - - if (!quiet && CP0_ExCode(reg_image) != ExcCode_Int) - error ("Exception occurred at PC=0x%08x\n", last_exception_addr); - - reg_image.exception_occurred = 0; - reg_image.PC = EXCEPTION_ADDR; - - switch (CP0_ExCode(reg_image)) - { - case ExcCode_Int: - break; - - case ExcCode_AdEL: - if (!quiet) - error (" Unaligned address in inst/data fetch: 0x%08x\n", CP0_BadVAddr(reg_image)); - break; - - case ExcCode_AdES: - if (!quiet) - error (" Unaligned address in store: 0x%08x\n", CP0_BadVAddr(reg_image)); - break; - - case ExcCode_IBE: - if (!quiet) - error (" Bad address in text read: 0x%08x\n", CP0_BadVAddr(reg_image)); - break; - - case ExcCode_DBE: - if (!quiet) - error (" Bad address in data/stack read: 0x%08x\n", CP0_BadVAddr(reg_image)); - break; - - case ExcCode_Sys: - if (!quiet) - error (" Error in syscall\n"); - break; - - case ExcCode_Bp: - reg_image.exception_occurred = 0; - return; - - case ExcCode_RI: - if (!quiet) - error (" Reserved instruction execution\n"); - break; - - case ExcCode_CpU: - if (!quiet) - error (" Coprocessor unuable\n"); - break; - - case ExcCode_Ov: - if (!quiet) - error (" Arithmetic overflow\n"); - break; - - case ExcCode_Tr: - if (!quiet) - error (" Trap\n"); - break; - - case ExcCode_FPE: - if (!quiet) - error (" Floating point\n"); - break; - - default: - if (!quiet) - error ("Unknown exception: %d\n", CP0_ExCode(reg_image)); - break; - } -} diff --git a/spim-qtspimbot/CPU/syscall.h b/spim-qtspimbot/CPU/syscall.h deleted file mode 100755 index 6a5c149..0000000 --- a/spim-qtspimbot/CPU/syscall.h +++ /dev/null @@ -1,66 +0,0 @@ -/* SPIM S20 MIPS simulator. - Execute SPIM syscalls, both in simulator and bare mode. - - Copyright (c) 1990-2010, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* Exported functions. */ - -int do_syscall (size_t context); -void handle_exception (reg_image_t ®_image); - -#define PRINT_INT_SYSCALL 1 -#define PRINT_FLOAT_SYSCALL 2 -#define PRINT_DOUBLE_SYSCALL 3 -#define PRINT_STRING_SYSCALL 4 - -#define READ_INT_SYSCALL 5 -#define READ_FLOAT_SYSCALL 6 -#define READ_DOUBLE_SYSCALL 7 -#define READ_STRING_SYSCALL 8 - -#define SBRK_SYSCALL 9 - -#define EXIT_SYSCALL 10 - -#define PRINT_CHARACTER_SYSCALL 11 -#define READ_CHARACTER_SYSCALL 12 - -#define OPEN_SYSCALL 13 -#define READ_SYSCALL 14 -#define WRITE_SYSCALL 15 -#define CLOSE_SYSCALL 16 - -#define EXIT2_SYSCALL 17 - -#define PRINT_HEX_SYSCALL 34 - -/* Exported variables. */ -extern mem_addr last_exception_addr; diff --git a/spim-qtspimbot/CPU/vasm.cpp b/spim-qtspimbot/CPU/vasm.cpp deleted file mode 100644 index 0cf74ba..0000000 --- a/spim-qtspimbot/CPU/vasm.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include - -#include "spim.h" -#include "string-stream.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "data.h" -#include "vasm.h" - -namespace -{ -/** - * @brief Forward iterator for encoded instructions - */ -class inst_iterator -{ -public: - inst_iterator() - { - // empty - } - - inst_iterator(mem_addr addr) : addr(addr) - { - // empty - } - - mem_word operator*() const - { - instruction * inst = read_mem_inst(0, addr); - return inst_encode(inst, true); - } - - bool operator==(const inst_iterator & other) const - { - return addr == other.addr; - } - - bool operator!=(const inst_iterator & other) const - { - return !(*this == other); - } - - inst_iterator & operator++() - { - addr += 4; - return *this; - } - - inst_iterator operator++(int) - { - inst_iterator temp(*this); - ++*this; - return temp; - } - - mem_word word_addr() - { - return (addr - TEXT_BOT) >> 2; - } - -private: - mem_addr addr; -}; - -/** - * @brief Forward iterator for data words - */ -class data_iterator -{ -public: - data_iterator() - { - // empty - } - - data_iterator(mem_addr addr) : addr(addr) - { - // empty - } - - mem_word operator*() const - { - return read_mem_word(0, addr); - } - - bool operator==(const data_iterator & other) const - { - return addr == other.addr; - } - - bool operator!=(const data_iterator & other) const - { - return !(*this == other); - } - - data_iterator & operator++() - { - addr += 4; - return *this; - } - - data_iterator operator++(int) - { - data_iterator temp(*this); - ++*this; - return temp; - } - - mem_addr word_addr() const - { - return (addr - DATA_BOT) >> 2; - } - -private: - mem_addr addr; -}; - -template -void vasm(const std::string & file_path, T begin, T end) -{ - FILE * output_file = fopen(file_path.c_str(), "w"); - if (output_file == NULL) - { - perror("Could not open file for writing"); - return; - } - - if (begin == end) - { - // emulate spim.vasm behavior on empty segments - fclose(output_file); - return; - } - - fprintf(output_file, "\n@%08x\n", begin.word_addr()); - for (T it = begin; it != end;) - { - for (int i = 0; i < 4 && it != end; ++i, ++it) - { - fprintf(output_file, " %08x", *it); - } - fputc('\n', output_file); - } - - fclose(output_file); -} -} - -void vasm(const std::string & files_prefix) -{ - std::string text_path = files_prefix + ".text.dat"; - inst_iterator text_begin(TEXT_BOT); - inst_iterator text_end(current_text_pc()); - vasm(text_path, text_begin, text_end); - - std::string data_path = files_prefix + ".data.dat"; - data_iterator data_begin(DATA_BOT + 64*K); - data_iterator data_end(current_data_pc()); - vasm(data_path, data_begin, data_end); -} diff --git a/spim-qtspimbot/CPU/vasm.h b/spim-qtspimbot/CPU/vasm.h deleted file mode 100644 index d4671a6..0000000 --- a/spim-qtspimbot/CPU/vasm.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef VASM_H -#define VASM_H - -#include - -void vasm(const std::string & files_prefix); - -#endif // VASM_H diff --git a/spim-qtspimbot/CPU/version.h b/spim-qtspimbot/CPU/version.h deleted file mode 100644 index 2c1902e..0000000 --- a/spim-qtspimbot/CPU/version.h +++ /dev/null @@ -1 +0,0 @@ -#define SPIM_VERSION "Version 9.1.20 of August 29, 2017" diff --git a/spim-qtspimbot/README b/spim-qtspimbot/README deleted file mode 100644 index 645e645..0000000 --- a/spim-qtspimbot/README +++ /dev/null @@ -1,49 +0,0 @@ - README FILE FOR SPIM - ==================== - -This directory contains part of SPIM--an assembly language MIPS R2000/R3000 -simulator. It contains the terminal interface to SPIM. - -SPIM is covered by a BSD license. - -Copyright (c) 1990-2010, James R. Larus. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -Neither the name of the James R. Larus nor the names of its contributors may be -used to endorse or promote products derived from this software without specific -prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -The files in this directory are: - -README - This file. - -Makefile - Makefile to build the terminal version of spim. This Makefile works - for Unix and on Microsoft Windows under Cygwin. - -spim.c - Terminal interface to spim. diff --git a/spim-qtspimbot/spim.cpp b/spim-qtspimbot/spim.cpp deleted file mode 100755 index 2d7fec5..0000000 --- a/spim-qtspimbot/spim.cpp +++ /dev/null @@ -1,1277 +0,0 @@ -/* SPIM S20 MIPS simulator. - Terminal interface for SPIM simulator. - - Copyright (c) 1990-2015, James R. Larus. - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. - - Neither the name of the James R. Larus nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef WIN32 -#include -#endif -#include -#include -#include -#include -#include - - -#ifdef RS -/* This is problem on HP Snakes, which define RS in syscall.h */ -#undef RS -#endif - -#include -#include - -#ifdef _AIX -#ifndef NBBY -#define NBBY 8 -#endif -#endif - - -#ifndef WIN32 -#include -#ifdef NEED_TERMIOS -#include -#include -#else -#include -#endif -#endif - -#include - -#include "spim.h" -#include "string-stream.h" -#include "spim-utils.h" -#include "inst.h" -#include "reg.h" -#include "mem.h" -#include "parser.h" -#include "sym-tbl.h" -#include "scanner.h" -#include "parser_yacc.h" -#include "data.h" - - -/* Internal functions: */ - -static void console_to_program (); -static void console_to_spim (); -static void control_c_seen (int /*arg*/); -static void flush_to_newline (); -static int get_opt_int (); -static bool parse_spim_command (bool redo); -static void print_reg (int reg_no); -static int print_fp_reg (int reg_no); -static int print_reg_from_string (char *reg); -static void print_all_regs (int hex_flag); -static int read_assembly_command (); -static int str_prefix (char *s1, char *s2, int min_match); -static void top_level (); -static int read_token (); -static bool write_assembled_code(char* program_name); -static void dump_data_seg (bool kernel_also); -static void dump_text_seg (bool kernel_also); - - -/* Exported Variables: */ - -/* Not local, but not export so all files don't need setjmp.h */ -jmp_buf spim_top_level_env; /* For ^C */ - -bool bare_machine; /* => simulate bare machine */ -bool delayed_branches; /* => simulate delayed branches */ -bool delayed_loads; /* => simulate delayed loads */ -bool accept_pseudo_insts; /* => parse pseudo instructions */ -bool quiet; /* => no warning messages */ -bool assemble; /* => assemble, write to stdout and exit */ -char *exception_file_name = DEFAULT_EXCEPTION_HANDLER; -port message_out, console_out, console_in; -bool mapped_io; /* => activate memory-mapped IO */ -int pipe_out; -int spim_return_value; /* Value returned when spim exits */ - - -/* Local variables: */ - -/* => load standard exception handler */ -static bool load_exception_handler = true; -static int console_state_saved; -#ifdef NEED_TERMIOS -static struct sgttyb saved_console_state; -#else -static struct termios saved_console_state; -#endif -static int program_argc; -static char** program_argv; -static bool dump_user_segments = false; -static bool dump_all_segments = false; - - - -int -main (int argc, char **argv) -{ - int i; - bool assembly_file_loaded = false; - int print_usage_msg = 0; - - console_out.f = stdout; - message_out.f = stdout; - - bare_machine = false; - delayed_branches = false; - delayed_loads = false; - accept_pseudo_insts = true; - quiet = false; - assemble = false; - spim_return_value = 0; - - /* Input comes directly (not through stdio): */ - console_in.i = 0; - mapped_io = false; - - // write_startup_message (); - - if (getenv ("SPIM_EXCEPTION_HANDLER") != NULL) - exception_file_name = getenv ("SPIM_EXCEPTION_HANDLER"); - - for (i = 1; i < argc; i++) - { -#ifdef WIN32 - if (argv [i][0] == '/') { argv [i][0] = '-'; } -#endif - if (streq (argv [i], "-asm") - || streq (argv [i], "-a")) - { - bare_machine = false; - delayed_branches = false; - delayed_loads = false; - } - else if (streq (argv [i], "-bare") - || streq (argv [i], "-b")) - { - bare_machine = true; - delayed_branches = true; - delayed_loads = true; - quiet = true; - } - else if (streq (argv [i], "-delayed_branches") - || streq (argv [i], "-db")) - { - delayed_branches = true; - } - else if (streq (argv [i], "-delayed_loads") - || streq (argv [i], "-dl")) - { - delayed_loads = true; - } - else if (streq (argv [i], "-exception") - || streq (argv [i], "-e")) - { load_exception_handler = true; } - else if (streq (argv [i], "-noexception") - || streq (argv [i], "-ne")) - { load_exception_handler = false; } - else if (streq (argv [i], "-exception_file") - || streq (argv [i], "-ef")) - { - exception_file_name = argv[++i]; - load_exception_handler = true; - } - else if (streq (argv [i], "-mapped_io") - || streq (argv [i], "-mio")) - { mapped_io = true; } - else if (streq (argv [i], "-nomapped_io") - || streq (argv [i], "-nmio")) - { mapped_io = false; } - else if (streq (argv [i], "-pseudo") - || streq (argv [i], "-p")) - { accept_pseudo_insts = true; } - else if (streq (argv [i], "-nopseudo") - || streq (argv [i], "-np")) - { accept_pseudo_insts = false; } - else if (streq (argv [i], "-quiet") - || streq (argv [i], "-q")) - { quiet = true; } - else if (streq (argv [i], "-noquiet") - || streq (argv [i], "-nq")) - { quiet = false; } - else if (streq (argv [i], "-trap") - || streq (argv [i], "-t")) - { load_exception_handler = true; } - else if (streq (argv [i], "-notrap") - || streq (argv [i], "-nt")) - { load_exception_handler = false; } - else if (streq (argv [i], "-trap_file") - || streq (argv [i], "-tf")) - { - exception_file_name = argv[++i]; - load_exception_handler = true; - } - else if (streq (argv [i], "-stext") - || streq (argv [i], "-st")) - { initial_text_size = atoi (argv[++i]); } - else if (streq (argv [i], "-sdata") - || streq (argv [i], "-sd")) - { initial_data_size = atoi (argv[++i]); } - else if (streq (argv [i], "-ldata") - || streq (argv [i], "-ld")) - { initial_data_limit = atoi (argv[++i]); } - else if (streq (argv [i], "-sstack") - || streq (argv [i], "-ss")) - { initial_stack_size = atoi (argv[++i]); } - else if (streq (argv [i], "-lstack") - || streq (argv [i], "-ls")) - { initial_stack_limit = atoi (argv[++i]); } - else if (streq (argv [i], "-sktext") - || streq (argv [i], "-skt")) - { initial_k_text_size = atoi (argv[++i]); } - else if (streq (argv [i], "-skdata") - || streq (argv [i], "-skd")) - { initial_k_data_size = atoi (argv[++i]); } - else if (streq (argv [i], "-lkdata") - || streq (argv [i], "-lkd")) - { initial_k_data_limit = atoi (argv[++i]); } - else if (((streq (argv [i], "-file") - || streq (argv [i], "-f")) - && (i + 1 < argc)) - /* Assume this argument is a file name and everything following are - arguments for program */ - || (argv [i][0] != '-')) - { - program_argc = argc - (i + 1); - program_argv = &argv[i + 1]; /* Everything following is argv */ - - if (!assembly_file_loaded) - { - initialize_world (load_exception_handler ? exception_file_name : NULL, true); - initialize_run_stack (program_argc, program_argv); - } - assembly_file_loaded = read_assembly_file (argv[++i]) || assembly_file_loaded; - break; - } - else if (streq (argv [i], "-assemble")) - { assemble = true; } - else if (streq (argv [i], "-dump")) - { dump_user_segments = true; } - else if (streq (argv [i], "-full_dump")) - { dump_all_segments = true; } - else - { - error ("\nUnknown argument: %s (ignored)\n", argv[i]); - print_usage_msg = 1; - } - } - - if (print_usage_msg) - { - error ("Usage: spim\n\ - -bare Bare machine (no pseudo-ops, delayed branches and loads)\n\ - -asm Extended machine (pseudo-ops, no delayed branches and loads) (default)\n\ - -delayed_branches Execute delayed branches\n\ - -delayed_loads Execute delayed loads\n\ - -exception Load exception handler (default)\n\ - -noexception Do not load exception handler\n\ - -exception_file Specify exception handler in place of default\n\ - -quiet Do not print warnings\n\ - -noquiet Print warnings (default)\n\ - -mapped_io Enable memory-mapped IO\n\ - -nomapped_io Do not enable memory-mapped IO (default)\n\ - -file Assembly code file and arguments to program\n\ - -assemble Write assembled code to standard output\n\ - -dump Write user data and text segments into files\n\ - -full_dump Write user and kernel data and text into files.\n"); - } - - - if (!assembly_file_loaded) - { - initialize_world (load_exception_handler ? exception_file_name : NULL, true); - initialize_run_stack (program_argc, program_argv); - top_level (); - } - else /* assembly_file_loaded */ - { - if (assemble) - { - return write_assembled_code (program_argv[0]); - } - else if (dump_user_segments) - { - dump_data_seg (false); - dump_text_seg (false); - } - else if (dump_all_segments) - { - dump_data_seg (true); - dump_text_seg (true); - } - else - { - bool continuable; - console_to_program (); - initialize_run_stack (program_argc, program_argv); - if (!setjmp (spim_top_level_env)) - { - char *undefs = undefined_symbol_string (); - if (undefs != NULL) - { - write_output (message_out, "The following symbols are undefined:\n"); - write_output (message_out, undefs); - write_output (message_out, "\n"); - free (undefs); - } - run_program (find_symbol_address (DEFAULT_RUN_LOCATION), DEFAULT_RUN_STEPS, false, false, &continuable); - } - console_to_spim (); - } - } - - return (spim_return_value); -} - - - -/* Top-level read-eval-print loop for SPIM. */ - -static void -top_level () -{ - bool redo = false; /* => reexecute last command */ - - (void)signal (SIGINT, control_c_seen); - initialize_scanner (stdin); - initialize_parser (""); - while (1) - { - if (!redo) - write_output (message_out, "(spim) "); - if (!setjmp (spim_top_level_env)) - redo = parse_spim_command (redo); - else - redo = false; - fflush (stdout); - fflush (stderr); - } -} - - -static void -control_c_seen (int /*arg*/) -{ - console_to_spim (); - write_output (message_out, "\nExecution interrupted\n"); - longjmp (spim_top_level_env, 1); -} - - -/* SPIM commands */ - -enum { - UNKNOWN_CMD = 0, - EXIT_CMD, - READ_CMD, - RUN_CMD, - STEP_CMD, - PRINT_CMD, - PRINT_SYM_CMD, - PRINT_ALL_REGS_CMD, - REINITIALIZE_CMD, - ASM_CMD, - REDO_CMD, - NOP_CMD, - HELP_CMD, - CONTINUE_CMD, - SET_BKPT_CMD, - DELETE_BKPT_CMD, - LIST_BKPT_CMD, - DUMPNATIVE_TEXT_CMD, - DUMP_TEXT_CMD -}; - - -/* Parse a SPIM command from the currently open file and execute it. - If REDO is true, don't read a new command; just rexecute the - previous one. Return true if the command was to redo the previous - command. */ - -static bool -parse_spim_command (bool redo) -{ - static int prev_cmd = NOP_CMD; /* Default redo */ - static int prev_token; - int cmd; - - switch (cmd = (redo ? prev_cmd : read_assembly_command ())) - { - case EXIT_CMD: - console_to_spim (); - exit (0); - - case READ_CMD: - { - int token = (redo ? prev_token : read_token ()); - - if (!redo) flush_to_newline (); - if (token == Y_STR) - { - read_assembly_file ((char *) yylval.p); - pop_scanner(); - } - else - error ("Must supply a filename to read\n"); - prev_cmd = READ_CMD; - return (0); - } - - case RUN_CMD: - { - static mem_addr addr; - bool continuable; - - addr = (redo ? addr : get_opt_int ()); - if (addr == 0) - addr = starting_address (); - - initialize_run_stack (program_argc, program_argv); - console_to_program (); - if (addr != 0) - { - char *undefs = undefined_symbol_string (); - if (undefs != NULL) - { - write_output (message_out, "The following symbols are undefined:\n"); - write_output (message_out, undefs); - write_output (message_out, "\n"); - free (undefs); - } - - if (run_program (addr, DEFAULT_RUN_STEPS, false, false, &continuable)) - write_output (message_out, "Breakpoint encountered at 0x%08x\n", PC); - } - console_to_spim (); - - prev_cmd = RUN_CMD; - return (0); - } - - case CONTINUE_CMD: - { - if (PC != 0) - { - bool continuable; - console_to_program (); - if (run_program (PC, DEFAULT_RUN_STEPS, false, true, &continuable)) - write_output (message_out, "Breakpoint encountered at 0x%08x\n", PC); - console_to_spim (); - } - prev_cmd = CONTINUE_CMD; - return (0); - } - - case STEP_CMD: - { - static int steps; - mem_addr addr; - - steps = (redo ? steps : get_opt_int ()); - addr = PC == 0 ? starting_address () : PC; - - if (steps == 0) - steps = 1; - if (addr != 0) - { - bool continuable; - console_to_program (); - if (run_program (addr, steps, true, true, &continuable)) - write_output (message_out, "Breakpoint encountered at 0x%08x\n", PC); - console_to_spim (); - } - - prev_cmd = STEP_CMD; - return (0); - } - - case PRINT_CMD: - { - int token = (redo ? prev_token : read_token ()); - static int loc; - - if (token == Y_REG) - { - if (redo) loc += 1; - else loc = yylval.i; - print_reg (loc); - } - else if (token == Y_FP_REG) - { - if (redo) loc += 2; - else loc = yylval.i; - print_fp_reg (loc); - } - else if (token == Y_INT) - { - if (redo) loc += 4; - else loc = yylval.i; - print_mem (loc); - } - else if (token == Y_ID) - { - if (!print_reg_from_string ((char *) yylval.p)) - { - if (redo) loc += 4; - else loc = find_symbol_address ((char *) yylval.p); - - if (loc != 0) - print_mem (loc); - else - error ("Unknown label: %s\n", yylval.p); - } - } - else - error ("Print what?\n"); - if (!redo) flush_to_newline (); - prev_cmd = PRINT_CMD; - prev_token = token; - return (0); - } - - case PRINT_SYM_CMD: - print_symbols (); - if (!redo) flush_to_newline (); - prev_cmd = NOP_CMD; - return (0); - - case PRINT_ALL_REGS_CMD: - { - int hex_flag = 0; - int token = (redo ? prev_token : read_token ()); - if (token == Y_ID && streq((char*)yylval.p, "hex")) - hex_flag = 1; - print_all_regs (hex_flag); - if (!redo) flush_to_newline (); - prev_cmd = NOP_CMD; - return (0); - } - - case REINITIALIZE_CMD: - flush_to_newline (); - initialize_world (load_exception_handler ? exception_file_name : NULL, true); - initialize_run_stack (program_argc, program_argv); - write_startup_message (); - prev_cmd = NOP_CMD; - return (0); - - case ASM_CMD: - yyparse (); - prev_cmd = ASM_CMD; - return (0); - - case REDO_CMD: - return (1); - - case NOP_CMD: - prev_cmd = NOP_CMD; - return (0); - - case HELP_CMD: - if (!redo) flush_to_newline (); - write_output (message_out, "\nSPIM is a MIPS32 simulator.\n"); - write_output (message_out, "Its top-level commands are:\n"); - write_output (message_out, "exit -- Exit the simulator\n"); - write_output (message_out, "quit -- Exit the simulator\n"); - write_output (message_out, - "read \"FILE\" -- Read FILE containing assembly code into memory\n"); - write_output (message_out, - "load \"FILE\" -- Same as read\n"); - write_output (message_out, - "run -- Start the program at (optional) ADDRESS\n"); - write_output (message_out, - "step -- Step the program for N instructions (default 1)\n"); - write_output (message_out, - "continue -- Continue program execution without stepping\n"); - write_output (message_out, "print $N -- Print register N\n"); - write_output (message_out, - "print $fN -- Print floating point register N\n"); - write_output (message_out, - "print ADDR -- Print contents of memory at ADDRESS\n"); - write_output (message_out, - "print_symbols -- Print all global symbols\n"); - write_output (message_out, - "print_all_regs -- Print all MIPS registers\n"); - write_output (message_out, - "print_all_regs hex -- Print all MIPS registers in hex\n"); - write_output (message_out, - "reinitialize -- Clear the memory and registers\n"); - write_output (message_out, - "breakpoint -- Set a breakpoint at address ADDR\n"); - write_output (message_out, - "delete -- Delete breakpoint at address ADDR\n"); - write_output (message_out, "list -- List all breakpoints\n"); - write_output (message_out, "dump [ \"FILE\" ] -- Dump binary code to spim.dump or FILE in network byte order\n"); - write_output (message_out, "dumpnative [ \"FILE\" ] -- Dump binary code to spim.dump or FILE in host byte order\n"); - write_output (message_out, - ". -- Rest of line is assembly instruction to execute\n"); - write_output (message_out, " -- Newline reexecutes previous command\n"); - write_output (message_out, "? -- Print this message\n"); - - write_output (message_out, - "\nMost commands can be abbreviated to their unique prefix\n"); - write_output (message_out, "e.g., ex(it), re(ad), l(oad), ru(n), s(tep), p(rint)\n\n"); - prev_cmd = HELP_CMD; - return (0); - - case SET_BKPT_CMD: - case DELETE_BKPT_CMD: - { - int token = (redo ? prev_token : read_token ()); - static mem_addr addr; - - if (!redo) flush_to_newline (); - if (token == Y_INT) - addr = redo ? addr + 4 : (mem_addr)yylval.i; - else if (token == Y_ID) - addr = redo ? addr + 4 : find_symbol_address ((char *) yylval.p); - else - error ("Must supply an address for breakpoint\n"); - if (cmd == SET_BKPT_CMD) - add_breakpoint (addr); - else - delete_breakpoint (addr); - prev_cmd = cmd; - - return (0); - } - - case LIST_BKPT_CMD: - if (!redo) flush_to_newline (); - list_breakpoints (); - prev_cmd = LIST_BKPT_CMD; - return (0); - - case DUMPNATIVE_TEXT_CMD: - case DUMP_TEXT_CMD: - { - int token = (redo ? prev_token : read_token ()); - - FILE *fp = NULL; - char *filename = NULL; - - int words = 0; - mem_addr addr; - mem_addr dump_start; - mem_addr dump_end; - - if (token == Y_STR) - filename = (char *) yylval.p; - else if (token == Y_NL) - filename = "spim.dump"; - else - { - fprintf (stderr, "usage: %s [ \"filename\" ]\n", - (cmd == DUMP_TEXT_CMD ? "dump" : "dumpnative")); - return (0); - } - - fp = fopen (filename, "wbt"); - if (fp == NULL) - { - perror (filename); - return (0); - } - - user_kernel_text_segment (false); - dump_start = find_symbol_address (END_OF_TRAP_HANDLER_SYMBOL); - dump_end = current_text_pc (); - - for (addr = dump_start; addr < dump_end; addr += BYTES_PER_WORD) - { - int32 code = inst_encode (read_mem_inst (addr)); - if (cmd == DUMP_TEXT_CMD) - code = (int32)htonl ((unsigned long)code); /* dump in network byte order */ - (void)fwrite (&code, 1, sizeof(code), fp); - words += 1; - } - - fclose (fp); - fprintf (stderr, "Dumped %d words starting at 0x%08x to file %s\n", - words, (unsigned int)dump_start, filename); - - prev_cmd = cmd; - return (0); - } - - default: - while (read_token () != Y_NL) ; - error ("Unknown spim command\n"); - return (0); - } -} - - -/* Read a SPIM command with the scanner and return its ennuemerated - value. */ - -static int -read_assembly_command () -{ - int token = read_token (); - - if (token == Y_NL) /* Blank line means redo */ - return (REDO_CMD); - else if (token != Y_ID) /* Better be a string */ - return (UNKNOWN_CMD); - else if (str_prefix ((char *) yylval.p, "exit", 2)) - return (EXIT_CMD); - else if (str_prefix ((char *) yylval.p, "quit", 2)) - return (EXIT_CMD); - else if (str_prefix ((char *) yylval.p, "print", 1)) - return (PRINT_CMD); - else if (str_prefix ((char *) yylval.p, "print_symbols", 7)) - return (PRINT_SYM_CMD); - else if (str_prefix ((char *) yylval.p, "print_all_regs", 7)) - return (PRINT_ALL_REGS_CMD); - else if (str_prefix ((char *) yylval.p, "run", 2)) - return (RUN_CMD); - else if (str_prefix ((char *) yylval.p, "read", 2)) - return (READ_CMD); - else if (str_prefix ((char *) yylval.p, "load", 2)) - return (READ_CMD); - else if (str_prefix ((char *) yylval.p, "reinitialize", 6)) - return (REINITIALIZE_CMD); - else if (str_prefix ((char *) yylval.p, "step", 1)) - return (STEP_CMD); - else if (str_prefix ((char *) yylval.p, "help", 1)) - return (HELP_CMD); - else if (str_prefix ((char *) yylval.p, "continue", 1)) - return (CONTINUE_CMD); - else if (str_prefix ((char *) yylval.p, "breakpoint", 2)) - return (SET_BKPT_CMD); - else if (str_prefix ((char *) yylval.p, "delete", 1)) - return (DELETE_BKPT_CMD); - else if (str_prefix ((char *) yylval.p, "list", 2)) - return (LIST_BKPT_CMD); - else if (str_prefix ((char *) yylval.p, "dumpnative", 5)) - return (DUMPNATIVE_TEXT_CMD); - else if (str_prefix ((char *) yylval.p, "dump", 4)) - return (DUMP_TEXT_CMD); - else if (*(char *) yylval.p == '?') - return (HELP_CMD); - else if (*(char *) yylval.p == '.') - return (ASM_CMD); - else - return (UNKNOWN_CMD); -} - - -/* Return non-nil if STRING1 is a (proper) prefix of STRING2. */ - -static int -str_prefix (char *s1, char *s2, int min_match) -{ - for ( ; *s1 == *s2 && *s1 != '\0'; s1 ++, s2 ++) min_match --; - return (*s1 == '\0' && min_match <= 0); -} - - -/* Read and return an integer from the current line of input. If the - line doesn't contain an integer, return 0. In either case, flush the - rest of the line, including the newline. */ - -static int -get_opt_int () -{ - int token; - - if ((token = read_token ()) == Y_INT) - { - flush_to_newline (); - return (yylval.i); - } - else if (token == Y_NL) - return (0); - else - { - flush_to_newline (); - return (0); - } -} - - -/* Flush the rest of the input line up to and including the next newline. */ - -static void -flush_to_newline () -{ - while (read_token () != Y_NL) ; -} - - -/* Print register number N. */ - -static void -print_reg (int reg_no) -{ - write_output (message_out, "Reg %d = 0x%08x (%d)\n", reg_no, R[reg_no], R[reg_no]); -} - - -static int -print_fp_reg (int reg_no) -{ - if ((reg_no & 1) == 0) - write_output (message_out, "FP reg %d = %g (double)\n", reg_no, FPR_D (reg_no)); - write_output (message_out, "FP reg %d = %g (single)\n", reg_no, FPR_S (reg_no)); - return (1); -} - - -static int -print_reg_from_string (char* reg_num) -{ - char s[100]; - char *s1 = s; - - /* Conver to lower case */ - while (*reg_num != '\0' && s1 - s < 100) - *s1++ = tolower (*reg_num++); - *s1 = '\0'; - /* Drop leading $ */ - if (s[0] == '$') - s1 = s + 1; - else - s1 = s; - - if (streq (s1, "pc")) - write_output (message_out, "PC = 0x%08x (%d)\n", PC, PC); - else if (streq (s1, "hi")) - write_output (message_out, "HI = 0x%08x (%d)\n", HI, HI); - else if (streq (s1, "lo")) - write_output (message_out, "LO = 0x%08x (%d)\n", LO, LO); - else if (streq (s1, "fpcond")) - write_output (message_out, "FCSR = 0x%08x (%d)\n", FCSR, FCSR); - else if (streq (s1, "cause")) - write_output (message_out, "Cause = 0x%08x (%d)\n", CP0_Cause, CP0_Cause); - else if (streq (s1, "epc")) - write_output (message_out, "EPC = 0x%08x (%d)\n", CP0_EPC, CP0_EPC); - else if (streq (s1, "status")) - write_output (message_out, "Status = 0x%08x (%d)\n", CP0_Status, CP0_Status); - else if (streq (s1, "badvaddr")) - write_output (message_out, "BadVAddr = 0x%08x (%d)\n", CP0_BadVAddr, CP0_BadVAddr); - else - return (0); - - return (1); -} - - -static void -print_all_regs (int hex_flag) -{ - static str_stream ss; - - ss_clear (&ss); - format_registers (&ss, hex_flag, hex_flag); - write_output (message_out, "%s\n", ss_to_string (&ss)); -} - - -static bool -write_assembled_code(char* program_name) -{ - if (parse_error_occurred) - { - return (parse_error_occurred); - } - - FILE *fp = NULL; - char *filename = NULL; - - mem_addr addr; - mem_addr dump_start; - mem_addr dump_end; - - filename = (char*) xmalloc(strlen(program_name) + 5); - strcpy(filename, program_name); - strcat(filename, ".out"); - - fp = fopen (filename, "wt"); - if (fp == NULL) - { - perror (filename); - return (true); - } - - /* dump text segment */ - user_kernel_text_segment (false); - dump_start = find_symbol_address (END_OF_TRAP_HANDLER_SYMBOL); - dump_end = current_text_pc (); - - (void)fprintf (fp, ".text # 0x%x .. 0x%x\n.word ", dump_start, dump_end); - for (addr = dump_start; addr < dump_end; addr += BYTES_PER_WORD) - { - int32 code = inst_encode (read_mem_inst (addr)); - (void)fprintf (fp, "0x%x%s", code, addr != (dump_end - BYTES_PER_WORD) ? ", " : ""); - } - (void)fprintf (fp, "\n"); - - /* dump data segment */ - user_kernel_data_segment (false); - if (bare_machine) - { - dump_start = 0; - } - else - { - dump_start = DATA_BOT; - } - dump_end = current_data_pc (); - - if (dump_end > dump_start) - { - (void)fprintf (fp, ".data # 0x%x .. 0x%x\n.word ", dump_start, dump_end); - for (addr = dump_start; addr < dump_end; addr += BYTES_PER_WORD) - { - int32 code = read_mem_word (addr); - (void)fprintf (fp, "0x%x%s", code, addr != (dump_end - BYTES_PER_WORD) ? ", " : ""); - } - (void)fprintf (fp, "\n"); - } - - fclose (fp); - return (false); -} - - - -/* Print an error message. */ - -void -error (char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, stderr); -#else - vfprintf (stderr, fmt, args); -#endif - va_end (args); -} - - -/* Print the error message then exit. */ - -void -fatal_error (char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - fmt = va_arg (args, char *); - -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, stderr); -#else - vfprintf (stderr, fmt, args); -#endif - exit (-1); -} - - -/* Print an error message and return to top level. */ - -void -run_error (char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - - console_to_spim (); - -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, stderr); -#else - vfprintf (stderr, fmt, args); -#endif - va_end (args); - longjmp (spim_top_level_env, 1); -} - - - -/* IO facilities: */ - -void -write_output (port fp, char *fmt, ...) -{ - va_list args; - FILE *f; - int restore_console_to_program = 0; - - va_start (args, fmt); - f = fp.f; - - if (console_state_saved) - { - restore_console_to_program = 1; - console_to_spim (); - } - - if (f != 0) - { -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, f); -#else - vfprintf (f, fmt, args); -#endif - fflush (f); - } - else - { -#ifdef NEED_VFPRINTF - _doprnt (fmt, args, stdout); -#else - vfprintf (stdout, fmt, args); -#endif - fflush (stdout); - } - va_end (args); - - if (restore_console_to_program) - console_to_program (); -} - - -/* Simulate the semantics of fgets (not gets) on Unix file. */ - -void -read_input (char *str, int str_size) -{ - char *ptr; - int restore_console_to_program = 0; - - if (console_state_saved) - { - restore_console_to_program = 1; - console_to_spim (); - } - - ptr = str; - - while (1 < str_size) /* Reserve space for null */ - { - char buf[1]; - if (read ((int) console_in.i, buf, 1) <= 0) /* Not in raw mode! */ - break; - - *ptr ++ = buf[0]; - str_size -= 1; - - if (buf[0] == '\n') - break; - } - - if (0 < str_size) - *ptr = '\0'; /* Null terminate input */ - - if (restore_console_to_program) - console_to_program (); -} - - -/* Give the console to the program for IO. */ - -static void -console_to_program () -{ - if (mapped_io && !console_state_saved) - { -#ifdef NEED_TERMIOS - int flags; - ioctl ((int) console_in.i, TIOCGETP, (char *) &saved_console_state); - flags = saved_console_state.sg_flags; - saved_console_state.sg_flags = (flags | RAW) & ~(CRMOD|ECHO); - ioctl ((int) console_in.i, TIOCSETP, (char *) &saved_console_state); - saved_console_state.sg_flags = flags; -#else - struct termios params; - - tcgetattr (console_in.i, &saved_console_state); - params = saved_console_state; - params.c_iflag &= ~(ISTRIP|INLCR|ICRNL|IGNCR|IXON|IXOFF|INPCK|BRKINT|PARMRK); - - /* Translate CR -> NL to canonicalize input. */ - params.c_iflag |= IGNBRK|IGNPAR|ICRNL; - params.c_oflag = OPOST|ONLCR; - params.c_cflag &= ~PARENB; - params.c_cflag |= CREAD|CS8; - params.c_lflag = 0; - params.c_cc[VMIN] = 1; - params.c_cc[VTIME] = 1; - - tcsetattr (console_in.i, TCSANOW, ¶ms); -#endif - console_state_saved = 1; - } -} - - -/* Return the console to SPIM. */ - -static void -console_to_spim () -{ - if (mapped_io && console_state_saved) -#ifdef NEED_TERMIOS - ioctl ((int) console_in.i, TIOCSETP, (char *) &saved_console_state); -#else - tcsetattr (console_in.i, TCSANOW, &saved_console_state); -#endif - console_state_saved = 0; -} - - -int -console_input_available () -{ - fd_set fdset; - struct timeval timeout; - - if (mapped_io) - { - timeout.tv_sec = 0; - timeout.tv_usec = 0; - FD_ZERO (&fdset); - FD_SET ((int) console_in.i, &fdset); - return (select (sizeof (fdset) * 8, &fdset, NULL, NULL, &timeout)); - } - else - return (0); -} - - -char -get_console_char () -{ - char buf; - - read ((int) console_in.i, &buf, 1); - - if (buf == 3) /* ^C */ - control_c_seen (0); - return (buf); -} - - -void -put_console_char (char c) -{ - putc (c, console_out.f); - fflush (console_out.f); -} - - -static int -read_token () -{ - int token = yylex (); - - if (token == 0) /* End of file */ - { - console_to_spim (); - exit (0); - } - else - { - return (token); - } -} - - -/* - * Writes the contents of the (user and optionally kernel) data segment into data.asm file. - * If data.asm already exists, it's replaced. - */ - -static void -dump_data_seg(bool kernel_also) -{ - static str_stream ss; - ss_clear (&ss); - - if (kernel_also) - { - format_data_segs (&ss); - } - else - { - ss_printf (&ss, "\tDATA\n"); - format_mem (&ss, DATA_BOT, data_top); - } - - FILE *fp; - fp = fopen ("data.asm", "w"); - fprintf (fp, "%s", ss_to_string (&ss)); - fclose (fp); -} - - -/* - * Writes the contents of the (user and optionally kernel) text segment in text.asm file. - * If data.asm already exists, it's replaced. - */ - -static void -dump_text_seg(bool kernel_also) -{ - static str_stream ss; - ss_clear (&ss); - - if (kernel_also) - { - format_insts (&ss, TEXT_BOT, text_top); - ss_printf (&ss, "\n\tKERNEL\n"); - format_insts (&ss, K_TEXT_BOT, k_text_top); - } - else - { - ss_printf (&ss, "\n\tUSER TEXT SEGMENT\n"); - format_insts (&ss, TEXT_BOT, text_top); - } - - FILE *fp; - fp = fopen ("text.asm", "w"); - fprintf (fp, "%s", ss_to_string (&ss)); - fclose (fp); -}
  • -

    Assemblers, Linkers, and the SPIM Simulator

    -

    James R. Larus
    EPFL
    spim@larusstone.org

    -
    -

    Introduction

    -

    Encoding instructions as binary numbers is natural and efficient for computers. - Humans, however, have a great deal of difficulty understanding and manipulating - these numbers. People read and write symbols (words) much better than long sequences - of digits. Chapter 2 showed that we need not choose between numbers and words - because computer instructions can be represented in many ways. Humans can write - and read symbols, and computers can execute the equivalent binary numbers. This - appendix describes the process by which a human-readable program is translated - into a form that a computer can execute, provides a few hints about writing - assembly programs, and explains how to run these programs on SPIM, a simulator - that executes MIPS programs. UNIX, Windows, and Mac OS X versions of the SPIM - simulator are available on the CD.

    -