1 /* int.c --- M32C interrupt handling. 2 3 Copyright (C) 2005-2017 Free Software Foundation, Inc. 4 Contributed by Red Hat, Inc. 5 6 This file is part of the GNU simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 22 #include "int.h" 23 #include "cpu.h" 24 #include "mem.h" 25 26 static void 27 trigger_interrupt (int addr, int clear_u) 28 { 29 int s = get_reg (sp); 30 int f = get_reg (flags); 31 int p = get_reg (pc); 32 33 if (clear_u) 34 set_flags (FLAGBIT_U, 0); 35 set_flags (FLAGBIT_I | FLAGBIT_D, 0); 36 37 if (A16) 38 { 39 s -= 4; 40 put_reg (sp, s); 41 mem_put_hi (s, p); 42 mem_put_qi (s + 2, f); 43 mem_put_qi (s + 3, ((f >> 4) & 0x0f) | (p >> 16)); 44 } 45 else 46 { 47 s -= 6; 48 put_reg (sp, s); 49 mem_put_si (s, p); 50 mem_put_hi (s + 4, f); 51 } 52 put_reg (pc, mem_get_psi (addr)); 53 } 54 55 void 56 trigger_fixed_interrupt (int addr) 57 { 58 trigger_interrupt (addr, 1); 59 } 60 61 void 62 trigger_based_interrupt (int vector) 63 { 64 int addr = get_reg (intb) + vector * 4; 65 trigger_interrupt (addr, vector <= 31); 66 } 67 68 void 69 trigger_peripheral_interrupt (int vector, int icaddr) 70 { 71 unsigned char old_ic = mem_get_qi (icaddr); 72 int addr = get_reg (intb) + vector * 4; 73 trigger_interrupt (addr, 1); 74 put_reg (flags, (get_reg (flags) & 0x8fff) | ((old_ic & 7) << 12)); 75 mem_put_qi (icaddr, old_ic & ~ 0x08); 76 } 77