Revision 4b6a83fb target-arm/helper.c

b/target-arm/helper.c
137 137
    g_slist_free(list);
138 138
}
139 139

  
140
void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu,
141
                                       const ARMCPRegInfo *r, void *opaque)
142
{
143
    /* Define implementations of coprocessor registers.
144
     * We store these in a hashtable because typically
145
     * there are less than 150 registers in a space which
146
     * is 16*16*16*8*8 = 262144 in size.
147
     * Wildcarding is supported for the crm, opc1 and opc2 fields.
148
     * If a register is defined twice then the second definition is
149
     * used, so this can be used to define some generic registers and
150
     * then override them with implementation specific variations.
151
     * At least one of the original and the second definition should
152
     * include ARM_CP_OVERRIDE in its type bits -- this is just a guard
153
     * against accidental use.
154
     */
155
    int crm, opc1, opc2;
156
    int crmmin = (r->crm == CP_ANY) ? 0 : r->crm;
157
    int crmmax = (r->crm == CP_ANY) ? 15 : r->crm;
158
    int opc1min = (r->opc1 == CP_ANY) ? 0 : r->opc1;
159
    int opc1max = (r->opc1 == CP_ANY) ? 7 : r->opc1;
160
    int opc2min = (r->opc2 == CP_ANY) ? 0 : r->opc2;
161
    int opc2max = (r->opc2 == CP_ANY) ? 7 : r->opc2;
162
    /* 64 bit registers have only CRm and Opc1 fields */
163
    assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn)));
164
    /* Check that the register definition has enough info to handle
165
     * reads and writes if they are permitted.
166
     */
167
    if (!(r->type & (ARM_CP_SPECIAL|ARM_CP_CONST))) {
168
        if (r->access & PL3_R) {
169
            assert(r->fieldoffset || r->readfn);
170
        }
171
        if (r->access & PL3_W) {
172
            assert(r->fieldoffset || r->writefn);
173
        }
174
    }
175
    /* Bad type field probably means missing sentinel at end of reg list */
176
    assert(cptype_valid(r->type));
177
    for (crm = crmmin; crm <= crmmax; crm++) {
178
        for (opc1 = opc1min; opc1 <= opc1max; opc1++) {
179
            for (opc2 = opc2min; opc2 <= opc2max; opc2++) {
180
                uint32_t *key = g_new(uint32_t, 1);
181
                ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo));
182
                int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0;
183
                *key = ENCODE_CP_REG(r->cp, is64, r->crn, crm, opc1, opc2);
184
                r2->opaque = opaque;
185
                /* Make sure reginfo passed to helpers for wildcarded regs
186
                 * has the correct crm/opc1/opc2 for this reg, not CP_ANY:
187
                 */
188
                r2->crm = crm;
189
                r2->opc1 = opc1;
190
                r2->opc2 = opc2;
191
                /* Overriding of an existing definition must be explicitly
192
                 * requested.
193
                 */
194
                if (!(r->type & ARM_CP_OVERRIDE)) {
195
                    ARMCPRegInfo *oldreg;
196
                    oldreg = g_hash_table_lookup(cpu->cp_regs, key);
197
                    if (oldreg && !(oldreg->type & ARM_CP_OVERRIDE)) {
198
                        fprintf(stderr, "Register redefined: cp=%d %d bit "
199
                                "crn=%d crm=%d opc1=%d opc2=%d, "
200
                                "was %s, now %s\n", r2->cp, 32 + 32 * is64,
201
                                r2->crn, r2->crm, r2->opc1, r2->opc2,
202
                                oldreg->name, r2->name);
203
                        assert(0);
204
                    }
205
                }
206
                g_hash_table_insert(cpu->cp_regs, key, r2);
207
            }
208
        }
209
    }
210
}
211

  
212
void define_arm_cp_regs_with_opaque(ARMCPU *cpu,
213
                                    const ARMCPRegInfo *regs, void *opaque)
214
{
215
    /* Define a whole list of registers */
216
    const ARMCPRegInfo *r;
217
    for (r = regs; r->type != ARM_CP_SENTINEL; r++) {
218
        define_one_arm_cp_reg_with_opaque(cpu, r, opaque);
219
    }
220
}
221

  
222
const ARMCPRegInfo *get_arm_cp_reginfo(ARMCPU *cpu, uint32_t encoded_cp)
223
{
224
    return g_hash_table_lookup(cpu->cp_regs, &encoded_cp);
225
}
226

  
227
int arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri,
228
                        uint64_t value)
229
{
230
    /* Helper coprocessor write function for write-ignore registers */
231
    return 0;
232
}
233

  
234
int arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t *value)
235
{
236
    /* Helper coprocessor write function for read-as-zero registers */
237
    *value = 0;
238
    return 0;
239
}
240

  
140 241
static int bad_mode_switch(CPUARMState *env, int mode)
141 242
{
142 243
    /* Return true if it is not valid for us to switch to

Also available in: Unified diff