| 1 | /* Run function for the micromips simulator |
| 2 | |
| 3 | Copyright (C) 2005-2020 Free Software Foundation, Inc. |
| 4 | Contributed by Imagination Technologies, Ltd. |
| 5 | Written by Andrew Bennett <andrew.bennett@imgtec.com>. |
| 6 | |
| 7 | This file is part of the MIPS sim. |
| 8 | |
| 9 | This program is free software; you can redistribute it and/or modify |
| 10 | it under the terms of the GNU General Public License as published by |
| 11 | the Free Software Foundation; either version 3 of the License, or |
| 12 | (at your option) any later version. |
| 13 | |
| 14 | This program is distributed in the hope that it will be useful, |
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | GNU General Public License for more details. |
| 18 | |
| 19 | You should have received a copy of the GNU General Public License |
| 20 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| 21 | |
| 22 | #include "sim-main.h" |
| 23 | #include "micromips16_idecode.h" |
| 24 | #include "micromips32_idecode.h" |
| 25 | #include "micromips_m32_idecode.h" |
| 26 | #include "bfd.h" |
| 27 | #include "sim-engine.h" |
| 28 | |
| 29 | /* These definitions come from the *_support.h files generated by igen and are |
| 30 | required because they are used in some of the macros in the code below. |
| 31 | Unfortunately we can not just blindly include the *_support.h files to get |
| 32 | these definitions because some of the defines in these files are specific |
| 33 | for a particular configuration of the simulator for example instruction word |
| 34 | size is 16 bits for micromips16 and 32 bits for micromips32. This means we |
| 35 | could break future code changes by doing this, so a safer approach is to just |
| 36 | extract the defines that we need to get this file to compile. */ |
| 37 | #define SD sd |
| 38 | #define CPU cpu |
| 39 | |
| 40 | address_word |
| 41 | micromips_instruction_decode (SIM_DESC sd, sim_cpu * cpu, |
| 42 | address_word cia, |
| 43 | int instruction_size) |
| 44 | { |
| 45 | if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_ANY) |
| 46 | { |
| 47 | micromips16_instruction_word instruction_0 = IMEM16_MICROMIPS (cia); |
| 48 | if (MICROMIPS_MINOR_OPCODE (instruction_0) > 0 |
| 49 | && MICROMIPS_MINOR_OPCODE (instruction_0) < 4) |
| 50 | return micromips16_idecode_issue (sd, instruction_0, cia); |
| 51 | else |
| 52 | { |
| 53 | micromips32_instruction_word instruction_0 = IMEM32_MICROMIPS (cia); |
| 54 | return micromips32_idecode_issue (sd, instruction_0, cia); |
| 55 | } |
| 56 | } |
| 57 | else if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_16) |
| 58 | { |
| 59 | micromips16_instruction_word instruction_0 = IMEM16_MICROMIPS (cia); |
| 60 | if (MICROMIPS_MINOR_OPCODE (instruction_0) > 0 |
| 61 | && MICROMIPS_MINOR_OPCODE (instruction_0) < 4) |
| 62 | return micromips16_idecode_issue (sd, instruction_0, cia); |
| 63 | else |
| 64 | sim_engine_abort (sd, cpu, cia, |
| 65 | "Invalid 16 bit micromips instruction"); |
| 66 | } |
| 67 | else if (instruction_size == MICROMIPS_DELAYSLOT_SIZE_32) |
| 68 | { |
| 69 | micromips32_instruction_word instruction_0 = IMEM32_MICROMIPS (cia); |
| 70 | return micromips32_idecode_issue (sd, instruction_0, cia); |
| 71 | } |
| 72 | else |
| 73 | return NULL_CIA; |
| 74 | } |
| 75 | |
| 76 | void |
| 77 | sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus, |
| 78 | int signal) |
| 79 | { |
| 80 | micromips_m32_instruction_word instruction_0; |
| 81 | sim_cpu *cpu = STATE_CPU (sd, next_cpu_nr); |
| 82 | micromips32_instruction_address cia = CPU_PC_GET (cpu); |
| 83 | sd->isa_mode = ISA_MODE_MIPS32; |
| 84 | |
| 85 | while (1) |
| 86 | { |
| 87 | micromips32_instruction_address nia; |
| 88 | |
| 89 | /* Allow us to switch back from MIPS32 to microMIPS |
| 90 | This covers two cases: |
| 91 | 1. Setting the correct isa mode based on the start address |
| 92 | from the elf header. |
| 93 | 2. Setting the correct isa mode after a MIPS32 jump or branch |
| 94 | instruction. */ |
| 95 | if ((sd->isa_mode == ISA_MODE_MIPS32) |
| 96 | && ((cia & 0x1) == ISA_MODE_MICROMIPS)) |
| 97 | { |
| 98 | sd->isa_mode = ISA_MODE_MICROMIPS; |
| 99 | cia = cia & ~0x1; |
| 100 | } |
| 101 | |
| 102 | #if defined (ENGINE_ISSUE_PREFIX_HOOK) |
| 103 | ENGINE_ISSUE_PREFIX_HOOK (); |
| 104 | #endif |
| 105 | switch (sd->isa_mode) |
| 106 | { |
| 107 | case ISA_MODE_MICROMIPS: |
| 108 | nia = |
| 109 | micromips_instruction_decode (sd, cpu, cia, |
| 110 | MICROMIPS_DELAYSLOT_SIZE_ANY); |
| 111 | break; |
| 112 | case ISA_MODE_MIPS32: |
| 113 | instruction_0 = IMEM32 (cia); |
| 114 | nia = micromips_m32_idecode_issue (sd, instruction_0, cia); |
| 115 | break; |
| 116 | default: |
| 117 | nia = NULL_CIA; |
| 118 | } |
| 119 | |
| 120 | #if defined (ENGINE_ISSUE_POSTFIX_HOOK) |
| 121 | ENGINE_ISSUE_POSTFIX_HOOK (); |
| 122 | #endif |
| 123 | |
| 124 | /* Update the instruction address */ |
| 125 | cia = nia; |
| 126 | |
| 127 | /* process any events */ |
| 128 | if (sim_events_tick (sd)) |
| 129 | { |
| 130 | CPU_PC_SET (cpu, cia); |
| 131 | sim_events_process (sd); |
| 132 | cia = CPU_PC_GET (cpu); |
| 133 | } |
| 134 | } |
| 135 | } |