fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 202 lines 4.1 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/cpu/arm/copr14.c * 7 * Created: 2007-02-16 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2007-2011 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include "arm.h" 24#include "internal.h" 25 26 27static int cp14_reset (arm_t *c, arm_copr_t *p); 28static int cp14_exec (arm_t *c, arm_copr_t *p); 29 30 31void cp14_init (arm_copr14_t *c) 32{ 33 arm_copr_init (&c->copr); 34 35 c->copr.ext = c; 36 c->copr.reset = cp14_reset; 37 c->copr.exec = cp14_exec; 38 39 c->cclkcfg = 0; 40 c->pwrmode = 0; 41} 42 43arm_copr_t *cp14_new (void) 44{ 45 arm_copr14_t *c; 46 47 c = malloc (sizeof (arm_copr14_t)); 48 if (c == NULL) { 49 return (NULL); 50 } 51 52 cp14_init (c); 53 54 return (&c->copr); 55} 56 57void cp14_free (arm_copr14_t *p) 58{ 59} 60 61void cp14_del (arm_copr14_t *p) 62{ 63 if (p != NULL) { 64 cp14_free (p); 65 } 66 67 free (p); 68} 69 70static 71int cp14_op_mrc (arm_t *c, arm_copr_t *p) 72{ 73 arm_copr14_t *p14; 74 unsigned rn, rm; 75 uint32_t val; 76 77 p14 = p->ext; 78 79 rn = arm_ir_rn (c->ir); 80 rm = arm_ir_rm (c->ir); 81 /* op2 = arm_get_bits (c->ir, 5, 3); */ 82 83 switch ((rm << 4) | rn) { 84 case 0x00: /* xsc1 performance monitor control register */ 85 val = 0; 86 break; 87 88 case 0x06: /* CCLKCFG */ 89 val = p14->cclkcfg; 90 break; 91 92 case 0x07: /* PWRMODE */ 93 val = p14->pwrmode; 94 break; 95 96 default: 97 return (1); 98 } 99 100 if (arm_rd_is_pc (c->ir)) { 101 arm_set_cpsr (c, (arm_get_cpsr (c) & ~ARM_PSR_CC) | (val & ARM_PSR_CC)); 102 } 103 else { 104 arm_set_rd (c, c->ir, val & 0xffffffff); 105 } 106 107 return (0); 108} 109 110static 111int cp14_op_mcr (arm_t *c, arm_copr_t *p) 112{ 113 arm_copr14_t *p14; 114 unsigned rn, rm; 115 uint32_t val; 116 117 p14 = p->ext; 118 119 rn = arm_ir_rn (c->ir); 120 rm = arm_ir_rm (c->ir); 121 /* op2 = arm_get_bits (c->ir, 5, 3); */ 122 123 val = arm_get_rd (c, c->ir); 124 125 switch ((rm << 4) | rn) { 126 case 0x00: /* xsc1 performance monitor control register */ 127 break; 128 129 case 0x06: /* CCLKCFG */ 130 p14->cclkcfg = val & 0x0000000f; 131 break; 132 133 case 0x07: /* PWRMODE */ 134 p14->pwrmode = val & 0x0000000f; 135 break; 136 137 default: 138 return (1); 139 } 140 141 return (0); 142} 143 144int cp14_reset (arm_t *c, arm_copr_t *p) 145{ 146 arm_copr14_t *p14; 147 148 p14 = p->ext; 149 150 p14->cclkcfg = 0; 151 p14->pwrmode = 0; 152 153 return (0); 154} 155 156static 157int cp14_exec (arm_t *c, arm_copr_t *p) 158{ 159 int r; 160 unsigned long pc; 161 char *op; 162 163 pc = arm_get_pc (c); 164 165 if (arm_is_privileged (c) == 0) { 166 return (1); 167 } 168 169 op = "?"; 170 171 switch (c->ir & 0x00f00010) { 172 case 0x00000010: /* mcr */ 173 op = "W"; 174 r = cp14_op_mcr (c, p); 175 break; 176 177 case 0x00100010: /* mrc */ 178 op = "R"; 179 r = cp14_op_mrc (c, p); 180 break; 181 182 default: 183 r = 1; 184 break; 185 } 186 187 if (r == 0) { 188 arm_set_clk (c, 4, 1); 189 } 190 191 if (r) { 192 fprintf (stderr, "%08lX C14: %s Rd=%u Rn=%u Rm=%u op2=%u\n", 193 pc, op, 194 (unsigned) arm_ir_rd (c->ir), 195 (unsigned) arm_ir_rn (c->ir), 196 (unsigned) arm_ir_rm (c->ir), 197 (unsigned) arm_get_bits (c->ir, 5, 3) 198 ); fflush (stderr); 199 } 200 201 return (r); 202}