|
|
1.1 root 1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <string.h>
4:
5: #include "cpu.h"
6: #include "exec-all.h"
1.1.1.5 root 7: #include "gdbstub.h"
1.1.1.6 root 8: #include "helpers.h"
9: #include "qemu-common.h"
1.1.1.5 root 10:
11: static uint32_t cortexa8_cp15_c0_c1[8] =
12: { 0x1031, 0x11, 0x400, 0, 0x31100003, 0x20000000, 0x01202000, 0x11 };
13:
14: static uint32_t cortexa8_cp15_c0_c2[8] =
15: { 0x00101111, 0x12112111, 0x21232031, 0x11112131, 0x00111142, 0, 0, 0 };
16:
17: static uint32_t mpcore_cp15_c0_c1[8] =
18: { 0x111, 0x1, 0, 0x2, 0x01100103, 0x10020302, 0x01222000, 0 };
19:
20: static uint32_t mpcore_cp15_c0_c2[8] =
21: { 0x00100011, 0x12002111, 0x11221011, 0x01102131, 0x141, 0, 0, 0 };
22:
23: static uint32_t arm1136_cp15_c0_c1[8] =
24: { 0x111, 0x1, 0x2, 0x3, 0x01130003, 0x10030302, 0x01222110, 0 };
25:
26: static uint32_t arm1136_cp15_c0_c2[8] =
27: { 0x00140011, 0x12002111, 0x11231111, 0x01102131, 0x141, 0, 0, 0 };
28:
29: static uint32_t cpu_arm_find_by_name(const char *name);
30:
31: static inline void set_feature(CPUARMState *env, int feature)
32: {
33: env->features |= 1u << feature;
34: }
35:
36: static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
37: {
38: env->cp15.c0_cpuid = id;
39: switch (id) {
40: case ARM_CPUID_ARM926:
41: set_feature(env, ARM_FEATURE_VFP);
42: env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
43: env->cp15.c0_cachetype = 0x1dd20d2;
44: env->cp15.c1_sys = 0x00090078;
45: break;
46: case ARM_CPUID_ARM946:
47: set_feature(env, ARM_FEATURE_MPU);
48: env->cp15.c0_cachetype = 0x0f004006;
49: env->cp15.c1_sys = 0x00000078;
50: break;
51: case ARM_CPUID_ARM1026:
52: set_feature(env, ARM_FEATURE_VFP);
53: set_feature(env, ARM_FEATURE_AUXCR);
54: env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
55: env->cp15.c0_cachetype = 0x1dd20d2;
56: env->cp15.c1_sys = 0x00090078;
57: break;
1.1.1.6 root 58: case ARM_CPUID_ARM1136_R2:
1.1.1.5 root 59: case ARM_CPUID_ARM1136:
60: set_feature(env, ARM_FEATURE_V6);
61: set_feature(env, ARM_FEATURE_VFP);
62: set_feature(env, ARM_FEATURE_AUXCR);
63: env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
64: env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
65: env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000;
66: memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c1, 8 * sizeof(uint32_t));
1.1.1.6 root 67: memcpy(env->cp15.c0_c2, arm1136_cp15_c0_c2, 8 * sizeof(uint32_t));
1.1.1.5 root 68: env->cp15.c0_cachetype = 0x1dd20d2;
69: break;
70: case ARM_CPUID_ARM11MPCORE:
71: set_feature(env, ARM_FEATURE_V6);
72: set_feature(env, ARM_FEATURE_V6K);
73: set_feature(env, ARM_FEATURE_VFP);
74: set_feature(env, ARM_FEATURE_AUXCR);
75: env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
76: env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
77: env->vfp.xregs[ARM_VFP_MVFR1] = 0x00000000;
78: memcpy(env->cp15.c0_c1, mpcore_cp15_c0_c1, 8 * sizeof(uint32_t));
1.1.1.6 root 79: memcpy(env->cp15.c0_c2, mpcore_cp15_c0_c2, 8 * sizeof(uint32_t));
1.1.1.5 root 80: env->cp15.c0_cachetype = 0x1dd20d2;
81: break;
82: case ARM_CPUID_CORTEXA8:
83: set_feature(env, ARM_FEATURE_V6);
84: set_feature(env, ARM_FEATURE_V6K);
85: set_feature(env, ARM_FEATURE_V7);
86: set_feature(env, ARM_FEATURE_AUXCR);
87: set_feature(env, ARM_FEATURE_THUMB2);
88: set_feature(env, ARM_FEATURE_VFP);
89: set_feature(env, ARM_FEATURE_VFP3);
90: set_feature(env, ARM_FEATURE_NEON);
1.1.1.6 root 91: set_feature(env, ARM_FEATURE_THUMB2EE);
1.1.1.5 root 92: env->vfp.xregs[ARM_VFP_FPSID] = 0x410330c0;
93: env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
94: env->vfp.xregs[ARM_VFP_MVFR1] = 0x00011100;
95: memcpy(env->cp15.c0_c1, cortexa8_cp15_c0_c1, 8 * sizeof(uint32_t));
1.1.1.6 root 96: memcpy(env->cp15.c0_c2, cortexa8_cp15_c0_c2, 8 * sizeof(uint32_t));
97: env->cp15.c0_cachetype = 0x82048004;
98: env->cp15.c0_clid = (1 << 27) | (2 << 24) | 3;
99: env->cp15.c0_ccsid[0] = 0xe007e01a; /* 16k L1 dcache. */
100: env->cp15.c0_ccsid[1] = 0x2007e01a; /* 16k L1 icache. */
101: env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */
1.1.1.5 root 102: break;
103: case ARM_CPUID_CORTEXM3:
104: set_feature(env, ARM_FEATURE_V6);
105: set_feature(env, ARM_FEATURE_THUMB2);
106: set_feature(env, ARM_FEATURE_V7);
107: set_feature(env, ARM_FEATURE_M);
108: set_feature(env, ARM_FEATURE_DIV);
109: break;
110: case ARM_CPUID_ANY: /* For userspace emulation. */
111: set_feature(env, ARM_FEATURE_V6);
112: set_feature(env, ARM_FEATURE_V6K);
113: set_feature(env, ARM_FEATURE_V7);
114: set_feature(env, ARM_FEATURE_THUMB2);
115: set_feature(env, ARM_FEATURE_VFP);
116: set_feature(env, ARM_FEATURE_VFP3);
117: set_feature(env, ARM_FEATURE_NEON);
1.1.1.6 root 118: set_feature(env, ARM_FEATURE_THUMB2EE);
1.1.1.5 root 119: set_feature(env, ARM_FEATURE_DIV);
120: break;
121: case ARM_CPUID_TI915T:
122: case ARM_CPUID_TI925T:
123: set_feature(env, ARM_FEATURE_OMAPCP);
124: env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring. */
125: env->cp15.c0_cachetype = 0x5109149;
126: env->cp15.c1_sys = 0x00000070;
127: env->cp15.c15_i_max = 0x000;
128: env->cp15.c15_i_min = 0xff0;
129: break;
130: case ARM_CPUID_PXA250:
131: case ARM_CPUID_PXA255:
132: case ARM_CPUID_PXA260:
133: case ARM_CPUID_PXA261:
134: case ARM_CPUID_PXA262:
135: set_feature(env, ARM_FEATURE_XSCALE);
136: /* JTAG_ID is ((id << 28) | 0x09265013) */
137: env->cp15.c0_cachetype = 0xd172172;
138: env->cp15.c1_sys = 0x00000078;
139: break;
140: case ARM_CPUID_PXA270_A0:
141: case ARM_CPUID_PXA270_A1:
142: case ARM_CPUID_PXA270_B0:
143: case ARM_CPUID_PXA270_B1:
144: case ARM_CPUID_PXA270_C0:
145: case ARM_CPUID_PXA270_C5:
146: set_feature(env, ARM_FEATURE_XSCALE);
147: /* JTAG_ID is ((id << 28) | 0x09265013) */
148: set_feature(env, ARM_FEATURE_IWMMXT);
149: env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
150: env->cp15.c0_cachetype = 0xd172172;
151: env->cp15.c1_sys = 0x00000078;
152: break;
153: default:
154: cpu_abort(env, "Bad CPU ID: %x\n", id);
155: break;
156: }
157: }
1.1 root 158:
1.1.1.2 root 159: void cpu_reset(CPUARMState *env)
160: {
1.1.1.5 root 161: uint32_t id;
1.1.1.6 root 162:
163: if (qemu_loglevel_mask(CPU_LOG_RESET)) {
164: qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
165: log_cpu_state(env, 0);
166: }
167:
1.1.1.5 root 168: id = env->cp15.c0_cpuid;
169: memset(env, 0, offsetof(CPUARMState, breakpoints));
170: if (id)
171: cpu_reset_model_id(env, id);
1.1.1.2 root 172: #if defined (CONFIG_USER_ONLY)
173: env->uncached_cpsr = ARM_CPU_MODE_USR;
174: env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
175: #else
176: /* SVC mode with interrupts disabled. */
177: env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
1.1.1.5 root 178: /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
179: clear at reset. */
180: if (IS_M(env))
181: env->uncached_cpsr &= ~CPSR_I;
1.1.1.2 root 182: env->vfp.xregs[ARM_VFP_FPEXC] = 0;
1.1.1.6 root 183: env->cp15.c2_base_mask = 0xffffc000u;
1.1.1.2 root 184: #endif
185: env->regs[15] = 0;
1.1.1.5 root 186: tlb_flush(env, 1);
1.1.1.2 root 187: }
188:
1.1.1.6 root 189: static int vfp_gdb_get_reg(CPUState *env, uint8_t *buf, int reg)
190: {
191: int nregs;
192:
193: /* VFP data registers are always little-endian. */
194: nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
195: if (reg < nregs) {
196: stfq_le_p(buf, env->vfp.regs[reg]);
197: return 8;
198: }
199: if (arm_feature(env, ARM_FEATURE_NEON)) {
200: /* Aliases for Q regs. */
201: nregs += 16;
202: if (reg < nregs) {
203: stfq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
204: stfq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
205: return 16;
206: }
207: }
208: switch (reg - nregs) {
209: case 0: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSID]); return 4;
210: case 1: stl_p(buf, env->vfp.xregs[ARM_VFP_FPSCR]); return 4;
211: case 2: stl_p(buf, env->vfp.xregs[ARM_VFP_FPEXC]); return 4;
212: }
213: return 0;
214: }
215:
216: static int vfp_gdb_set_reg(CPUState *env, uint8_t *buf, int reg)
217: {
218: int nregs;
219:
220: nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
221: if (reg < nregs) {
222: env->vfp.regs[reg] = ldfq_le_p(buf);
223: return 8;
224: }
225: if (arm_feature(env, ARM_FEATURE_NEON)) {
226: nregs += 16;
227: if (reg < nregs) {
228: env->vfp.regs[(reg - 32) * 2] = ldfq_le_p(buf);
229: env->vfp.regs[(reg - 32) * 2 + 1] = ldfq_le_p(buf + 8);
230: return 16;
231: }
232: }
233: switch (reg - nregs) {
234: case 0: env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4;
235: case 1: env->vfp.xregs[ARM_VFP_FPSCR] = ldl_p(buf); return 4;
236: case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf); return 4;
237: }
238: return 0;
239: }
240:
1.1.1.5 root 241: CPUARMState *cpu_arm_init(const char *cpu_model)
1.1.1.2 root 242: {
243: CPUARMState *env;
1.1.1.5 root 244: uint32_t id;
1.1.1.6 root 245: static int inited = 0;
1.1.1.2 root 246:
1.1.1.5 root 247: id = cpu_arm_find_by_name(cpu_model);
248: if (id == 0)
249: return NULL;
1.1.1.2 root 250: env = qemu_mallocz(sizeof(CPUARMState));
251: cpu_exec_init(env);
1.1.1.6 root 252: if (!inited) {
253: inited = 1;
254: arm_translate_init();
255: }
256:
1.1.1.5 root 257: env->cpu_model_str = cpu_model;
258: env->cp15.c0_cpuid = id;
1.1.1.2 root 259: cpu_reset(env);
1.1.1.6 root 260: if (arm_feature(env, ARM_FEATURE_NEON)) {
261: gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
262: 51, "arm-neon.xml", 0);
263: } else if (arm_feature(env, ARM_FEATURE_VFP3)) {
264: gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
265: 35, "arm-vfp3.xml", 0);
266: } else if (arm_feature(env, ARM_FEATURE_VFP)) {
267: gdb_register_coprocessor(env, vfp_gdb_get_reg, vfp_gdb_set_reg,
268: 19, "arm-vfp.xml", 0);
269: }
1.1.1.7 ! root 270: qemu_init_vcpu(env);
1.1.1.2 root 271: return env;
272: }
273:
1.1.1.5 root 274: struct arm_cpu_t {
275: uint32_t id;
276: const char *name;
277: };
278:
279: static const struct arm_cpu_t arm_cpu_names[] = {
280: { ARM_CPUID_ARM926, "arm926"},
281: { ARM_CPUID_ARM946, "arm946"},
282: { ARM_CPUID_ARM1026, "arm1026"},
283: { ARM_CPUID_ARM1136, "arm1136"},
1.1.1.6 root 284: { ARM_CPUID_ARM1136_R2, "arm1136-r2"},
1.1.1.5 root 285: { ARM_CPUID_ARM11MPCORE, "arm11mpcore"},
286: { ARM_CPUID_CORTEXM3, "cortex-m3"},
287: { ARM_CPUID_CORTEXA8, "cortex-a8"},
288: { ARM_CPUID_TI925T, "ti925t" },
289: { ARM_CPUID_PXA250, "pxa250" },
290: { ARM_CPUID_PXA255, "pxa255" },
291: { ARM_CPUID_PXA260, "pxa260" },
292: { ARM_CPUID_PXA261, "pxa261" },
293: { ARM_CPUID_PXA262, "pxa262" },
294: { ARM_CPUID_PXA270, "pxa270" },
295: { ARM_CPUID_PXA270_A0, "pxa270-a0" },
296: { ARM_CPUID_PXA270_A1, "pxa270-a1" },
297: { ARM_CPUID_PXA270_B0, "pxa270-b0" },
298: { ARM_CPUID_PXA270_B1, "pxa270-b1" },
299: { ARM_CPUID_PXA270_C0, "pxa270-c0" },
300: { ARM_CPUID_PXA270_C5, "pxa270-c5" },
301: { ARM_CPUID_ANY, "any"},
302: { 0, NULL}
303: };
304:
305: void arm_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
1.1.1.2 root 306: {
1.1.1.5 root 307: int i;
308:
309: (*cpu_fprintf)(f, "Available CPUs:\n");
310: for (i = 0; arm_cpu_names[i].name; i++) {
311: (*cpu_fprintf)(f, " %s\n", arm_cpu_names[i].name);
312: }
1.1.1.2 root 313: }
314:
1.1.1.5 root 315: /* return 0 if not found */
316: static uint32_t cpu_arm_find_by_name(const char *name)
1.1.1.2 root 317: {
1.1.1.5 root 318: int i;
319: uint32_t id;
320:
321: id = 0;
322: for (i = 0; arm_cpu_names[i].name; i++) {
323: if (strcmp(name, arm_cpu_names[i].name) == 0) {
324: id = arm_cpu_names[i].id;
325: break;
326: }
1.1.1.2 root 327: }
1.1.1.5 root 328: return id;
1.1.1.2 root 329: }
330:
331: void cpu_arm_close(CPUARMState *env)
332: {
333: free(env);
334: }
335:
1.1.1.5 root 336: uint32_t cpsr_read(CPUARMState *env)
337: {
338: int ZF;
1.1.1.6 root 339: ZF = (env->ZF == 0);
340: return env->uncached_cpsr | (env->NF & 0x80000000) | (ZF << 30) |
1.1.1.5 root 341: (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
342: | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
343: | ((env->condexec_bits & 0xfc) << 8)
344: | (env->GE << 16);
345: }
346:
347: void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
348: {
349: if (mask & CPSR_NZCV) {
1.1.1.6 root 350: env->ZF = (~val) & CPSR_Z;
351: env->NF = val;
1.1.1.5 root 352: env->CF = (val >> 29) & 1;
353: env->VF = (val << 3) & 0x80000000;
354: }
355: if (mask & CPSR_Q)
356: env->QF = ((val & CPSR_Q) != 0);
357: if (mask & CPSR_T)
358: env->thumb = ((val & CPSR_T) != 0);
359: if (mask & CPSR_IT_0_1) {
360: env->condexec_bits &= ~3;
361: env->condexec_bits |= (val >> 25) & 3;
362: }
363: if (mask & CPSR_IT_2_7) {
364: env->condexec_bits &= 3;
365: env->condexec_bits |= (val >> 8) & 0xfc;
366: }
367: if (mask & CPSR_GE) {
368: env->GE = (val >> 16) & 0xf;
369: }
370:
371: if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
372: switch_mode(env, val & CPSR_M);
373: }
374: mask &= ~CACHED_CPSR_BITS;
375: env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
376: }
377:
1.1.1.6 root 378: /* Sign/zero extend */
379: uint32_t HELPER(sxtb16)(uint32_t x)
380: {
381: uint32_t res;
382: res = (uint16_t)(int8_t)x;
383: res |= (uint32_t)(int8_t)(x >> 16) << 16;
384: return res;
385: }
386:
387: uint32_t HELPER(uxtb16)(uint32_t x)
388: {
389: uint32_t res;
390: res = (uint16_t)(uint8_t)x;
391: res |= (uint32_t)(uint8_t)(x >> 16) << 16;
392: return res;
393: }
394:
395: uint32_t HELPER(clz)(uint32_t x)
396: {
397: int count;
398: for (count = 32; x; count--)
399: x >>= 1;
400: return count;
401: }
402:
403: int32_t HELPER(sdiv)(int32_t num, int32_t den)
404: {
405: if (den == 0)
406: return 0;
407: return num / den;
408: }
409:
410: uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
411: {
412: if (den == 0)
413: return 0;
414: return num / den;
415: }
416:
417: uint32_t HELPER(rbit)(uint32_t x)
418: {
419: x = ((x & 0xff000000) >> 24)
420: | ((x & 0x00ff0000) >> 8)
421: | ((x & 0x0000ff00) << 8)
422: | ((x & 0x000000ff) << 24);
423: x = ((x & 0xf0f0f0f0) >> 4)
424: | ((x & 0x0f0f0f0f) << 4);
425: x = ((x & 0x88888888) >> 3)
426: | ((x & 0x44444444) >> 1)
427: | ((x & 0x22222222) << 1)
428: | ((x & 0x11111111) << 3);
429: return x;
430: }
431:
432: uint32_t HELPER(abs)(uint32_t x)
433: {
434: return ((int32_t)x < 0) ? -x : x;
435: }
436:
1.1.1.5 root 437: #if defined(CONFIG_USER_ONLY)
1.1 root 438:
439: void do_interrupt (CPUState *env)
440: {
441: env->exception_index = -1;
442: }
443:
1.1.1.5 root 444: /* Structure used to record exclusive memory locations. */
445: typedef struct mmon_state {
446: struct mmon_state *next;
447: CPUARMState *cpu_env;
448: uint32_t addr;
449: } mmon_state;
450:
451: /* Chain of current locks. */
452: static mmon_state* mmon_head = NULL;
453:
1.1 root 454: int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1.1.1.5 root 455: int mmu_idx, int is_softmmu)
1.1 root 456: {
457: if (rw == 2) {
458: env->exception_index = EXCP_PREFETCH_ABORT;
459: env->cp15.c6_insn = address;
460: } else {
461: env->exception_index = EXCP_DATA_ABORT;
462: env->cp15.c6_data = address;
463: }
464: return 1;
465: }
466:
1.1.1.5 root 467: static void allocate_mmon_state(CPUState *env)
468: {
469: env->mmon_entry = malloc(sizeof (mmon_state));
470: memset (env->mmon_entry, 0, sizeof (mmon_state));
471: env->mmon_entry->cpu_env = env;
472: mmon_head = env->mmon_entry;
473: }
474:
475: /* Flush any monitor locks for the specified address. */
476: static void flush_mmon(uint32_t addr)
477: {
478: mmon_state *mon;
479:
480: for (mon = mmon_head; mon; mon = mon->next)
481: {
482: if (mon->addr != addr)
483: continue;
484:
485: mon->addr = 0;
486: break;
487: }
488: }
489:
490: /* Mark an address for exclusive access. */
1.1.1.6 root 491: void HELPER(mark_exclusive)(CPUState *env, uint32_t addr)
1.1.1.5 root 492: {
493: if (!env->mmon_entry)
494: allocate_mmon_state(env);
495: /* Clear any previous locks. */
496: flush_mmon(addr);
497: env->mmon_entry->addr = addr;
498: }
499:
500: /* Test if an exclusive address is still exclusive. Returns zero
501: if the address is still exclusive. */
1.1.1.6 root 502: uint32_t HELPER(test_exclusive)(CPUState *env, uint32_t addr)
1.1.1.5 root 503: {
504: int res;
505:
506: if (!env->mmon_entry)
507: return 1;
508: if (env->mmon_entry->addr == addr)
509: res = 0;
510: else
511: res = 1;
512: flush_mmon(addr);
513: return res;
514: }
515:
1.1.1.6 root 516: void HELPER(clrex)(CPUState *env)
1.1.1.5 root 517: {
518: if (!(env->mmon_entry && env->mmon_entry->addr))
519: return;
520: flush_mmon(env->mmon_entry->addr);
521: }
522:
523: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1.1 root 524: {
525: return addr;
526: }
527:
528: /* These should probably raise undefined insn exceptions. */
1.1.1.6 root 529: void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
1.1.1.5 root 530: {
531: int op1 = (insn >> 8) & 0xf;
532: cpu_abort(env, "cp%i insn %08x\n", op1, insn);
533: return;
534: }
535:
1.1.1.6 root 536: uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
1.1.1.5 root 537: {
538: int op1 = (insn >> 8) & 0xf;
539: cpu_abort(env, "cp%i insn %08x\n", op1, insn);
540: return 0;
541: }
542:
1.1.1.6 root 543: void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
1.1 root 544: {
545: cpu_abort(env, "cp15 insn %08x\n", insn);
546: }
547:
1.1.1.6 root 548: uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
1.1 root 549: {
550: cpu_abort(env, "cp15 insn %08x\n", insn);
551: return 0;
552: }
553:
1.1.1.5 root 554: /* These should probably raise undefined insn exceptions. */
1.1.1.6 root 555: void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
1.1.1.5 root 556: {
557: cpu_abort(env, "v7m_mrs %d\n", reg);
558: }
559:
1.1.1.6 root 560: uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
1.1.1.5 root 561: {
562: cpu_abort(env, "v7m_mrs %d\n", reg);
563: return 0;
564: }
565:
1.1 root 566: void switch_mode(CPUState *env, int mode)
567: {
568: if (mode != ARM_CPU_MODE_USR)
569: cpu_abort(env, "Tried to switch out of user mode\n");
570: }
571:
1.1.1.6 root 572: void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
1.1.1.5 root 573: {
574: cpu_abort(env, "banked r13 write\n");
575: }
576:
1.1.1.6 root 577: uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
1.1.1.5 root 578: {
579: cpu_abort(env, "banked r13 read\n");
580: return 0;
581: }
582:
1.1 root 583: #else
584:
1.1.1.4 root 585: extern int semihosting_enabled;
586:
1.1 root 587: /* Map CPU modes onto saved register banks. */
588: static inline int bank_number (int mode)
589: {
590: switch (mode) {
591: case ARM_CPU_MODE_USR:
592: case ARM_CPU_MODE_SYS:
593: return 0;
594: case ARM_CPU_MODE_SVC:
595: return 1;
596: case ARM_CPU_MODE_ABT:
597: return 2;
598: case ARM_CPU_MODE_UND:
599: return 3;
600: case ARM_CPU_MODE_IRQ:
601: return 4;
602: case ARM_CPU_MODE_FIQ:
603: return 5;
604: }
605: cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
606: return -1;
607: }
608:
609: void switch_mode(CPUState *env, int mode)
610: {
611: int old_mode;
612: int i;
613:
614: old_mode = env->uncached_cpsr & CPSR_M;
615: if (mode == old_mode)
616: return;
617:
618: if (old_mode == ARM_CPU_MODE_FIQ) {
619: memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
1.1.1.2 root 620: memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
1.1 root 621: } else if (mode == ARM_CPU_MODE_FIQ) {
622: memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
1.1.1.2 root 623: memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
1.1 root 624: }
625:
626: i = bank_number(old_mode);
627: env->banked_r13[i] = env->regs[13];
628: env->banked_r14[i] = env->regs[14];
629: env->banked_spsr[i] = env->spsr;
630:
631: i = bank_number(mode);
632: env->regs[13] = env->banked_r13[i];
633: env->regs[14] = env->banked_r14[i];
634: env->spsr = env->banked_spsr[i];
635: }
636:
1.1.1.5 root 637: static void v7m_push(CPUARMState *env, uint32_t val)
638: {
639: env->regs[13] -= 4;
640: stl_phys(env->regs[13], val);
641: }
642:
643: static uint32_t v7m_pop(CPUARMState *env)
644: {
645: uint32_t val;
646: val = ldl_phys(env->regs[13]);
647: env->regs[13] += 4;
648: return val;
649: }
650:
651: /* Switch to V7M main or process stack pointer. */
652: static void switch_v7m_sp(CPUARMState *env, int process)
653: {
654: uint32_t tmp;
655: if (env->v7m.current_sp != process) {
656: tmp = env->v7m.other_sp;
657: env->v7m.other_sp = env->regs[13];
658: env->regs[13] = tmp;
659: env->v7m.current_sp = process;
660: }
661: }
662:
663: static void do_v7m_exception_exit(CPUARMState *env)
664: {
665: uint32_t type;
666: uint32_t xpsr;
667:
668: type = env->regs[15];
669: if (env->v7m.exception != 0)
670: armv7m_nvic_complete_irq(env->v7m.nvic, env->v7m.exception);
671:
672: /* Switch to the target stack. */
673: switch_v7m_sp(env, (type & 4) != 0);
674: /* Pop registers. */
675: env->regs[0] = v7m_pop(env);
676: env->regs[1] = v7m_pop(env);
677: env->regs[2] = v7m_pop(env);
678: env->regs[3] = v7m_pop(env);
679: env->regs[12] = v7m_pop(env);
680: env->regs[14] = v7m_pop(env);
681: env->regs[15] = v7m_pop(env);
682: xpsr = v7m_pop(env);
683: xpsr_write(env, xpsr, 0xfffffdff);
684: /* Undo stack alignment. */
685: if (xpsr & 0x200)
686: env->regs[13] |= 4;
687: /* ??? The exception return type specifies Thread/Handler mode. However
688: this is also implied by the xPSR value. Not sure what to do
689: if there is a mismatch. */
690: /* ??? Likewise for mismatches between the CONTROL register and the stack
691: pointer. */
692: }
693:
1.1.1.7 ! root 694: static void do_interrupt_v7m(CPUARMState *env)
1.1.1.5 root 695: {
696: uint32_t xpsr = xpsr_read(env);
697: uint32_t lr;
698: uint32_t addr;
699:
700: lr = 0xfffffff1;
701: if (env->v7m.current_sp)
702: lr |= 4;
703: if (env->v7m.exception == 0)
704: lr |= 8;
705:
706: /* For exceptions we just mark as pending on the NVIC, and let that
707: handle it. */
708: /* TODO: Need to escalate if the current priority is higher than the
709: one we're raising. */
710: switch (env->exception_index) {
711: case EXCP_UDEF:
712: armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_USAGE);
713: return;
714: case EXCP_SWI:
715: env->regs[15] += 2;
716: armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_SVC);
717: return;
718: case EXCP_PREFETCH_ABORT:
719: case EXCP_DATA_ABORT:
720: armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_MEM);
721: return;
722: case EXCP_BKPT:
723: if (semihosting_enabled) {
724: int nr;
725: nr = lduw_code(env->regs[15]) & 0xff;
726: if (nr == 0xab) {
727: env->regs[15] += 2;
728: env->regs[0] = do_arm_semihosting(env);
729: return;
730: }
731: }
732: armv7m_nvic_set_pending(env->v7m.nvic, ARMV7M_EXCP_DEBUG);
733: return;
734: case EXCP_IRQ:
735: env->v7m.exception = armv7m_nvic_acknowledge_irq(env->v7m.nvic);
736: break;
737: case EXCP_EXCEPTION_EXIT:
738: do_v7m_exception_exit(env);
739: return;
740: default:
741: cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
742: return; /* Never happens. Keep compiler happy. */
743: }
744:
745: /* Align stack pointer. */
746: /* ??? Should only do this if Configuration Control Register
747: STACKALIGN bit is set. */
748: if (env->regs[13] & 4) {
1.1.1.6 root 749: env->regs[13] -= 4;
1.1.1.5 root 750: xpsr |= 0x200;
751: }
1.1.1.6 root 752: /* Switch to the handler mode. */
1.1.1.5 root 753: v7m_push(env, xpsr);
754: v7m_push(env, env->regs[15]);
755: v7m_push(env, env->regs[14]);
756: v7m_push(env, env->regs[12]);
757: v7m_push(env, env->regs[3]);
758: v7m_push(env, env->regs[2]);
759: v7m_push(env, env->regs[1]);
760: v7m_push(env, env->regs[0]);
761: switch_v7m_sp(env, 0);
762: env->uncached_cpsr &= ~CPSR_IT;
763: env->regs[14] = lr;
764: addr = ldl_phys(env->v7m.vecbase + env->v7m.exception * 4);
765: env->regs[15] = addr & 0xfffffffe;
766: env->thumb = addr & 1;
767: }
768:
1.1 root 769: /* Handle a CPU exception. */
770: void do_interrupt(CPUARMState *env)
771: {
772: uint32_t addr;
773: uint32_t mask;
774: int new_mode;
775: uint32_t offset;
776:
1.1.1.5 root 777: if (IS_M(env)) {
778: do_interrupt_v7m(env);
779: return;
780: }
1.1 root 781: /* TODO: Vectored interrupt controller. */
782: switch (env->exception_index) {
783: case EXCP_UDEF:
784: new_mode = ARM_CPU_MODE_UND;
785: addr = 0x04;
786: mask = CPSR_I;
787: if (env->thumb)
788: offset = 2;
789: else
790: offset = 4;
791: break;
792: case EXCP_SWI:
1.1.1.4 root 793: if (semihosting_enabled) {
794: /* Check for semihosting interrupt. */
795: if (env->thumb) {
796: mask = lduw_code(env->regs[15] - 2) & 0xff;
797: } else {
798: mask = ldl_code(env->regs[15] - 4) & 0xffffff;
799: }
800: /* Only intercept calls from privileged modes, to provide some
801: semblance of security. */
802: if (((mask == 0x123456 && !env->thumb)
803: || (mask == 0xab && env->thumb))
804: && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
805: env->regs[0] = do_arm_semihosting(env);
806: return;
807: }
808: }
1.1 root 809: new_mode = ARM_CPU_MODE_SVC;
810: addr = 0x08;
811: mask = CPSR_I;
1.1.1.6 root 812: /* The PC already points to the next instruction. */
1.1 root 813: offset = 0;
814: break;
1.1.1.2 root 815: case EXCP_BKPT:
1.1.1.5 root 816: /* See if this is a semihosting syscall. */
817: if (env->thumb && semihosting_enabled) {
818: mask = lduw_code(env->regs[15]) & 0xff;
819: if (mask == 0xab
820: && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
821: env->regs[15] += 2;
822: env->regs[0] = do_arm_semihosting(env);
823: return;
824: }
825: }
826: /* Fall through to prefetch abort. */
827: case EXCP_PREFETCH_ABORT:
1.1 root 828: new_mode = ARM_CPU_MODE_ABT;
829: addr = 0x0c;
830: mask = CPSR_A | CPSR_I;
831: offset = 4;
832: break;
833: case EXCP_DATA_ABORT:
834: new_mode = ARM_CPU_MODE_ABT;
835: addr = 0x10;
836: mask = CPSR_A | CPSR_I;
837: offset = 8;
838: break;
839: case EXCP_IRQ:
840: new_mode = ARM_CPU_MODE_IRQ;
841: addr = 0x18;
842: /* Disable IRQ and imprecise data aborts. */
843: mask = CPSR_A | CPSR_I;
844: offset = 4;
845: break;
846: case EXCP_FIQ:
847: new_mode = ARM_CPU_MODE_FIQ;
848: addr = 0x1c;
849: /* Disable FIQ, IRQ and imprecise data aborts. */
850: mask = CPSR_A | CPSR_I | CPSR_F;
851: offset = 4;
852: break;
853: default:
854: cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
855: return; /* Never happens. Keep compiler happy. */
856: }
857: /* High vectors. */
858: if (env->cp15.c1_sys & (1 << 13)) {
859: addr += 0xffff0000;
860: }
861: switch_mode (env, new_mode);
862: env->spsr = cpsr_read(env);
1.1.1.5 root 863: /* Clear IT bits. */
864: env->condexec_bits = 0;
1.1 root 865: /* Switch to the new mode, and switch to Arm mode. */
866: /* ??? Thumb interrupt handlers not implemented. */
867: env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
868: env->uncached_cpsr |= mask;
869: env->thumb = 0;
870: env->regs[14] = env->regs[15] + offset;
871: env->regs[15] = addr;
872: env->interrupt_request |= CPU_INTERRUPT_EXITTB;
873: }
874:
875: /* Check section/page access permissions.
876: Returns the page protection flags, or zero if the access is not
877: permitted. */
878: static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
879: int is_user)
880: {
1.1.1.5 root 881: int prot_ro;
882:
1.1 root 883: if (domain == 3)
884: return PAGE_READ | PAGE_WRITE;
885:
1.1.1.5 root 886: if (access_type == 1)
887: prot_ro = 0;
888: else
889: prot_ro = PAGE_READ;
890:
1.1 root 891: switch (ap) {
892: case 0:
1.1.1.4 root 893: if (access_type == 1)
1.1 root 894: return 0;
895: switch ((env->cp15.c1_sys >> 8) & 3) {
896: case 1:
897: return is_user ? 0 : PAGE_READ;
898: case 2:
899: return PAGE_READ;
900: default:
901: return 0;
902: }
903: case 1:
904: return is_user ? 0 : PAGE_READ | PAGE_WRITE;
905: case 2:
906: if (is_user)
1.1.1.5 root 907: return prot_ro;
1.1 root 908: else
909: return PAGE_READ | PAGE_WRITE;
910: case 3:
911: return PAGE_READ | PAGE_WRITE;
1.1.1.6 root 912: case 4: /* Reserved. */
1.1.1.5 root 913: return 0;
914: case 5:
915: return is_user ? 0 : prot_ro;
916: case 6:
917: return prot_ro;
1.1.1.6 root 918: case 7:
919: if (!arm_feature (env, ARM_FEATURE_V7))
920: return 0;
921: return prot_ro;
1.1 root 922: default:
923: abort();
924: }
925: }
926:
1.1.1.6 root 927: static uint32_t get_level1_table_address(CPUState *env, uint32_t address)
928: {
929: uint32_t table;
930:
931: if (address & env->cp15.c2_mask)
932: table = env->cp15.c2_base1 & 0xffffc000;
933: else
934: table = env->cp15.c2_base0 & env->cp15.c2_base_mask;
935:
936: table |= (address >> 18) & 0x3ffc;
937: return table;
938: }
939:
1.1.1.5 root 940: static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
941: int is_user, uint32_t *phys_ptr, int *prot)
1.1 root 942: {
943: int code;
944: uint32_t table;
945: uint32_t desc;
946: int type;
947: int ap;
948: int domain;
949: uint32_t phys_addr;
950:
1.1.1.5 root 951: /* Pagetable walk. */
952: /* Lookup l1 descriptor. */
1.1.1.6 root 953: table = get_level1_table_address(env, address);
1.1.1.5 root 954: desc = ldl_phys(table);
955: type = (desc & 3);
956: domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
957: if (type == 0) {
1.1.1.6 root 958: /* Section translation fault. */
1.1.1.5 root 959: code = 5;
960: goto do_fault;
961: }
962: if (domain == 0 || domain == 2) {
963: if (type == 2)
964: code = 9; /* Section domain fault. */
965: else
966: code = 11; /* Page domain fault. */
967: goto do_fault;
968: }
969: if (type == 2) {
970: /* 1Mb section. */
971: phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
972: ap = (desc >> 10) & 3;
973: code = 13;
1.1 root 974: } else {
1.1.1.5 root 975: /* Lookup l2 entry. */
976: if (type == 1) {
977: /* Coarse pagetable. */
978: table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
979: } else {
980: /* Fine pagetable. */
981: table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
982: }
1.1 root 983: desc = ldl_phys(table);
1.1.1.5 root 984: switch (desc & 3) {
985: case 0: /* Page translation fault. */
986: code = 7;
1.1 root 987: goto do_fault;
1.1.1.5 root 988: case 1: /* 64k page. */
989: phys_addr = (desc & 0xffff0000) | (address & 0xffff);
990: ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
991: break;
992: case 2: /* 4k page. */
993: phys_addr = (desc & 0xfffff000) | (address & 0xfff);
994: ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
995: break;
996: case 3: /* 1k page. */
997: if (type == 1) {
998: if (arm_feature(env, ARM_FEATURE_XSCALE)) {
999: phys_addr = (desc & 0xfffff000) | (address & 0xfff);
1000: } else {
1001: /* Page translation fault. */
1002: code = 7;
1003: goto do_fault;
1004: }
1005: } else {
1006: phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
1007: }
1008: ap = (desc >> 4) & 3;
1009: break;
1010: default:
1011: /* Never happens, but compiler isn't smart enough to tell. */
1012: abort();
1.1 root 1013: }
1.1.1.5 root 1014: code = 15;
1015: }
1016: *prot = check_ap(env, ap, domain, access_type, is_user);
1017: if (!*prot) {
1018: /* Access permission fault. */
1019: goto do_fault;
1020: }
1021: *phys_ptr = phys_addr;
1022: return 0;
1023: do_fault:
1024: return code | (domain << 4);
1025: }
1026:
1027: static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
1028: int is_user, uint32_t *phys_ptr, int *prot)
1029: {
1030: int code;
1031: uint32_t table;
1032: uint32_t desc;
1033: uint32_t xn;
1034: int type;
1035: int ap;
1036: int domain;
1037: uint32_t phys_addr;
1038:
1039: /* Pagetable walk. */
1040: /* Lookup l1 descriptor. */
1.1.1.6 root 1041: table = get_level1_table_address(env, address);
1.1.1.5 root 1042: desc = ldl_phys(table);
1043: type = (desc & 3);
1044: if (type == 0) {
1.1.1.6 root 1045: /* Section translation fault. */
1.1.1.5 root 1046: code = 5;
1047: domain = 0;
1048: goto do_fault;
1049: } else if (type == 2 && (desc & (1 << 18))) {
1050: /* Supersection. */
1051: domain = 0;
1052: } else {
1053: /* Section or page. */
1054: domain = (desc >> 4) & 0x1e;
1055: }
1056: domain = (env->cp15.c3 >> domain) & 3;
1057: if (domain == 0 || domain == 2) {
1058: if (type == 2)
1059: code = 9; /* Section domain fault. */
1060: else
1061: code = 11; /* Page domain fault. */
1062: goto do_fault;
1063: }
1064: if (type == 2) {
1065: if (desc & (1 << 18)) {
1066: /* Supersection. */
1067: phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
1.1 root 1068: } else {
1.1.1.5 root 1069: /* Section. */
1070: phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
1.1 root 1071: }
1.1.1.5 root 1072: ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
1073: xn = desc & (1 << 4);
1074: code = 13;
1075: } else {
1076: /* Lookup l2 entry. */
1077: table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
1078: desc = ldl_phys(table);
1079: ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
1080: switch (desc & 3) {
1081: case 0: /* Page translation fault. */
1082: code = 7;
1.1 root 1083: goto do_fault;
1.1.1.5 root 1084: case 1: /* 64k page. */
1085: phys_addr = (desc & 0xffff0000) | (address & 0xffff);
1086: xn = desc & (1 << 15);
1087: break;
1088: case 2: case 3: /* 4k page. */
1089: phys_addr = (desc & 0xfffff000) | (address & 0xfff);
1090: xn = desc & 1;
1091: break;
1092: default:
1093: /* Never happens, but compiler isn't smart enough to tell. */
1094: abort();
1.1 root 1095: }
1.1.1.5 root 1096: code = 15;
1097: }
1098: if (xn && access_type == 2)
1099: goto do_fault;
1100:
1.1.1.6 root 1101: /* The simplified model uses AP[0] as an access control bit. */
1102: if ((env->cp15.c1_sys & (1 << 29)) && (ap & 1) == 0) {
1103: /* Access flag fault. */
1104: code = (code == 15) ? 6 : 3;
1105: goto do_fault;
1106: }
1.1.1.5 root 1107: *prot = check_ap(env, ap, domain, access_type, is_user);
1108: if (!*prot) {
1109: /* Access permission fault. */
1110: goto do_fault;
1.1 root 1111: }
1.1.1.5 root 1112: *phys_ptr = phys_addr;
1.1 root 1113: return 0;
1114: do_fault:
1115: return code | (domain << 4);
1116: }
1117:
1.1.1.5 root 1118: static int get_phys_addr_mpu(CPUState *env, uint32_t address, int access_type,
1119: int is_user, uint32_t *phys_ptr, int *prot)
1120: {
1121: int n;
1122: uint32_t mask;
1123: uint32_t base;
1124:
1125: *phys_ptr = address;
1126: for (n = 7; n >= 0; n--) {
1127: base = env->cp15.c6_region[n];
1128: if ((base & 1) == 0)
1129: continue;
1130: mask = 1 << ((base >> 1) & 0x1f);
1131: /* Keep this shift separate from the above to avoid an
1132: (undefined) << 32. */
1133: mask = (mask << 1) - 1;
1134: if (((base ^ address) & ~mask) == 0)
1135: break;
1136: }
1137: if (n < 0)
1138: return 2;
1139:
1140: if (access_type == 2) {
1141: mask = env->cp15.c5_insn;
1142: } else {
1143: mask = env->cp15.c5_data;
1144: }
1145: mask = (mask >> (n * 4)) & 0xf;
1146: switch (mask) {
1147: case 0:
1148: return 1;
1149: case 1:
1150: if (is_user)
1151: return 1;
1152: *prot = PAGE_READ | PAGE_WRITE;
1153: break;
1154: case 2:
1155: *prot = PAGE_READ;
1156: if (!is_user)
1157: *prot |= PAGE_WRITE;
1158: break;
1159: case 3:
1160: *prot = PAGE_READ | PAGE_WRITE;
1161: break;
1162: case 5:
1163: if (is_user)
1164: return 1;
1165: *prot = PAGE_READ;
1166: break;
1167: case 6:
1168: *prot = PAGE_READ;
1169: break;
1170: default:
1171: /* Bad permission. */
1172: return 1;
1173: }
1174: return 0;
1175: }
1176:
1177: static inline int get_phys_addr(CPUState *env, uint32_t address,
1178: int access_type, int is_user,
1179: uint32_t *phys_ptr, int *prot)
1180: {
1181: /* Fast Context Switch Extension. */
1182: if (address < 0x02000000)
1183: address += env->cp15.c13_fcse;
1184:
1185: if ((env->cp15.c1_sys & 1) == 0) {
1186: /* MMU/MPU disabled. */
1187: *phys_ptr = address;
1188: *prot = PAGE_READ | PAGE_WRITE;
1189: return 0;
1190: } else if (arm_feature(env, ARM_FEATURE_MPU)) {
1191: return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
1192: prot);
1193: } else if (env->cp15.c1_sys & (1 << 23)) {
1194: return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
1195: prot);
1196: } else {
1197: return get_phys_addr_v5(env, address, access_type, is_user, phys_ptr,
1198: prot);
1199: }
1200: }
1201:
1.1 root 1202: int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
1.1.1.5 root 1203: int access_type, int mmu_idx, int is_softmmu)
1.1 root 1204: {
1205: uint32_t phys_addr;
1206: int prot;
1.1.1.5 root 1207: int ret, is_user;
1.1 root 1208:
1.1.1.5 root 1209: is_user = mmu_idx == MMU_USER_IDX;
1.1 root 1210: ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
1211: if (ret == 0) {
1212: /* Map a single [sub]page. */
1213: phys_addr &= ~(uint32_t)0x3ff;
1214: address &= ~(uint32_t)0x3ff;
1.1.1.5 root 1215: return tlb_set_page (env, address, phys_addr, prot, mmu_idx,
1.1 root 1216: is_softmmu);
1217: }
1218:
1219: if (access_type == 2) {
1220: env->cp15.c5_insn = ret;
1221: env->cp15.c6_insn = address;
1222: env->exception_index = EXCP_PREFETCH_ABORT;
1223: } else {
1224: env->cp15.c5_data = ret;
1.1.1.5 root 1225: if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
1226: env->cp15.c5_data |= (1 << 11);
1.1 root 1227: env->cp15.c6_data = address;
1228: env->exception_index = EXCP_DATA_ABORT;
1229: }
1230: return 1;
1231: }
1232:
1.1.1.5 root 1233: target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1.1 root 1234: {
1235: uint32_t phys_addr;
1236: int prot;
1237: int ret;
1238:
1239: ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
1240:
1241: if (ret != 0)
1242: return -1;
1243:
1244: return phys_addr;
1245: }
1246:
1.1.1.5 root 1247: /* Not really implemented. Need to figure out a sane way of doing this.
1248: Maybe add generic watchpoint support and use that. */
1249:
1.1.1.6 root 1250: void HELPER(mark_exclusive)(CPUState *env, uint32_t addr)
1.1.1.5 root 1251: {
1252: env->mmon_addr = addr;
1253: }
1254:
1.1.1.6 root 1255: uint32_t HELPER(test_exclusive)(CPUState *env, uint32_t addr)
1.1.1.5 root 1256: {
1257: return (env->mmon_addr != addr);
1258: }
1259:
1.1.1.6 root 1260: void HELPER(clrex)(CPUState *env)
1.1.1.5 root 1261: {
1262: env->mmon_addr = -1;
1263: }
1264:
1.1.1.6 root 1265: void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
1.1.1.5 root 1266: {
1267: int cp_num = (insn >> 8) & 0xf;
1268: int cp_info = (insn >> 5) & 7;
1269: int src = (insn >> 16) & 0xf;
1270: int operand = insn & 0xf;
1271:
1272: if (env->cp[cp_num].cp_write)
1273: env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
1274: cp_info, src, operand, val);
1275: }
1276:
1.1.1.6 root 1277: uint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
1.1.1.5 root 1278: {
1279: int cp_num = (insn >> 8) & 0xf;
1280: int cp_info = (insn >> 5) & 7;
1281: int dest = (insn >> 16) & 0xf;
1282: int operand = insn & 0xf;
1283:
1284: if (env->cp[cp_num].cp_read)
1285: return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
1286: cp_info, dest, operand);
1287: return 0;
1288: }
1289:
1290: /* Return basic MPU access permission bits. */
1291: static uint32_t simple_mpu_ap_bits(uint32_t val)
1292: {
1293: uint32_t ret;
1294: uint32_t mask;
1295: int i;
1296: ret = 0;
1297: mask = 3;
1298: for (i = 0; i < 16; i += 2) {
1299: ret |= (val >> i) & mask;
1300: mask <<= 2;
1301: }
1302: return ret;
1303: }
1304:
1305: /* Pad basic MPU access permission bits to extended format. */
1306: static uint32_t extended_mpu_ap_bits(uint32_t val)
1307: {
1308: uint32_t ret;
1309: uint32_t mask;
1310: int i;
1311: ret = 0;
1312: mask = 3;
1313: for (i = 0; i < 16; i += 2) {
1314: ret |= (val & mask) << i;
1315: mask <<= 2;
1316: }
1317: return ret;
1318: }
1319:
1.1.1.6 root 1320: void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
1.1 root 1321: {
1.1.1.5 root 1322: int op1;
1323: int op2;
1324: int crm;
1.1 root 1325:
1.1.1.5 root 1326: op1 = (insn >> 21) & 7;
1.1 root 1327: op2 = (insn >> 5) & 7;
1.1.1.5 root 1328: crm = insn & 0xf;
1.1 root 1329: switch ((insn >> 16) & 0xf) {
1.1.1.5 root 1330: case 0:
1331: /* ID codes. */
1332: if (arm_feature(env, ARM_FEATURE_XSCALE))
1333: break;
1334: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1335: break;
1.1.1.6 root 1336: if (arm_feature(env, ARM_FEATURE_V7)
1337: && op1 == 2 && crm == 0 && op2 == 0) {
1338: env->cp15.c0_cssel = val & 0xf;
1339: break;
1340: }
1.1 root 1341: goto bad_reg;
1342: case 1: /* System configuration. */
1.1.1.5 root 1343: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1344: op2 = 0;
1.1 root 1345: switch (op2) {
1346: case 0:
1.1.1.5 root 1347: if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
1348: env->cp15.c1_sys = val;
1.1 root 1349: /* ??? Lots of these bits are not implemented. */
1350: /* This may enable/disable the MMU, so do a TLB flush. */
1351: tlb_flush(env, 1);
1352: break;
1.1.1.5 root 1353: case 1: /* Auxiliary cotrol register. */
1354: if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1355: env->cp15.c1_xscaleauxcr = val;
1356: break;
1357: }
1358: /* Not implemented. */
1359: break;
1.1 root 1360: case 2:
1.1.1.5 root 1361: if (arm_feature(env, ARM_FEATURE_XSCALE))
1362: goto bad_reg;
1.1.1.6 root 1363: if (env->cp15.c1_coproc != val) {
1364: env->cp15.c1_coproc = val;
1365: /* ??? Is this safe when called from within a TB? */
1366: tb_flush(env);
1367: }
1.1.1.5 root 1368: break;
1.1 root 1369: default:
1370: goto bad_reg;
1371: }
1372: break;
1.1.1.5 root 1373: case 2: /* MMU Page table control / MPU cache control. */
1374: if (arm_feature(env, ARM_FEATURE_MPU)) {
1375: switch (op2) {
1376: case 0:
1377: env->cp15.c2_data = val;
1378: break;
1379: case 1:
1380: env->cp15.c2_insn = val;
1381: break;
1382: default:
1383: goto bad_reg;
1384: }
1385: } else {
1386: switch (op2) {
1387: case 0:
1388: env->cp15.c2_base0 = val;
1389: break;
1390: case 1:
1391: env->cp15.c2_base1 = val;
1392: break;
1393: case 2:
1.1.1.6 root 1394: val &= 7;
1395: env->cp15.c2_control = val;
1.1.1.5 root 1396: env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> val);
1.1.1.6 root 1397: env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> val);
1.1.1.5 root 1398: break;
1399: default:
1400: goto bad_reg;
1401: }
1402: }
1.1 root 1403: break;
1.1.1.5 root 1404: case 3: /* MMU Domain access control / MPU write buffer control. */
1.1 root 1405: env->cp15.c3 = val;
1.1.1.5 root 1406: tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */
1.1 root 1407: break;
1408: case 4: /* Reserved. */
1409: goto bad_reg;
1.1.1.5 root 1410: case 5: /* MMU Fault status / MPU access permission. */
1411: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1412: op2 = 0;
1.1 root 1413: switch (op2) {
1414: case 0:
1.1.1.5 root 1415: if (arm_feature(env, ARM_FEATURE_MPU))
1416: val = extended_mpu_ap_bits(val);
1.1 root 1417: env->cp15.c5_data = val;
1418: break;
1419: case 1:
1.1.1.5 root 1420: if (arm_feature(env, ARM_FEATURE_MPU))
1421: val = extended_mpu_ap_bits(val);
1.1 root 1422: env->cp15.c5_insn = val;
1423: break;
1.1.1.5 root 1424: case 2:
1425: if (!arm_feature(env, ARM_FEATURE_MPU))
1426: goto bad_reg;
1427: env->cp15.c5_data = val;
1.1 root 1428: break;
1.1.1.5 root 1429: case 3:
1430: if (!arm_feature(env, ARM_FEATURE_MPU))
1431: goto bad_reg;
1432: env->cp15.c5_insn = val;
1.1 root 1433: break;
1434: default:
1435: goto bad_reg;
1436: }
1437: break;
1.1.1.5 root 1438: case 6: /* MMU Fault address / MPU base/size. */
1439: if (arm_feature(env, ARM_FEATURE_MPU)) {
1440: if (crm >= 8)
1441: goto bad_reg;
1442: env->cp15.c6_region[crm] = val;
1443: } else {
1444: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1445: op2 = 0;
1446: switch (op2) {
1447: case 0:
1448: env->cp15.c6_data = val;
1449: break;
1450: case 1: /* ??? This is WFAR on armv6 */
1451: case 2:
1452: env->cp15.c6_insn = val;
1453: break;
1454: default:
1455: goto bad_reg;
1456: }
1457: }
1458: break;
1.1 root 1459: case 7: /* Cache control. */
1.1.1.5 root 1460: env->cp15.c15_i_max = 0x000;
1461: env->cp15.c15_i_min = 0xff0;
1.1 root 1462: /* No cache, so nothing to do. */
1.1.1.5 root 1463: /* ??? MPCore has VA to PA translation functions. */
1.1 root 1464: break;
1465: case 8: /* MMU TLB control. */
1466: switch (op2) {
1467: case 0: /* Invalidate all. */
1468: tlb_flush(env, 0);
1469: break;
1470: case 1: /* Invalidate single TLB entry. */
1471: #if 0
1472: /* ??? This is wrong for large pages and sections. */
1473: /* As an ugly hack to make linux work we always flush a 4K
1474: pages. */
1475: val &= 0xfffff000;
1476: tlb_flush_page(env, val);
1477: tlb_flush_page(env, val + 0x400);
1478: tlb_flush_page(env, val + 0x800);
1479: tlb_flush_page(env, val + 0xc00);
1480: #else
1481: tlb_flush(env, 1);
1482: #endif
1483: break;
1.1.1.5 root 1484: case 2: /* Invalidate on ASID. */
1485: tlb_flush(env, val == 0);
1486: break;
1487: case 3: /* Invalidate single entry on MVA. */
1488: /* ??? This is like case 1, but ignores ASID. */
1489: tlb_flush(env, 1);
1490: break;
1.1 root 1491: default:
1492: goto bad_reg;
1493: }
1494: break;
1.1.1.5 root 1495: case 9:
1496: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1.1 root 1497: break;
1.1.1.5 root 1498: switch (crm) {
1499: case 0: /* Cache lockdown. */
1500: switch (op1) {
1501: case 0: /* L1 cache. */
1502: switch (op2) {
1503: case 0:
1504: env->cp15.c9_data = val;
1505: break;
1506: case 1:
1507: env->cp15.c9_insn = val;
1508: break;
1509: default:
1510: goto bad_reg;
1511: }
1512: break;
1513: case 1: /* L2 cache. */
1514: /* Ignore writes to L2 lockdown/auxiliary registers. */
1515: break;
1516: default:
1517: goto bad_reg;
1518: }
1519: break;
1520: case 1: /* TCM memory region registers. */
1521: /* Not implemented. */
1522: goto bad_reg;
1.1 root 1523: default:
1524: goto bad_reg;
1525: }
1526: break;
1527: case 10: /* MMU TLB lockdown. */
1528: /* ??? TLB lockdown not implemented. */
1529: break;
1530: case 12: /* Reserved. */
1531: goto bad_reg;
1532: case 13: /* Process ID. */
1533: switch (op2) {
1534: case 0:
1.1.1.3 root 1535: /* Unlike real hardware the qemu TLB uses virtual addresses,
1536: not modified virtual addresses, so this causes a TLB flush.
1537: */
1538: if (env->cp15.c13_fcse != val)
1539: tlb_flush(env, 1);
1540: env->cp15.c13_fcse = val;
1.1 root 1541: break;
1542: case 1:
1.1.1.3 root 1543: /* This changes the ASID, so do a TLB flush. */
1.1.1.5 root 1544: if (env->cp15.c13_context != val
1545: && !arm_feature(env, ARM_FEATURE_MPU))
1.1.1.3 root 1546: tlb_flush(env, 0);
1547: env->cp15.c13_context = val;
1.1 root 1548: break;
1.1.1.5 root 1549: case 2:
1550: env->cp15.c13_tls1 = val;
1551: break;
1552: case 3:
1553: env->cp15.c13_tls2 = val;
1554: break;
1555: case 4:
1556: env->cp15.c13_tls3 = val;
1557: break;
1.1 root 1558: default:
1559: goto bad_reg;
1560: }
1561: break;
1562: case 14: /* Reserved. */
1563: goto bad_reg;
1564: case 15: /* Implementation specific. */
1.1.1.5 root 1565: if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1566: if (op2 == 0 && crm == 1) {
1567: if (env->cp15.c15_cpar != (val & 0x3fff)) {
1568: /* Changes cp0 to cp13 behavior, so needs a TB flush. */
1569: tb_flush(env);
1570: env->cp15.c15_cpar = val & 0x3fff;
1571: }
1572: break;
1573: }
1574: goto bad_reg;
1575: }
1576: if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
1577: switch (crm) {
1578: case 0:
1579: break;
1580: case 1: /* Set TI925T configuration. */
1581: env->cp15.c15_ticonfig = val & 0xe7;
1582: env->cp15.c0_cpuid = (val & (1 << 5)) ? /* OS_TYPE bit */
1583: ARM_CPUID_TI915T : ARM_CPUID_TI925T;
1584: break;
1585: case 2: /* Set I_max. */
1586: env->cp15.c15_i_max = val;
1587: break;
1588: case 3: /* Set I_min. */
1589: env->cp15.c15_i_min = val;
1590: break;
1591: case 4: /* Set thread-ID. */
1592: env->cp15.c15_threadid = val & 0xffff;
1593: break;
1594: case 8: /* Wait-for-interrupt (deprecated). */
1595: cpu_interrupt(env, CPU_INTERRUPT_HALT);
1596: break;
1597: default:
1598: goto bad_reg;
1599: }
1600: }
1.1 root 1601: break;
1602: }
1603: return;
1604: bad_reg:
1605: /* ??? For debugging only. Should raise illegal instruction exception. */
1.1.1.5 root 1606: cpu_abort(env, "Unimplemented cp15 register write (c%d, c%d, {%d, %d})\n",
1607: (insn >> 16) & 0xf, crm, op1, op2);
1.1 root 1608: }
1609:
1.1.1.6 root 1610: uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
1.1 root 1611: {
1.1.1.5 root 1612: int op1;
1613: int op2;
1614: int crm;
1.1 root 1615:
1.1.1.5 root 1616: op1 = (insn >> 21) & 7;
1.1 root 1617: op2 = (insn >> 5) & 7;
1.1.1.5 root 1618: crm = insn & 0xf;
1.1 root 1619: switch ((insn >> 16) & 0xf) {
1620: case 0: /* ID codes. */
1.1.1.5 root 1621: switch (op1) {
1622: case 0:
1623: switch (crm) {
1624: case 0:
1625: switch (op2) {
1626: case 0: /* Device ID. */
1627: return env->cp15.c0_cpuid;
1628: case 1: /* Cache Type. */
1629: return env->cp15.c0_cachetype;
1630: case 2: /* TCM status. */
1631: return 0;
1632: case 3: /* TLB type register. */
1633: return 0; /* No lockable TLB entries. */
1634: case 5: /* CPU ID */
1635: return env->cpu_index;
1636: default:
1637: goto bad_reg;
1638: }
1639: case 1:
1640: if (!arm_feature(env, ARM_FEATURE_V6))
1641: goto bad_reg;
1642: return env->cp15.c0_c1[op2];
1643: case 2:
1644: if (!arm_feature(env, ARM_FEATURE_V6))
1645: goto bad_reg;
1646: return env->cp15.c0_c2[op2];
1647: case 3: case 4: case 5: case 6: case 7:
1648: return 0;
1649: default:
1650: goto bad_reg;
1651: }
1652: case 1:
1653: /* These registers aren't documented on arm11 cores. However
1654: Linux looks at them anyway. */
1655: if (!arm_feature(env, ARM_FEATURE_V6))
1656: goto bad_reg;
1657: if (crm != 0)
1658: goto bad_reg;
1.1.1.6 root 1659: if (!arm_feature(env, ARM_FEATURE_V7))
1660: return 0;
1661:
1662: switch (op2) {
1663: case 0:
1664: return env->cp15.c0_ccsid[env->cp15.c0_cssel];
1665: case 1:
1666: return env->cp15.c0_clid;
1667: case 7:
1668: return 0;
1669: }
1670: goto bad_reg;
1671: case 2:
1672: if (op2 != 0 || crm != 0)
1.1.1.5 root 1673: goto bad_reg;
1.1.1.6 root 1674: return env->cp15.c0_cssel;
1.1.1.5 root 1675: default:
1676: goto bad_reg;
1.1 root 1677: }
1678: case 1: /* System configuration. */
1.1.1.5 root 1679: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1680: op2 = 0;
1.1 root 1681: switch (op2) {
1682: case 0: /* Control register. */
1683: return env->cp15.c1_sys;
1684: case 1: /* Auxiliary control register. */
1.1.1.5 root 1685: if (arm_feature(env, ARM_FEATURE_XSCALE))
1686: return env->cp15.c1_xscaleauxcr;
1687: if (!arm_feature(env, ARM_FEATURE_AUXCR))
1688: goto bad_reg;
1689: switch (ARM_CPUID(env)) {
1690: case ARM_CPUID_ARM1026:
1.1.1.2 root 1691: return 1;
1.1.1.5 root 1692: case ARM_CPUID_ARM1136:
1.1.1.6 root 1693: case ARM_CPUID_ARM1136_R2:
1.1.1.5 root 1694: return 7;
1695: case ARM_CPUID_ARM11MPCORE:
1696: return 1;
1697: case ARM_CPUID_CORTEXA8:
1.1.1.7 ! root 1698: return 2;
1.1.1.5 root 1699: default:
1700: goto bad_reg;
1701: }
1.1 root 1702: case 2: /* Coprocessor access register. */
1.1.1.5 root 1703: if (arm_feature(env, ARM_FEATURE_XSCALE))
1704: goto bad_reg;
1.1 root 1705: return env->cp15.c1_coproc;
1706: default:
1707: goto bad_reg;
1708: }
1.1.1.5 root 1709: case 2: /* MMU Page table control / MPU cache control. */
1710: if (arm_feature(env, ARM_FEATURE_MPU)) {
1711: switch (op2) {
1712: case 0:
1713: return env->cp15.c2_data;
1714: break;
1715: case 1:
1716: return env->cp15.c2_insn;
1717: break;
1718: default:
1719: goto bad_reg;
1720: }
1721: } else {
1722: switch (op2) {
1723: case 0:
1724: return env->cp15.c2_base0;
1725: case 1:
1726: return env->cp15.c2_base1;
1727: case 2:
1.1.1.6 root 1728: return env->cp15.c2_control;
1.1.1.5 root 1729: default:
1730: goto bad_reg;
1731: }
1732: }
1733: case 3: /* MMU Domain access control / MPU write buffer control. */
1.1 root 1734: return env->cp15.c3;
1735: case 4: /* Reserved. */
1736: goto bad_reg;
1.1.1.5 root 1737: case 5: /* MMU Fault status / MPU access permission. */
1738: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1739: op2 = 0;
1.1 root 1740: switch (op2) {
1741: case 0:
1.1.1.5 root 1742: if (arm_feature(env, ARM_FEATURE_MPU))
1743: return simple_mpu_ap_bits(env->cp15.c5_data);
1.1 root 1744: return env->cp15.c5_data;
1745: case 1:
1.1.1.5 root 1746: if (arm_feature(env, ARM_FEATURE_MPU))
1747: return simple_mpu_ap_bits(env->cp15.c5_data);
1748: return env->cp15.c5_insn;
1749: case 2:
1750: if (!arm_feature(env, ARM_FEATURE_MPU))
1751: goto bad_reg;
1752: return env->cp15.c5_data;
1753: case 3:
1754: if (!arm_feature(env, ARM_FEATURE_MPU))
1755: goto bad_reg;
1.1 root 1756: return env->cp15.c5_insn;
1757: default:
1758: goto bad_reg;
1759: }
1760: case 6: /* MMU Fault address. */
1.1.1.5 root 1761: if (arm_feature(env, ARM_FEATURE_MPU)) {
1762: if (crm >= 8)
1763: goto bad_reg;
1764: return env->cp15.c6_region[crm];
1765: } else {
1766: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1767: op2 = 0;
1768: switch (op2) {
1769: case 0:
1770: return env->cp15.c6_data;
1771: case 1:
1772: if (arm_feature(env, ARM_FEATURE_V6)) {
1773: /* Watchpoint Fault Adrress. */
1774: return 0; /* Not implemented. */
1775: } else {
1776: /* Instruction Fault Adrress. */
1777: /* Arm9 doesn't have an IFAR, but implementing it anyway
1778: shouldn't do any harm. */
1779: return env->cp15.c6_insn;
1780: }
1781: case 2:
1782: if (arm_feature(env, ARM_FEATURE_V6)) {
1783: /* Instruction Fault Adrress. */
1784: return env->cp15.c6_insn;
1785: } else {
1786: goto bad_reg;
1787: }
1788: default:
1789: goto bad_reg;
1790: }
1.1 root 1791: }
1792: case 7: /* Cache control. */
1.1.1.6 root 1793: /* FIXME: Should only clear Z flag if destination is r15. */
1794: env->ZF = 0;
1.1 root 1795: return 0;
1796: case 8: /* MMU TLB control. */
1797: goto bad_reg;
1798: case 9: /* Cache lockdown. */
1.1.1.5 root 1799: switch (op1) {
1800: case 0: /* L1 cache. */
1801: if (arm_feature(env, ARM_FEATURE_OMAPCP))
1802: return 0;
1803: switch (op2) {
1804: case 0:
1805: return env->cp15.c9_data;
1806: case 1:
1807: return env->cp15.c9_insn;
1808: default:
1809: goto bad_reg;
1810: }
1811: case 1: /* L2 cache */
1812: if (crm != 0)
1813: goto bad_reg;
1814: /* L2 Lockdown and Auxiliary control. */
1815: return 0;
1.1 root 1816: default:
1817: goto bad_reg;
1818: }
1819: case 10: /* MMU TLB lockdown. */
1820: /* ??? TLB lockdown not implemented. */
1821: return 0;
1822: case 11: /* TCM DMA control. */
1823: case 12: /* Reserved. */
1824: goto bad_reg;
1825: case 13: /* Process ID. */
1826: switch (op2) {
1827: case 0:
1828: return env->cp15.c13_fcse;
1829: case 1:
1830: return env->cp15.c13_context;
1.1.1.5 root 1831: case 2:
1832: return env->cp15.c13_tls1;
1833: case 3:
1834: return env->cp15.c13_tls2;
1835: case 4:
1836: return env->cp15.c13_tls3;
1.1 root 1837: default:
1838: goto bad_reg;
1839: }
1840: case 14: /* Reserved. */
1841: goto bad_reg;
1842: case 15: /* Implementation specific. */
1.1.1.5 root 1843: if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1844: if (op2 == 0 && crm == 1)
1845: return env->cp15.c15_cpar;
1846:
1847: goto bad_reg;
1848: }
1849: if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
1850: switch (crm) {
1851: case 0:
1852: return 0;
1853: case 1: /* Read TI925T configuration. */
1854: return env->cp15.c15_ticonfig;
1855: case 2: /* Read I_max. */
1856: return env->cp15.c15_i_max;
1857: case 3: /* Read I_min. */
1858: return env->cp15.c15_i_min;
1859: case 4: /* Read thread-ID. */
1860: return env->cp15.c15_threadid;
1861: case 8: /* TI925T_status */
1862: return 0;
1863: }
1.1.1.6 root 1864: /* TODO: Peripheral port remap register:
1865: * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt
1866: * controller base address at $rn & ~0xfff and map size of
1867: * 0x200 << ($rn & 0xfff), when MMU is off. */
1.1.1.5 root 1868: goto bad_reg;
1869: }
1.1 root 1870: return 0;
1871: }
1872: bad_reg:
1873: /* ??? For debugging only. Should raise illegal instruction exception. */
1.1.1.5 root 1874: cpu_abort(env, "Unimplemented cp15 register read (c%d, c%d, {%d, %d})\n",
1875: (insn >> 16) & 0xf, crm, op1, op2);
1.1 root 1876: return 0;
1877: }
1878:
1.1.1.6 root 1879: void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
1.1.1.5 root 1880: {
1881: env->banked_r13[bank_number(mode)] = val;
1882: }
1883:
1.1.1.6 root 1884: uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
1.1.1.5 root 1885: {
1886: return env->banked_r13[bank_number(mode)];
1887: }
1888:
1.1.1.6 root 1889: uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
1.1.1.5 root 1890: {
1891: switch (reg) {
1892: case 0: /* APSR */
1893: return xpsr_read(env) & 0xf8000000;
1894: case 1: /* IAPSR */
1895: return xpsr_read(env) & 0xf80001ff;
1896: case 2: /* EAPSR */
1897: return xpsr_read(env) & 0xff00fc00;
1898: case 3: /* xPSR */
1899: return xpsr_read(env) & 0xff00fdff;
1900: case 5: /* IPSR */
1901: return xpsr_read(env) & 0x000001ff;
1902: case 6: /* EPSR */
1903: return xpsr_read(env) & 0x0700fc00;
1904: case 7: /* IEPSR */
1905: return xpsr_read(env) & 0x0700edff;
1906: case 8: /* MSP */
1907: return env->v7m.current_sp ? env->v7m.other_sp : env->regs[13];
1908: case 9: /* PSP */
1909: return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
1910: case 16: /* PRIMASK */
1911: return (env->uncached_cpsr & CPSR_I) != 0;
1912: case 17: /* FAULTMASK */
1913: return (env->uncached_cpsr & CPSR_F) != 0;
1914: case 18: /* BASEPRI */
1915: case 19: /* BASEPRI_MAX */
1916: return env->v7m.basepri;
1917: case 20: /* CONTROL */
1918: return env->v7m.control;
1919: default:
1920: /* ??? For debugging only. */
1921: cpu_abort(env, "Unimplemented system register read (%d)\n", reg);
1922: return 0;
1923: }
1924: }
1925:
1.1.1.6 root 1926: void HELPER(v7m_msr)(CPUState *env, uint32_t reg, uint32_t val)
1.1.1.5 root 1927: {
1928: switch (reg) {
1929: case 0: /* APSR */
1930: xpsr_write(env, val, 0xf8000000);
1931: break;
1932: case 1: /* IAPSR */
1933: xpsr_write(env, val, 0xf8000000);
1934: break;
1935: case 2: /* EAPSR */
1936: xpsr_write(env, val, 0xfe00fc00);
1937: break;
1938: case 3: /* xPSR */
1939: xpsr_write(env, val, 0xfe00fc00);
1940: break;
1941: case 5: /* IPSR */
1942: /* IPSR bits are readonly. */
1943: break;
1944: case 6: /* EPSR */
1945: xpsr_write(env, val, 0x0600fc00);
1946: break;
1947: case 7: /* IEPSR */
1948: xpsr_write(env, val, 0x0600fc00);
1949: break;
1950: case 8: /* MSP */
1951: if (env->v7m.current_sp)
1952: env->v7m.other_sp = val;
1953: else
1954: env->regs[13] = val;
1955: break;
1956: case 9: /* PSP */
1957: if (env->v7m.current_sp)
1958: env->regs[13] = val;
1959: else
1960: env->v7m.other_sp = val;
1961: break;
1962: case 16: /* PRIMASK */
1963: if (val & 1)
1964: env->uncached_cpsr |= CPSR_I;
1965: else
1966: env->uncached_cpsr &= ~CPSR_I;
1967: break;
1968: case 17: /* FAULTMASK */
1969: if (val & 1)
1970: env->uncached_cpsr |= CPSR_F;
1971: else
1972: env->uncached_cpsr &= ~CPSR_F;
1973: break;
1974: case 18: /* BASEPRI */
1975: env->v7m.basepri = val & 0xff;
1976: break;
1977: case 19: /* BASEPRI_MAX */
1978: val &= 0xff;
1979: if (val != 0 && (val < env->v7m.basepri || env->v7m.basepri == 0))
1980: env->v7m.basepri = val;
1981: break;
1982: case 20: /* CONTROL */
1983: env->v7m.control = val & 3;
1984: switch_v7m_sp(env, (val & 2) != 0);
1985: break;
1986: default:
1987: /* ??? For debugging only. */
1988: cpu_abort(env, "Unimplemented system register write (%d)\n", reg);
1989: return;
1990: }
1991: }
1992:
1993: void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
1994: ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
1995: void *opaque)
1996: {
1997: if (cpnum < 0 || cpnum > 14) {
1998: cpu_abort(env, "Bad coprocessor number: %i\n", cpnum);
1999: return;
2000: }
2001:
2002: env->cp[cpnum].cp_read = cp_read;
2003: env->cp[cpnum].cp_write = cp_write;
2004: env->cp[cpnum].opaque = opaque;
2005: }
2006:
1.1 root 2007: #endif
1.1.1.6 root 2008:
2009: /* Note that signed overflow is undefined in C. The following routines are
2010: careful to use unsigned types where modulo arithmetic is required.
2011: Failure to do so _will_ break on newer gcc. */
2012:
2013: /* Signed saturating arithmetic. */
2014:
2015: /* Perform 16-bit signed saturating addition. */
2016: static inline uint16_t add16_sat(uint16_t a, uint16_t b)
2017: {
2018: uint16_t res;
2019:
2020: res = a + b;
2021: if (((res ^ a) & 0x8000) && !((a ^ b) & 0x8000)) {
2022: if (a & 0x8000)
2023: res = 0x8000;
2024: else
2025: res = 0x7fff;
2026: }
2027: return res;
2028: }
2029:
2030: /* Perform 8-bit signed saturating addition. */
2031: static inline uint8_t add8_sat(uint8_t a, uint8_t b)
2032: {
2033: uint8_t res;
2034:
2035: res = a + b;
2036: if (((res ^ a) & 0x80) && !((a ^ b) & 0x80)) {
2037: if (a & 0x80)
2038: res = 0x80;
2039: else
2040: res = 0x7f;
2041: }
2042: return res;
2043: }
2044:
2045: /* Perform 16-bit signed saturating subtraction. */
2046: static inline uint16_t sub16_sat(uint16_t a, uint16_t b)
2047: {
2048: uint16_t res;
2049:
2050: res = a - b;
2051: if (((res ^ a) & 0x8000) && ((a ^ b) & 0x8000)) {
2052: if (a & 0x8000)
2053: res = 0x8000;
2054: else
2055: res = 0x7fff;
2056: }
2057: return res;
2058: }
2059:
2060: /* Perform 8-bit signed saturating subtraction. */
2061: static inline uint8_t sub8_sat(uint8_t a, uint8_t b)
2062: {
2063: uint8_t res;
2064:
2065: res = a - b;
2066: if (((res ^ a) & 0x80) && ((a ^ b) & 0x80)) {
2067: if (a & 0x80)
2068: res = 0x80;
2069: else
2070: res = 0x7f;
2071: }
2072: return res;
2073: }
2074:
2075: #define ADD16(a, b, n) RESULT(add16_sat(a, b), n, 16);
2076: #define SUB16(a, b, n) RESULT(sub16_sat(a, b), n, 16);
2077: #define ADD8(a, b, n) RESULT(add8_sat(a, b), n, 8);
2078: #define SUB8(a, b, n) RESULT(sub8_sat(a, b), n, 8);
2079: #define PFX q
2080:
2081: #include "op_addsub.h"
2082:
2083: /* Unsigned saturating arithmetic. */
2084: static inline uint16_t add16_usat(uint16_t a, uint16_t b)
2085: {
2086: uint16_t res;
2087: res = a + b;
2088: if (res < a)
2089: res = 0xffff;
2090: return res;
2091: }
2092:
2093: static inline uint16_t sub16_usat(uint16_t a, uint16_t b)
2094: {
2095: if (a < b)
2096: return a - b;
2097: else
2098: return 0;
2099: }
2100:
2101: static inline uint8_t add8_usat(uint8_t a, uint8_t b)
2102: {
2103: uint8_t res;
2104: res = a + b;
2105: if (res < a)
2106: res = 0xff;
2107: return res;
2108: }
2109:
2110: static inline uint8_t sub8_usat(uint8_t a, uint8_t b)
2111: {
2112: if (a < b)
2113: return a - b;
2114: else
2115: return 0;
2116: }
2117:
2118: #define ADD16(a, b, n) RESULT(add16_usat(a, b), n, 16);
2119: #define SUB16(a, b, n) RESULT(sub16_usat(a, b), n, 16);
2120: #define ADD8(a, b, n) RESULT(add8_usat(a, b), n, 8);
2121: #define SUB8(a, b, n) RESULT(sub8_usat(a, b), n, 8);
2122: #define PFX uq
2123:
2124: #include "op_addsub.h"
2125:
2126: /* Signed modulo arithmetic. */
2127: #define SARITH16(a, b, n, op) do { \
2128: int32_t sum; \
2129: sum = (int16_t)((uint16_t)(a) op (uint16_t)(b)); \
2130: RESULT(sum, n, 16); \
2131: if (sum >= 0) \
2132: ge |= 3 << (n * 2); \
2133: } while(0)
2134:
2135: #define SARITH8(a, b, n, op) do { \
2136: int32_t sum; \
2137: sum = (int8_t)((uint8_t)(a) op (uint8_t)(b)); \
2138: RESULT(sum, n, 8); \
2139: if (sum >= 0) \
2140: ge |= 1 << n; \
2141: } while(0)
2142:
2143:
2144: #define ADD16(a, b, n) SARITH16(a, b, n, +)
2145: #define SUB16(a, b, n) SARITH16(a, b, n, -)
2146: #define ADD8(a, b, n) SARITH8(a, b, n, +)
2147: #define SUB8(a, b, n) SARITH8(a, b, n, -)
2148: #define PFX s
2149: #define ARITH_GE
2150:
2151: #include "op_addsub.h"
2152:
2153: /* Unsigned modulo arithmetic. */
2154: #define ADD16(a, b, n) do { \
2155: uint32_t sum; \
2156: sum = (uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b); \
2157: RESULT(sum, n, 16); \
2158: if ((sum >> 16) == 1) \
2159: ge |= 3 << (n * 2); \
2160: } while(0)
2161:
2162: #define ADD8(a, b, n) do { \
2163: uint32_t sum; \
2164: sum = (uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b); \
2165: RESULT(sum, n, 8); \
2166: if ((sum >> 8) == 1) \
2167: ge |= 1 << n; \
2168: } while(0)
2169:
2170: #define SUB16(a, b, n) do { \
2171: uint32_t sum; \
2172: sum = (uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b); \
2173: RESULT(sum, n, 16); \
2174: if ((sum >> 16) == 0) \
2175: ge |= 3 << (n * 2); \
2176: } while(0)
2177:
2178: #define SUB8(a, b, n) do { \
2179: uint32_t sum; \
2180: sum = (uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b); \
2181: RESULT(sum, n, 8); \
2182: if ((sum >> 8) == 0) \
2183: ge |= 1 << n; \
2184: } while(0)
2185:
2186: #define PFX u
2187: #define ARITH_GE
2188:
2189: #include "op_addsub.h"
2190:
2191: /* Halved signed arithmetic. */
2192: #define ADD16(a, b, n) \
2193: RESULT(((int32_t)(int16_t)(a) + (int32_t)(int16_t)(b)) >> 1, n, 16)
2194: #define SUB16(a, b, n) \
2195: RESULT(((int32_t)(int16_t)(a) - (int32_t)(int16_t)(b)) >> 1, n, 16)
2196: #define ADD8(a, b, n) \
2197: RESULT(((int32_t)(int8_t)(a) + (int32_t)(int8_t)(b)) >> 1, n, 8)
2198: #define SUB8(a, b, n) \
2199: RESULT(((int32_t)(int8_t)(a) - (int32_t)(int8_t)(b)) >> 1, n, 8)
2200: #define PFX sh
2201:
2202: #include "op_addsub.h"
2203:
2204: /* Halved unsigned arithmetic. */
2205: #define ADD16(a, b, n) \
2206: RESULT(((uint32_t)(uint16_t)(a) + (uint32_t)(uint16_t)(b)) >> 1, n, 16)
2207: #define SUB16(a, b, n) \
2208: RESULT(((uint32_t)(uint16_t)(a) - (uint32_t)(uint16_t)(b)) >> 1, n, 16)
2209: #define ADD8(a, b, n) \
2210: RESULT(((uint32_t)(uint8_t)(a) + (uint32_t)(uint8_t)(b)) >> 1, n, 8)
2211: #define SUB8(a, b, n) \
2212: RESULT(((uint32_t)(uint8_t)(a) - (uint32_t)(uint8_t)(b)) >> 1, n, 8)
2213: #define PFX uh
2214:
2215: #include "op_addsub.h"
2216:
2217: static inline uint8_t do_usad(uint8_t a, uint8_t b)
2218: {
2219: if (a > b)
2220: return a - b;
2221: else
2222: return b - a;
2223: }
2224:
2225: /* Unsigned sum of absolute byte differences. */
2226: uint32_t HELPER(usad8)(uint32_t a, uint32_t b)
2227: {
2228: uint32_t sum;
2229: sum = do_usad(a, b);
2230: sum += do_usad(a >> 8, b >> 8);
2231: sum += do_usad(a >> 16, b >>16);
2232: sum += do_usad(a >> 24, b >> 24);
2233: return sum;
2234: }
2235:
2236: /* For ARMv6 SEL instruction. */
2237: uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b)
2238: {
2239: uint32_t mask;
2240:
2241: mask = 0;
2242: if (flags & 1)
2243: mask |= 0xff;
2244: if (flags & 2)
2245: mask |= 0xff00;
2246: if (flags & 4)
2247: mask |= 0xff0000;
2248: if (flags & 8)
2249: mask |= 0xff000000;
2250: return (a & mask) | (b & ~mask);
2251: }
2252:
2253: uint32_t HELPER(logicq_cc)(uint64_t val)
2254: {
2255: return (val >> 32) | (val != 0);
2256: }
2257:
2258: /* VFP support. We follow the convention used for VFP instrunctions:
2259: Single precition routines have a "s" suffix, double precision a
2260: "d" suffix. */
2261:
2262: /* Convert host exception flags to vfp form. */
2263: static inline int vfp_exceptbits_from_host(int host_bits)
2264: {
2265: int target_bits = 0;
2266:
2267: if (host_bits & float_flag_invalid)
2268: target_bits |= 1;
2269: if (host_bits & float_flag_divbyzero)
2270: target_bits |= 2;
2271: if (host_bits & float_flag_overflow)
2272: target_bits |= 4;
2273: if (host_bits & float_flag_underflow)
2274: target_bits |= 8;
2275: if (host_bits & float_flag_inexact)
2276: target_bits |= 0x10;
2277: return target_bits;
2278: }
2279:
2280: uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
2281: {
2282: int i;
2283: uint32_t fpscr;
2284:
2285: fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff)
2286: | (env->vfp.vec_len << 16)
2287: | (env->vfp.vec_stride << 20);
2288: i = get_float_exception_flags(&env->vfp.fp_status);
2289: fpscr |= vfp_exceptbits_from_host(i);
2290: return fpscr;
2291: }
2292:
2293: /* Convert vfp exception flags to target form. */
2294: static inline int vfp_exceptbits_to_host(int target_bits)
2295: {
2296: int host_bits = 0;
2297:
2298: if (target_bits & 1)
2299: host_bits |= float_flag_invalid;
2300: if (target_bits & 2)
2301: host_bits |= float_flag_divbyzero;
2302: if (target_bits & 4)
2303: host_bits |= float_flag_overflow;
2304: if (target_bits & 8)
2305: host_bits |= float_flag_underflow;
2306: if (target_bits & 0x10)
2307: host_bits |= float_flag_inexact;
2308: return host_bits;
2309: }
2310:
2311: void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
2312: {
2313: int i;
2314: uint32_t changed;
2315:
2316: changed = env->vfp.xregs[ARM_VFP_FPSCR];
2317: env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff);
2318: env->vfp.vec_len = (val >> 16) & 7;
2319: env->vfp.vec_stride = (val >> 20) & 3;
2320:
2321: changed ^= val;
2322: if (changed & (3 << 22)) {
2323: i = (val >> 22) & 3;
2324: switch (i) {
2325: case 0:
2326: i = float_round_nearest_even;
2327: break;
2328: case 1:
2329: i = float_round_up;
2330: break;
2331: case 2:
2332: i = float_round_down;
2333: break;
2334: case 3:
2335: i = float_round_to_zero;
2336: break;
2337: }
2338: set_float_rounding_mode(i, &env->vfp.fp_status);
2339: }
2340: if (changed & (1 << 24))
2341: set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
2342: if (changed & (1 << 25))
2343: set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
2344:
2345: i = vfp_exceptbits_to_host((val >> 8) & 0x1f);
2346: set_float_exception_flags(i, &env->vfp.fp_status);
2347: }
2348:
2349: #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
2350:
2351: #define VFP_BINOP(name) \
2352: float32 VFP_HELPER(name, s)(float32 a, float32 b, CPUState *env) \
2353: { \
2354: return float32_ ## name (a, b, &env->vfp.fp_status); \
2355: } \
2356: float64 VFP_HELPER(name, d)(float64 a, float64 b, CPUState *env) \
2357: { \
2358: return float64_ ## name (a, b, &env->vfp.fp_status); \
2359: }
2360: VFP_BINOP(add)
2361: VFP_BINOP(sub)
2362: VFP_BINOP(mul)
2363: VFP_BINOP(div)
2364: #undef VFP_BINOP
2365:
2366: float32 VFP_HELPER(neg, s)(float32 a)
2367: {
2368: return float32_chs(a);
2369: }
2370:
2371: float64 VFP_HELPER(neg, d)(float64 a)
2372: {
2373: return float64_chs(a);
2374: }
2375:
2376: float32 VFP_HELPER(abs, s)(float32 a)
2377: {
2378: return float32_abs(a);
2379: }
2380:
2381: float64 VFP_HELPER(abs, d)(float64 a)
2382: {
2383: return float64_abs(a);
2384: }
2385:
2386: float32 VFP_HELPER(sqrt, s)(float32 a, CPUState *env)
2387: {
2388: return float32_sqrt(a, &env->vfp.fp_status);
2389: }
2390:
2391: float64 VFP_HELPER(sqrt, d)(float64 a, CPUState *env)
2392: {
2393: return float64_sqrt(a, &env->vfp.fp_status);
2394: }
2395:
2396: /* XXX: check quiet/signaling case */
2397: #define DO_VFP_cmp(p, type) \
2398: void VFP_HELPER(cmp, p)(type a, type b, CPUState *env) \
2399: { \
2400: uint32_t flags; \
2401: switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \
2402: case 0: flags = 0x6; break; \
2403: case -1: flags = 0x8; break; \
2404: case 1: flags = 0x2; break; \
2405: default: case 2: flags = 0x3; break; \
2406: } \
2407: env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
2408: | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
2409: } \
2410: void VFP_HELPER(cmpe, p)(type a, type b, CPUState *env) \
2411: { \
2412: uint32_t flags; \
2413: switch(type ## _compare(a, b, &env->vfp.fp_status)) { \
2414: case 0: flags = 0x6; break; \
2415: case -1: flags = 0x8; break; \
2416: case 1: flags = 0x2; break; \
2417: default: case 2: flags = 0x3; break; \
2418: } \
2419: env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \
2420: | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
2421: }
2422: DO_VFP_cmp(s, float32)
2423: DO_VFP_cmp(d, float64)
2424: #undef DO_VFP_cmp
2425:
2426: /* Helper routines to perform bitwise copies between float and int. */
2427: static inline float32 vfp_itos(uint32_t i)
2428: {
2429: union {
2430: uint32_t i;
2431: float32 s;
2432: } v;
2433:
2434: v.i = i;
2435: return v.s;
2436: }
2437:
2438: static inline uint32_t vfp_stoi(float32 s)
2439: {
2440: union {
2441: uint32_t i;
2442: float32 s;
2443: } v;
2444:
2445: v.s = s;
2446: return v.i;
2447: }
2448:
2449: static inline float64 vfp_itod(uint64_t i)
2450: {
2451: union {
2452: uint64_t i;
2453: float64 d;
2454: } v;
2455:
2456: v.i = i;
2457: return v.d;
2458: }
2459:
2460: static inline uint64_t vfp_dtoi(float64 d)
2461: {
2462: union {
2463: uint64_t i;
2464: float64 d;
2465: } v;
2466:
2467: v.d = d;
2468: return v.i;
2469: }
2470:
2471: /* Integer to float conversion. */
2472: float32 VFP_HELPER(uito, s)(float32 x, CPUState *env)
2473: {
2474: return uint32_to_float32(vfp_stoi(x), &env->vfp.fp_status);
2475: }
2476:
2477: float64 VFP_HELPER(uito, d)(float32 x, CPUState *env)
2478: {
2479: return uint32_to_float64(vfp_stoi(x), &env->vfp.fp_status);
2480: }
2481:
2482: float32 VFP_HELPER(sito, s)(float32 x, CPUState *env)
2483: {
2484: return int32_to_float32(vfp_stoi(x), &env->vfp.fp_status);
2485: }
2486:
2487: float64 VFP_HELPER(sito, d)(float32 x, CPUState *env)
2488: {
2489: return int32_to_float64(vfp_stoi(x), &env->vfp.fp_status);
2490: }
2491:
2492: /* Float to integer conversion. */
2493: float32 VFP_HELPER(toui, s)(float32 x, CPUState *env)
2494: {
2495: return vfp_itos(float32_to_uint32(x, &env->vfp.fp_status));
2496: }
2497:
2498: float32 VFP_HELPER(toui, d)(float64 x, CPUState *env)
2499: {
2500: return vfp_itos(float64_to_uint32(x, &env->vfp.fp_status));
2501: }
2502:
2503: float32 VFP_HELPER(tosi, s)(float32 x, CPUState *env)
2504: {
2505: return vfp_itos(float32_to_int32(x, &env->vfp.fp_status));
2506: }
2507:
2508: float32 VFP_HELPER(tosi, d)(float64 x, CPUState *env)
2509: {
2510: return vfp_itos(float64_to_int32(x, &env->vfp.fp_status));
2511: }
2512:
2513: float32 VFP_HELPER(touiz, s)(float32 x, CPUState *env)
2514: {
2515: return vfp_itos(float32_to_uint32_round_to_zero(x, &env->vfp.fp_status));
2516: }
2517:
2518: float32 VFP_HELPER(touiz, d)(float64 x, CPUState *env)
2519: {
2520: return vfp_itos(float64_to_uint32_round_to_zero(x, &env->vfp.fp_status));
2521: }
2522:
2523: float32 VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
2524: {
2525: return vfp_itos(float32_to_int32_round_to_zero(x, &env->vfp.fp_status));
2526: }
2527:
2528: float32 VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
2529: {
2530: return vfp_itos(float64_to_int32_round_to_zero(x, &env->vfp.fp_status));
2531: }
2532:
2533: /* floating point conversion */
2534: float64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env)
2535: {
2536: return float32_to_float64(x, &env->vfp.fp_status);
2537: }
2538:
2539: float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
2540: {
2541: return float64_to_float32(x, &env->vfp.fp_status);
2542: }
2543:
2544: /* VFP3 fixed point conversion. */
2545: #define VFP_CONV_FIX(name, p, ftype, itype, sign) \
2546: ftype VFP_HELPER(name##to, p)(ftype x, uint32_t shift, CPUState *env) \
2547: { \
2548: ftype tmp; \
2549: tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(x), \
2550: &env->vfp.fp_status); \
2551: return ftype##_scalbn(tmp, -(int)shift, &env->vfp.fp_status); \
2552: } \
2553: ftype VFP_HELPER(to##name, p)(ftype x, uint32_t shift, CPUState *env) \
2554: { \
2555: ftype tmp; \
2556: tmp = ftype##_scalbn(x, shift, &env->vfp.fp_status); \
2557: return vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \
2558: &env->vfp.fp_status)); \
2559: }
2560:
2561: VFP_CONV_FIX(sh, d, float64, int16, )
2562: VFP_CONV_FIX(sl, d, float64, int32, )
2563: VFP_CONV_FIX(uh, d, float64, uint16, u)
2564: VFP_CONV_FIX(ul, d, float64, uint32, u)
2565: VFP_CONV_FIX(sh, s, float32, int16, )
2566: VFP_CONV_FIX(sl, s, float32, int32, )
2567: VFP_CONV_FIX(uh, s, float32, uint16, u)
2568: VFP_CONV_FIX(ul, s, float32, uint32, u)
2569: #undef VFP_CONV_FIX
2570:
2571: float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
2572: {
2573: float_status *s = &env->vfp.fp_status;
2574: float32 two = int32_to_float32(2, s);
2575: return float32_sub(two, float32_mul(a, b, s), s);
2576: }
2577:
2578: float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
2579: {
2580: float_status *s = &env->vfp.fp_status;
2581: float32 three = int32_to_float32(3, s);
2582: return float32_sub(three, float32_mul(a, b, s), s);
2583: }
2584:
2585: /* NEON helpers. */
2586:
2587: /* TODO: The architecture specifies the value that the estimate functions
2588: should return. We return the exact reciprocal/root instead. */
2589: float32 HELPER(recpe_f32)(float32 a, CPUState *env)
2590: {
2591: float_status *s = &env->vfp.fp_status;
2592: float32 one = int32_to_float32(1, s);
2593: return float32_div(one, a, s);
2594: }
2595:
2596: float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)
2597: {
2598: float_status *s = &env->vfp.fp_status;
2599: float32 one = int32_to_float32(1, s);
2600: return float32_div(one, float32_sqrt(a, s), s);
2601: }
2602:
2603: uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env)
2604: {
2605: float_status *s = &env->vfp.fp_status;
2606: float32 tmp;
2607: tmp = int32_to_float32(a, s);
2608: tmp = float32_scalbn(tmp, -32, s);
2609: tmp = helper_recpe_f32(tmp, env);
2610: tmp = float32_scalbn(tmp, 31, s);
2611: return float32_to_int32(tmp, s);
2612: }
2613:
2614: uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env)
2615: {
2616: float_status *s = &env->vfp.fp_status;
2617: float32 tmp;
2618: tmp = int32_to_float32(a, s);
2619: tmp = float32_scalbn(tmp, -32, s);
2620: tmp = helper_rsqrte_f32(tmp, env);
2621: tmp = float32_scalbn(tmp, 31, s);
2622: return float32_to_int32(tmp, s);
2623: }
2624:
2625: void HELPER(set_teecr)(CPUState *env, uint32_t val)
2626: {
2627: val &= 1;
2628: if (env->teecr != val) {
2629: env->teecr = val;
2630: tb_flush(env);
2631: }
2632: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.