Commit 5898e816840dd7cb2492c4cce85525e7383f8def
1 parent
394411ac
ARM emulation support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@232 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
1586 additions
and
0 deletions
cpu-arm.h
0 → 100644
| 1 | +/* | |
| 2 | + * ARM virtual CPU header | |
| 3 | + * | |
| 4 | + * Copyright (c) 2003 Fabrice Bellard | |
| 5 | + * | |
| 6 | + * This library is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU Lesser General Public | |
| 8 | + * License as published by the Free Software Foundation; either | |
| 9 | + * version 2 of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This library is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | + * Lesser General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public | |
| 17 | + * License along with this library; if not, write to the Free Software | |
| 18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | + */ | |
| 20 | +#ifndef CPU_ARM_H | |
| 21 | +#define CPU_ARM_H | |
| 22 | + | |
| 23 | +#include "config.h" | |
| 24 | +#include <setjmp.h> | |
| 25 | + | |
| 26 | +#define EXCP_UDEF 1 /* undefined instruction */ | |
| 27 | +#define EXCP_SWI 2 /* software interrupt */ | |
| 28 | +#define EXCP_INTERRUPT 256 /* async interruption */ | |
| 29 | + | |
| 30 | +typedef struct CPUARMState { | |
| 31 | + uint32_t regs[16]; | |
| 32 | + uint32_t cpsr; | |
| 33 | + | |
| 34 | + /* cpsr flag cache for faster execution */ | |
| 35 | + uint32_t CF; /* 0 or 1 */ | |
| 36 | + uint32_t VF; /* V is the bit 31. All other bits are undefined */ | |
| 37 | + uint32_t NZF; /* N is bit 31. Z is computed from NZF */ | |
| 38 | + | |
| 39 | + /* exception/interrupt handling */ | |
| 40 | + jmp_buf jmp_env; | |
| 41 | + int exception_index; | |
| 42 | + int interrupt_request; | |
| 43 | + | |
| 44 | + /* user data */ | |
| 45 | + void *opaque; | |
| 46 | +} CPUARMState; | |
| 47 | + | |
| 48 | +CPUARMState *cpu_arm_init(void); | |
| 49 | +int cpu_arm_exec(CPUARMState *s); | |
| 50 | +void cpu_arm_interrupt(CPUARMState *s); | |
| 51 | +void cpu_arm_close(CPUARMState *s); | |
| 52 | +/* you can call this signal handler from your SIGBUS and SIGSEGV | |
| 53 | + signal handlers to inform the virtual CPU of exceptions. non zero | |
| 54 | + is returned if the signal was handled by the virtual CPU. */ | |
| 55 | +struct siginfo; | |
| 56 | +int cpu_arm_signal_handler(int host_signum, struct siginfo *info, | |
| 57 | + void *puc); | |
| 58 | + | |
| 59 | +void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags); | |
| 60 | + | |
| 61 | +#define TARGET_PAGE_BITS 12 | |
| 62 | +#include "cpu-all.h" | |
| 63 | + | |
| 64 | +#endif | ... | ... |
exec-arm.h
0 → 100644
| 1 | +/* | |
| 2 | + * ARM execution defines | |
| 3 | + * | |
| 4 | + * Copyright (c) 2003 Fabrice Bellard | |
| 5 | + * | |
| 6 | + * This library is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU Lesser General Public | |
| 8 | + * License as published by the Free Software Foundation; either | |
| 9 | + * version 2 of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This library is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | + * Lesser General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public | |
| 17 | + * License along with this library; if not, write to the Free Software | |
| 18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | + */ | |
| 20 | +#include "dyngen-exec.h" | |
| 21 | + | |
| 22 | +register struct CPUARMState *env asm(AREG0); | |
| 23 | +register uint32_t T0 asm(AREG1); | |
| 24 | +register uint32_t T1 asm(AREG2); | |
| 25 | +register uint32_t T2 asm(AREG3); | |
| 26 | + | |
| 27 | +#include "cpu-arm.h" | |
| 28 | +#include "exec.h" | |
| 29 | + | |
| 30 | +void cpu_lock(void); | |
| 31 | +void cpu_unlock(void); | |
| 32 | +void cpu_loop_exit(void); | ... | ... |
op-arm-template.h
0 → 100644
| 1 | +/* | |
| 2 | + * ARM micro operations (templates for various register related | |
| 3 | + * operations) | |
| 4 | + * | |
| 5 | + * Copyright (c) 2003 Fabrice Bellard | |
| 6 | + * | |
| 7 | + * This library is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * This library is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with this library; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 20 | + */ | |
| 21 | + | |
| 22 | +void OPPROTO glue(op_movl_T0_, REGNAME)(void) | |
| 23 | +{ | |
| 24 | + T0 = REG; | |
| 25 | +} | |
| 26 | + | |
| 27 | +void OPPROTO glue(op_movl_T1_, REGNAME)(void) | |
| 28 | +{ | |
| 29 | + T1 = REG; | |
| 30 | +} | |
| 31 | + | |
| 32 | +void OPPROTO glue(op_movl_T2_, REGNAME)(void) | |
| 33 | +{ | |
| 34 | + T2 = REG; | |
| 35 | +} | |
| 36 | + | |
| 37 | +void OPPROTO glue(glue(op_movl_, REGNAME), _T0)(void) | |
| 38 | +{ | |
| 39 | + REG = T0; | |
| 40 | +} | |
| 41 | + | |
| 42 | +void OPPROTO glue(glue(op_movl_, REGNAME), _T1)(void) | |
| 43 | +{ | |
| 44 | + REG = T1; | |
| 45 | +} | |
| 46 | + | |
| 47 | +#undef REG | |
| 48 | +#undef REGNAME | ... | ... |
op-arm.c
0 → 100644
| 1 | +/* | |
| 2 | + * ARM micro operations | |
| 3 | + * | |
| 4 | + * Copyright (c) 2003 Fabrice Bellard | |
| 5 | + * | |
| 6 | + * This library is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU Lesser General Public | |
| 8 | + * License as published by the Free Software Foundation; either | |
| 9 | + * version 2 of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This library is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | + * Lesser General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public | |
| 17 | + * License along with this library; if not, write to the Free Software | |
| 18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | + */ | |
| 20 | +#include "exec-arm.h" | |
| 21 | + | |
| 22 | +#define REGNAME r0 | |
| 23 | +#define REG (env->regs[0]) | |
| 24 | +#include "op-arm-template.h" | |
| 25 | + | |
| 26 | +#define REGNAME r1 | |
| 27 | +#define REG (env->regs[1]) | |
| 28 | +#include "op-arm-template.h" | |
| 29 | + | |
| 30 | +#define REGNAME r2 | |
| 31 | +#define REG (env->regs[2]) | |
| 32 | +#include "op-arm-template.h" | |
| 33 | + | |
| 34 | +#define REGNAME r3 | |
| 35 | +#define REG (env->regs[3]) | |
| 36 | +#include "op-arm-template.h" | |
| 37 | + | |
| 38 | +#define REGNAME r4 | |
| 39 | +#define REG (env->regs[4]) | |
| 40 | +#include "op-arm-template.h" | |
| 41 | + | |
| 42 | +#define REGNAME r5 | |
| 43 | +#define REG (env->regs[5]) | |
| 44 | +#include "op-arm-template.h" | |
| 45 | + | |
| 46 | +#define REGNAME r6 | |
| 47 | +#define REG (env->regs[6]) | |
| 48 | +#include "op-arm-template.h" | |
| 49 | + | |
| 50 | +#define REGNAME r7 | |
| 51 | +#define REG (env->regs[7]) | |
| 52 | +#include "op-arm-template.h" | |
| 53 | + | |
| 54 | +#define REGNAME r8 | |
| 55 | +#define REG (env->regs[8]) | |
| 56 | +#include "op-arm-template.h" | |
| 57 | + | |
| 58 | +#define REGNAME r9 | |
| 59 | +#define REG (env->regs[9]) | |
| 60 | +#include "op-arm-template.h" | |
| 61 | + | |
| 62 | +#define REGNAME r10 | |
| 63 | +#define REG (env->regs[10]) | |
| 64 | +#include "op-arm-template.h" | |
| 65 | + | |
| 66 | +#define REGNAME r11 | |
| 67 | +#define REG (env->regs[11]) | |
| 68 | +#include "op-arm-template.h" | |
| 69 | + | |
| 70 | +#define REGNAME r12 | |
| 71 | +#define REG (env->regs[12]) | |
| 72 | +#include "op-arm-template.h" | |
| 73 | + | |
| 74 | +#define REGNAME r13 | |
| 75 | +#define REG (env->regs[13]) | |
| 76 | +#include "op-arm-template.h" | |
| 77 | + | |
| 78 | +#define REGNAME r14 | |
| 79 | +#define REG (env->regs[14]) | |
| 80 | +#include "op-arm-template.h" | |
| 81 | + | |
| 82 | +#define REGNAME r15 | |
| 83 | +#define REG (env->regs[15]) | |
| 84 | +#include "op-arm-template.h" | |
| 85 | + | |
| 86 | +void OPPROTO op_movl_T0_0(void) | |
| 87 | +{ | |
| 88 | + T0 = 0; | |
| 89 | +} | |
| 90 | + | |
| 91 | +void OPPROTO op_movl_T0_im(void) | |
| 92 | +{ | |
| 93 | + T0 = PARAM1; | |
| 94 | +} | |
| 95 | + | |
| 96 | +void OPPROTO op_movl_T1_im(void) | |
| 97 | +{ | |
| 98 | + T1 = PARAM1; | |
| 99 | +} | |
| 100 | + | |
| 101 | +void OPPROTO op_movl_T2_im(void) | |
| 102 | +{ | |
| 103 | + T2 = PARAM1; | |
| 104 | +} | |
| 105 | + | |
| 106 | +void OPPROTO op_addl_T1_im(void) | |
| 107 | +{ | |
| 108 | + T1 += PARAM1; | |
| 109 | +} | |
| 110 | + | |
| 111 | +void OPPROTO op_addl_T1_T2(void) | |
| 112 | +{ | |
| 113 | + T1 += T2; | |
| 114 | +} | |
| 115 | + | |
| 116 | +void OPPROTO op_subl_T1_T2(void) | |
| 117 | +{ | |
| 118 | + T1 -= T2; | |
| 119 | +} | |
| 120 | + | |
| 121 | +void OPPROTO op_addl_T0_T1(void) | |
| 122 | +{ | |
| 123 | + T0 += T1; | |
| 124 | +} | |
| 125 | + | |
| 126 | +void OPPROTO op_addl_T0_T1_cc(void) | |
| 127 | +{ | |
| 128 | + unsigned int src1; | |
| 129 | + src1 = T0; | |
| 130 | + T0 += T1; | |
| 131 | + env->NZF = T0; | |
| 132 | + env->CF = T0 < src1; | |
| 133 | + env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0); | |
| 134 | +} | |
| 135 | + | |
| 136 | +void OPPROTO op_adcl_T0_T1(void) | |
| 137 | +{ | |
| 138 | + T0 += T1 + env->CF; | |
| 139 | +} | |
| 140 | + | |
| 141 | +void OPPROTO op_adcl_T0_T1_cc(void) | |
| 142 | +{ | |
| 143 | + unsigned int src1; | |
| 144 | + src1 = T0; | |
| 145 | + if (!env->CF) { | |
| 146 | + T0 += T1; | |
| 147 | + env->CF = T0 < src1; | |
| 148 | + } else { | |
| 149 | + T0 += T1 + 1; | |
| 150 | + env->CF = T0 <= src1; | |
| 151 | + } | |
| 152 | + env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0); | |
| 153 | + env->NZF = T0; | |
| 154 | + FORCE_RET(); | |
| 155 | +} | |
| 156 | + | |
| 157 | +#define OPSUB(sub, sbc, T0, T1) \ | |
| 158 | + \ | |
| 159 | +void OPPROTO op_ ## sub ## l_T0_T1(void) \ | |
| 160 | +{ \ | |
| 161 | + T0 -= T1; \ | |
| 162 | +} \ | |
| 163 | + \ | |
| 164 | +void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \ | |
| 165 | +{ \ | |
| 166 | + unsigned int src1; \ | |
| 167 | + src1 = T0; \ | |
| 168 | + T0 -= T1; \ | |
| 169 | + env->NZF = T0; \ | |
| 170 | + env->CF = src1 < T1; \ | |
| 171 | + env->VF = (src1 ^ T1) & (src1 ^ T0); \ | |
| 172 | +} \ | |
| 173 | + \ | |
| 174 | +void OPPROTO op_ ## sbc ## l_T0_T1(void) \ | |
| 175 | +{ \ | |
| 176 | + T0 = T0 - T1 + env->CF - 1; \ | |
| 177 | +} \ | |
| 178 | + \ | |
| 179 | +void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \ | |
| 180 | +{ \ | |
| 181 | + unsigned int src1; \ | |
| 182 | + src1 = T0; \ | |
| 183 | + if (!env->CF) { \ | |
| 184 | + T0 = T0 - T1 - 1; \ | |
| 185 | + T0 += T1; \ | |
| 186 | + env->CF = src1 < T1; \ | |
| 187 | + } else { \ | |
| 188 | + T0 = T0 - T1; \ | |
| 189 | + env->CF = src1 <= T1; \ | |
| 190 | + } \ | |
| 191 | + env->VF = (src1 ^ T1) & (src1 ^ T0); \ | |
| 192 | + env->NZF = T0; \ | |
| 193 | + FORCE_RET(); \ | |
| 194 | +} | |
| 195 | + | |
| 196 | +OPSUB(sub, sbc, T0, T1) | |
| 197 | + | |
| 198 | +OPSUB(rsb, rsc, T1, T0) | |
| 199 | + | |
| 200 | +void OPPROTO op_andl_T0_T1(void) | |
| 201 | +{ | |
| 202 | + T0 &= T1; | |
| 203 | +} | |
| 204 | + | |
| 205 | +void OPPROTO op_xorl_T0_T1(void) | |
| 206 | +{ | |
| 207 | + T0 ^= T1; | |
| 208 | +} | |
| 209 | + | |
| 210 | +void OPPROTO op_orl_T0_T1(void) | |
| 211 | +{ | |
| 212 | + T0 |= T1; | |
| 213 | +} | |
| 214 | + | |
| 215 | +void OPPROTO op_bicl_T0_T1(void) | |
| 216 | +{ | |
| 217 | + T0 &= ~T1; | |
| 218 | +} | |
| 219 | + | |
| 220 | +void OPPROTO op_notl_T1(void) | |
| 221 | +{ | |
| 222 | + T1 = ~T1; | |
| 223 | +} | |
| 224 | + | |
| 225 | +void OPPROTO op_logic_cc(void) | |
| 226 | +{ | |
| 227 | + env->NZF = T0; | |
| 228 | +} | |
| 229 | + | |
| 230 | +#define EIP (env->regs[15]) | |
| 231 | + | |
| 232 | +void OPPROTO op_test_eq(void) | |
| 233 | +{ | |
| 234 | + if (env->NZF == 0) | |
| 235 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 236 | + FORCE_RET(); | |
| 237 | +} | |
| 238 | + | |
| 239 | +void OPPROTO op_test_ne(void) | |
| 240 | +{ | |
| 241 | + if (env->NZF != 0) | |
| 242 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 243 | + FORCE_RET(); | |
| 244 | +} | |
| 245 | + | |
| 246 | +void OPPROTO op_test_cs(void) | |
| 247 | +{ | |
| 248 | + if (env->CF != 0) | |
| 249 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 250 | + FORCE_RET(); | |
| 251 | +} | |
| 252 | + | |
| 253 | +void OPPROTO op_test_cc(void) | |
| 254 | +{ | |
| 255 | + if (env->CF == 0) | |
| 256 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 257 | + FORCE_RET(); | |
| 258 | +} | |
| 259 | + | |
| 260 | +void OPPROTO op_test_mi(void) | |
| 261 | +{ | |
| 262 | + if ((env->NZF & 0x80000000) != 0) | |
| 263 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 264 | + FORCE_RET(); | |
| 265 | +} | |
| 266 | + | |
| 267 | +void OPPROTO op_test_pl(void) | |
| 268 | +{ | |
| 269 | + if ((env->NZF & 0x80000000) == 0) | |
| 270 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 271 | + FORCE_RET(); | |
| 272 | +} | |
| 273 | + | |
| 274 | +void OPPROTO op_test_vs(void) | |
| 275 | +{ | |
| 276 | + if ((env->VF & 0x80000000) != 0) | |
| 277 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 278 | + FORCE_RET(); | |
| 279 | +} | |
| 280 | + | |
| 281 | +void OPPROTO op_test_vc(void) | |
| 282 | +{ | |
| 283 | + if ((env->VF & 0x80000000) == 0) | |
| 284 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 285 | + FORCE_RET(); | |
| 286 | +} | |
| 287 | + | |
| 288 | +void OPPROTO op_test_hi(void) | |
| 289 | +{ | |
| 290 | + if (env->CF != 0 && env->NZF != 0) | |
| 291 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 292 | + FORCE_RET(); | |
| 293 | +} | |
| 294 | + | |
| 295 | +void OPPROTO op_test_ls(void) | |
| 296 | +{ | |
| 297 | + if (env->CF == 0 || env->NZF == 0) | |
| 298 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 299 | + FORCE_RET(); | |
| 300 | +} | |
| 301 | + | |
| 302 | +void OPPROTO op_test_ge(void) | |
| 303 | +{ | |
| 304 | + if (((env->VF ^ env->NZF) & 0x80000000) == 0) | |
| 305 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 306 | + FORCE_RET(); | |
| 307 | +} | |
| 308 | + | |
| 309 | +void OPPROTO op_test_lt(void) | |
| 310 | +{ | |
| 311 | + if (((env->VF ^ env->NZF) & 0x80000000) != 0) | |
| 312 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 313 | + FORCE_RET(); | |
| 314 | +} | |
| 315 | + | |
| 316 | +void OPPROTO op_test_gt(void) | |
| 317 | +{ | |
| 318 | + if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0) | |
| 319 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 320 | + FORCE_RET(); | |
| 321 | +} | |
| 322 | + | |
| 323 | +void OPPROTO op_test_le(void) | |
| 324 | +{ | |
| 325 | + if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0) | |
| 326 | + JUMP_TB(PARAM1, 0, PARAM2); | |
| 327 | + FORCE_RET(); | |
| 328 | +} | |
| 329 | + | |
| 330 | +void OPPROTO op_jmp(void) | |
| 331 | +{ | |
| 332 | + JUMP_TB(PARAM1, 1, PARAM2); | |
| 333 | +} | |
| 334 | + | |
| 335 | +void OPPROTO op_movl_T0_psr(void) | |
| 336 | +{ | |
| 337 | + int ZF; | |
| 338 | + ZF = (env->NZF == 0); | |
| 339 | + T0 = env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) | | |
| 340 | + (env->CF << 29) | ((env->VF & 0x80000000) >> 3); | |
| 341 | +} | |
| 342 | + | |
| 343 | +/* NOTE: N = 1 and Z = 1 cannot be stored currently */ | |
| 344 | +void OPPROTO op_movl_psr_T0(void) | |
| 345 | +{ | |
| 346 | + unsigned int psr; | |
| 347 | + psr = T0; | |
| 348 | + env->CF = (psr >> 29) & 1; | |
| 349 | + env->NZF = (psr & 0xc0000000) ^ 0x40000000; | |
| 350 | + env->VF = (psr << 3) & 0x80000000; | |
| 351 | + /* for user mode we do not update other state info */ | |
| 352 | +} | |
| 353 | + | |
| 354 | +void OPPROTO op_mul_T0_T1(void) | |
| 355 | +{ | |
| 356 | + T0 = T0 * T1; | |
| 357 | +} | |
| 358 | + | |
| 359 | +/* 64 bit unsigned mul */ | |
| 360 | +void OPPROTO op_mull_T0_T1(void) | |
| 361 | +{ | |
| 362 | + uint64_t res; | |
| 363 | + res = T0 * T1; | |
| 364 | + T1 = res >> 32; | |
| 365 | + T0 = res; | |
| 366 | +} | |
| 367 | + | |
| 368 | +/* 64 bit signed mul */ | |
| 369 | +void OPPROTO op_imull_T0_T1(void) | |
| 370 | +{ | |
| 371 | + uint64_t res; | |
| 372 | + res = (int32_t)T0 * (int32_t)T1; | |
| 373 | + T1 = res >> 32; | |
| 374 | + T0 = res; | |
| 375 | +} | |
| 376 | + | |
| 377 | +void OPPROTO op_addq_T0_T1(void) | |
| 378 | +{ | |
| 379 | + uint64_t res; | |
| 380 | + res = ((uint64_t)T1 << 32) | T0; | |
| 381 | + res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]); | |
| 382 | + T1 = res >> 32; | |
| 383 | + T0 = res; | |
| 384 | +} | |
| 385 | + | |
| 386 | +void OPPROTO op_logicq_cc(void) | |
| 387 | +{ | |
| 388 | + env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0); | |
| 389 | +} | |
| 390 | + | |
| 391 | +/* memory access */ | |
| 392 | + | |
| 393 | +void OPPROTO op_ldub_T0_T1(void) | |
| 394 | +{ | |
| 395 | + T0 = ldub((void *)T1); | |
| 396 | +} | |
| 397 | + | |
| 398 | +void OPPROTO op_ldsb_T0_T1(void) | |
| 399 | +{ | |
| 400 | + T0 = ldsb((void *)T1); | |
| 401 | +} | |
| 402 | + | |
| 403 | +void OPPROTO op_lduw_T0_T1(void) | |
| 404 | +{ | |
| 405 | + T0 = lduw((void *)T1); | |
| 406 | +} | |
| 407 | + | |
| 408 | +void OPPROTO op_ldsw_T0_T1(void) | |
| 409 | +{ | |
| 410 | + T0 = ldsw((void *)T1); | |
| 411 | +} | |
| 412 | + | |
| 413 | +void OPPROTO op_ldl_T0_T1(void) | |
| 414 | +{ | |
| 415 | + T0 = ldl((void *)T1); | |
| 416 | +} | |
| 417 | + | |
| 418 | +void OPPROTO op_stb_T0_T1(void) | |
| 419 | +{ | |
| 420 | + stb((void *)T1, T0); | |
| 421 | +} | |
| 422 | + | |
| 423 | +void OPPROTO op_stw_T0_T1(void) | |
| 424 | +{ | |
| 425 | + stw((void *)T1, T0); | |
| 426 | +} | |
| 427 | + | |
| 428 | +void OPPROTO op_stl_T0_T1(void) | |
| 429 | +{ | |
| 430 | + stl((void *)T1, T0); | |
| 431 | +} | |
| 432 | + | |
| 433 | +void OPPROTO op_swpb_T0_T1(void) | |
| 434 | +{ | |
| 435 | + int tmp; | |
| 436 | + | |
| 437 | + cpu_lock(); | |
| 438 | + tmp = ldub((void *)T1); | |
| 439 | + stb((void *)T1, T0); | |
| 440 | + T0 = tmp; | |
| 441 | + cpu_unlock(); | |
| 442 | +} | |
| 443 | + | |
| 444 | +void OPPROTO op_swpl_T0_T1(void) | |
| 445 | +{ | |
| 446 | + int tmp; | |
| 447 | + | |
| 448 | + cpu_lock(); | |
| 449 | + tmp = ldl((void *)T1); | |
| 450 | + stl((void *)T1, T0); | |
| 451 | + T0 = tmp; | |
| 452 | + cpu_unlock(); | |
| 453 | +} | |
| 454 | + | |
| 455 | +/* shifts */ | |
| 456 | + | |
| 457 | +/* T1 based */ | |
| 458 | +void OPPROTO op_shll_T1_im(void) | |
| 459 | +{ | |
| 460 | + T1 = T1 << PARAM1; | |
| 461 | +} | |
| 462 | + | |
| 463 | +void OPPROTO op_shrl_T1_im(void) | |
| 464 | +{ | |
| 465 | + T1 = (uint32_t)T1 >> PARAM1; | |
| 466 | +} | |
| 467 | + | |
| 468 | +void OPPROTO op_sarl_T1_im(void) | |
| 469 | +{ | |
| 470 | + T1 = (int32_t)T1 >> PARAM1; | |
| 471 | +} | |
| 472 | + | |
| 473 | +void OPPROTO op_rorl_T1_im(void) | |
| 474 | +{ | |
| 475 | + int shift; | |
| 476 | + shift = PARAM1; | |
| 477 | + T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | |
| 478 | +} | |
| 479 | + | |
| 480 | +/* T1 based, set C flag */ | |
| 481 | +void OPPROTO op_shll_T1_im_cc(void) | |
| 482 | +{ | |
| 483 | + env->CF = (T1 >> (32 - PARAM1)) & 1; | |
| 484 | + T1 = T1 << PARAM1; | |
| 485 | +} | |
| 486 | + | |
| 487 | +void OPPROTO op_shrl_T1_im_cc(void) | |
| 488 | +{ | |
| 489 | + env->CF = (T1 >> (PARAM1 - 1)) & 1; | |
| 490 | + T1 = (uint32_t)T1 >> PARAM1; | |
| 491 | +} | |
| 492 | + | |
| 493 | +void OPPROTO op_sarl_T1_im_cc(void) | |
| 494 | +{ | |
| 495 | + env->CF = (T1 >> (PARAM1 - 1)) & 1; | |
| 496 | + T1 = (int32_t)T1 >> PARAM1; | |
| 497 | +} | |
| 498 | + | |
| 499 | +void OPPROTO op_rorl_T1_im_cc(void) | |
| 500 | +{ | |
| 501 | + int shift; | |
| 502 | + shift = PARAM1; | |
| 503 | + env->CF = (T1 >> (shift - 1)) & 1; | |
| 504 | + T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | |
| 505 | +} | |
| 506 | + | |
| 507 | +/* T2 based */ | |
| 508 | +void OPPROTO op_shll_T2_im(void) | |
| 509 | +{ | |
| 510 | + T2 = T2 << PARAM1; | |
| 511 | +} | |
| 512 | + | |
| 513 | +void OPPROTO op_shrl_T2_im(void) | |
| 514 | +{ | |
| 515 | + T2 = (uint32_t)T2 >> PARAM1; | |
| 516 | +} | |
| 517 | + | |
| 518 | +void OPPROTO op_sarl_T2_im(void) | |
| 519 | +{ | |
| 520 | + T2 = (int32_t)T2 >> PARAM1; | |
| 521 | +} | |
| 522 | + | |
| 523 | +void OPPROTO op_rorl_T2_im(void) | |
| 524 | +{ | |
| 525 | + int shift; | |
| 526 | + shift = PARAM1; | |
| 527 | + T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift)); | |
| 528 | +} | |
| 529 | + | |
| 530 | +/* T1 based, use T0 as shift count */ | |
| 531 | + | |
| 532 | +void OPPROTO op_shll_T1_T0(void) | |
| 533 | +{ | |
| 534 | + int shift; | |
| 535 | + shift = T0 & 0xff; | |
| 536 | + if (shift >= 32) | |
| 537 | + T1 = 0; | |
| 538 | + else | |
| 539 | + T1 = T1 << shift; | |
| 540 | + FORCE_RET(); | |
| 541 | +} | |
| 542 | + | |
| 543 | +void OPPROTO op_shrl_T1_T0(void) | |
| 544 | +{ | |
| 545 | + int shift; | |
| 546 | + shift = T0 & 0xff; | |
| 547 | + if (shift >= 32) | |
| 548 | + T1 = 0; | |
| 549 | + else | |
| 550 | + T1 = (uint32_t)T1 >> shift; | |
| 551 | + FORCE_RET(); | |
| 552 | +} | |
| 553 | + | |
| 554 | +void OPPROTO op_sarl_T1_T0(void) | |
| 555 | +{ | |
| 556 | + int shift; | |
| 557 | + shift = T0 & 0xff; | |
| 558 | + if (shift >= 32) | |
| 559 | + shift = 31; | |
| 560 | + T1 = (int32_t)T1 >> shift; | |
| 561 | +} | |
| 562 | + | |
| 563 | +void OPPROTO op_rorl_T1_T0(void) | |
| 564 | +{ | |
| 565 | + int shift; | |
| 566 | + shift = T0 & 0x1f; | |
| 567 | + if (shift) { | |
| 568 | + T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | |
| 569 | + } | |
| 570 | + FORCE_RET(); | |
| 571 | +} | |
| 572 | + | |
| 573 | +/* T1 based, use T0 as shift count and compute CF */ | |
| 574 | + | |
| 575 | +void OPPROTO op_shll_T1_T0_cc(void) | |
| 576 | +{ | |
| 577 | + int shift; | |
| 578 | + shift = T0 & 0xff; | |
| 579 | + if (shift >= 32) { | |
| 580 | + if (shift == 32) | |
| 581 | + env->CF = T1 & 1; | |
| 582 | + else | |
| 583 | + env->CF = 0; | |
| 584 | + T1 = 0; | |
| 585 | + } else if (shift != 0) { | |
| 586 | + env->CF = (T1 >> (32 - shift)) & 1; | |
| 587 | + T1 = T1 << shift; | |
| 588 | + } | |
| 589 | + FORCE_RET(); | |
| 590 | +} | |
| 591 | + | |
| 592 | +void OPPROTO op_shrl_T1_T0_cc(void) | |
| 593 | +{ | |
| 594 | + int shift; | |
| 595 | + shift = T0 & 0xff; | |
| 596 | + if (shift >= 32) { | |
| 597 | + if (shift == 32) | |
| 598 | + env->CF = (T1 >> 31) & 1; | |
| 599 | + else | |
| 600 | + env->CF = 0; | |
| 601 | + T1 = 0; | |
| 602 | + } else if (shift != 0) { | |
| 603 | + env->CF = (T1 >> (shift - 1)) & 1; | |
| 604 | + T1 = (uint32_t)T1 >> shift; | |
| 605 | + } | |
| 606 | + FORCE_RET(); | |
| 607 | +} | |
| 608 | + | |
| 609 | +void OPPROTO op_sarl_T1_T0_cc(void) | |
| 610 | +{ | |
| 611 | + int shift; | |
| 612 | + shift = T0 & 0xff; | |
| 613 | + if (shift >= 32) { | |
| 614 | + env->CF = (T1 >> 31) & 1; | |
| 615 | + T1 = (int32_t)T1 >> 31; | |
| 616 | + } else { | |
| 617 | + env->CF = (T1 >> (shift - 1)) & 1; | |
| 618 | + T1 = (int32_t)T1 >> shift; | |
| 619 | + } | |
| 620 | + FORCE_RET(); | |
| 621 | +} | |
| 622 | + | |
| 623 | +void OPPROTO op_rorl_T1_T0_cc(void) | |
| 624 | +{ | |
| 625 | + int shift1, shift; | |
| 626 | + shift1 = T0 & 0xff; | |
| 627 | + shift = shift1 & 0x1f; | |
| 628 | + if (shift == 0) { | |
| 629 | + if (shift1 != 0) | |
| 630 | + env->CF = (T1 >> 31) & 1; | |
| 631 | + } else { | |
| 632 | + env->CF = (T1 >> (shift - 1)) & 1; | |
| 633 | + T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift)); | |
| 634 | + } | |
| 635 | + FORCE_RET(); | |
| 636 | +} | |
| 637 | + | |
| 638 | +/* exceptions */ | |
| 639 | + | |
| 640 | +void OPPROTO op_swi(void) | |
| 641 | +{ | |
| 642 | + env->exception_index = EXCP_SWI; | |
| 643 | + cpu_loop_exit(); | |
| 644 | +} | |
| 645 | + | |
| 646 | +void OPPROTO op_undef_insn(void) | |
| 647 | +{ | |
| 648 | + env->exception_index = EXCP_UDEF; | |
| 649 | + cpu_loop_exit(); | |
| 650 | +} | |
| 651 | + | |
| 652 | +/* thread support */ | |
| 653 | + | |
| 654 | +spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; | |
| 655 | + | |
| 656 | +void cpu_lock(void) | |
| 657 | +{ | |
| 658 | + spin_lock(&global_cpu_lock); | |
| 659 | +} | |
| 660 | + | |
| 661 | +void cpu_unlock(void) | |
| 662 | +{ | |
| 663 | + spin_unlock(&global_cpu_lock); | |
| 664 | +} | |
| 665 | + | ... | ... |
syscall-arm.h
0 → 100644
| 1 | + | |
| 2 | +/* this struct defines the way the registers are stored on the | |
| 3 | + stack during a system call. */ | |
| 4 | + | |
| 5 | +struct target_pt_regs { | |
| 6 | + target_long uregs[18]; | |
| 7 | +}; | |
| 8 | + | |
| 9 | +#define ARM_cpsr uregs[16] | |
| 10 | +#define ARM_pc uregs[15] | |
| 11 | +#define ARM_lr uregs[14] | |
| 12 | +#define ARM_sp uregs[13] | |
| 13 | +#define ARM_ip uregs[12] | |
| 14 | +#define ARM_fp uregs[11] | |
| 15 | +#define ARM_r10 uregs[10] | |
| 16 | +#define ARM_r9 uregs[9] | |
| 17 | +#define ARM_r8 uregs[8] | |
| 18 | +#define ARM_r7 uregs[7] | |
| 19 | +#define ARM_r6 uregs[6] | |
| 20 | +#define ARM_r5 uregs[5] | |
| 21 | +#define ARM_r4 uregs[4] | |
| 22 | +#define ARM_r3 uregs[3] | |
| 23 | +#define ARM_r2 uregs[2] | |
| 24 | +#define ARM_r1 uregs[1] | |
| 25 | +#define ARM_r0 uregs[0] | |
| 26 | +#define ARM_ORIG_r0 uregs[17] | |
| 27 | + | ... | ... |
translate-arm.c
0 → 100644
| 1 | +/* | |
| 2 | + * ARM translation | |
| 3 | + * | |
| 4 | + * Copyright (c) 2003 Fabrice Bellard | |
| 5 | + * | |
| 6 | + * This library is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU Lesser General Public | |
| 8 | + * License as published by the Free Software Foundation; either | |
| 9 | + * version 2 of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This library is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | + * Lesser General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public | |
| 17 | + * License along with this library; if not, write to the Free Software | |
| 18 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 19 | + */ | |
| 20 | +#include <stdarg.h> | |
| 21 | +#include <stdlib.h> | |
| 22 | +#include <stdio.h> | |
| 23 | +#include <string.h> | |
| 24 | +#include <inttypes.h> | |
| 25 | + | |
| 26 | +#include "cpu-arm.h" | |
| 27 | +#include "exec.h" | |
| 28 | +#include "disas.h" | |
| 29 | + | |
| 30 | +/* internal defines */ | |
| 31 | +typedef struct DisasContext { | |
| 32 | + uint8_t *pc; | |
| 33 | + int is_jmp; | |
| 34 | + struct TranslationBlock *tb; | |
| 35 | +} DisasContext; | |
| 36 | + | |
| 37 | +/* XXX: move that elsewhere */ | |
| 38 | +static uint16_t *gen_opc_ptr; | |
| 39 | +static uint32_t *gen_opparam_ptr; | |
| 40 | +extern FILE *logfile; | |
| 41 | +extern int loglevel; | |
| 42 | + | |
| 43 | +enum { | |
| 44 | +#define DEF(s, n, copy_size) INDEX_op_ ## s, | |
| 45 | +#include "opc-arm.h" | |
| 46 | +#undef DEF | |
| 47 | + NB_OPS, | |
| 48 | +}; | |
| 49 | + | |
| 50 | +#include "gen-op-arm.h" | |
| 51 | + | |
| 52 | +typedef void (GenOpFunc)(void); | |
| 53 | +typedef void (GenOpFunc1)(long); | |
| 54 | +typedef void (GenOpFunc2)(long, long); | |
| 55 | +typedef void (GenOpFunc3)(long, long, long); | |
| 56 | + | |
| 57 | +static GenOpFunc2 *gen_test_cc[14] = { | |
| 58 | + gen_op_test_eq, | |
| 59 | + gen_op_test_ne, | |
| 60 | + gen_op_test_cs, | |
| 61 | + gen_op_test_cc, | |
| 62 | + gen_op_test_mi, | |
| 63 | + gen_op_test_pl, | |
| 64 | + gen_op_test_vs, | |
| 65 | + gen_op_test_vc, | |
| 66 | + gen_op_test_hi, | |
| 67 | + gen_op_test_ls, | |
| 68 | + gen_op_test_ge, | |
| 69 | + gen_op_test_lt, | |
| 70 | + gen_op_test_gt, | |
| 71 | + gen_op_test_le, | |
| 72 | +}; | |
| 73 | + | |
| 74 | +const uint8_t table_logic_cc[16] = { | |
| 75 | + 1, /* and */ | |
| 76 | + 1, /* xor */ | |
| 77 | + 0, /* sub */ | |
| 78 | + 0, /* rsb */ | |
| 79 | + 0, /* add */ | |
| 80 | + 0, /* adc */ | |
| 81 | + 0, /* sbc */ | |
| 82 | + 0, /* rsc */ | |
| 83 | + 1, /* andl */ | |
| 84 | + 1, /* xorl */ | |
| 85 | + 0, /* cmp */ | |
| 86 | + 0, /* cmn */ | |
| 87 | + 1, /* orr */ | |
| 88 | + 1, /* mov */ | |
| 89 | + 1, /* bic */ | |
| 90 | + 1, /* mvn */ | |
| 91 | +}; | |
| 92 | + | |
| 93 | +static GenOpFunc1 *gen_shift_T1_im[4] = { | |
| 94 | + gen_op_shll_T1_im, | |
| 95 | + gen_op_shrl_T1_im, | |
| 96 | + gen_op_sarl_T1_im, | |
| 97 | + gen_op_rorl_T1_im, | |
| 98 | +}; | |
| 99 | + | |
| 100 | +static GenOpFunc1 *gen_shift_T2_im[4] = { | |
| 101 | + gen_op_shll_T2_im, | |
| 102 | + gen_op_shrl_T2_im, | |
| 103 | + gen_op_sarl_T2_im, | |
| 104 | + gen_op_rorl_T2_im, | |
| 105 | +}; | |
| 106 | + | |
| 107 | +static GenOpFunc1 *gen_shift_T1_im_cc[4] = { | |
| 108 | + gen_op_shll_T1_im_cc, | |
| 109 | + gen_op_shrl_T1_im_cc, | |
| 110 | + gen_op_sarl_T1_im_cc, | |
| 111 | + gen_op_rorl_T1_im_cc, | |
| 112 | +}; | |
| 113 | + | |
| 114 | +static GenOpFunc *gen_shift_T1_T0[4] = { | |
| 115 | + gen_op_shll_T1_T0, | |
| 116 | + gen_op_shrl_T1_T0, | |
| 117 | + gen_op_sarl_T1_T0, | |
| 118 | + gen_op_rorl_T1_T0, | |
| 119 | +}; | |
| 120 | + | |
| 121 | +static GenOpFunc *gen_shift_T1_T0_cc[4] = { | |
| 122 | + gen_op_shll_T1_T0_cc, | |
| 123 | + gen_op_shrl_T1_T0_cc, | |
| 124 | + gen_op_sarl_T1_T0_cc, | |
| 125 | + gen_op_rorl_T1_T0_cc, | |
| 126 | +}; | |
| 127 | + | |
| 128 | +static GenOpFunc *gen_op_movl_TN_reg[3][16] = { | |
| 129 | + { | |
| 130 | + gen_op_movl_T0_r0, | |
| 131 | + gen_op_movl_T0_r1, | |
| 132 | + gen_op_movl_T0_r2, | |
| 133 | + gen_op_movl_T0_r3, | |
| 134 | + gen_op_movl_T0_r4, | |
| 135 | + gen_op_movl_T0_r5, | |
| 136 | + gen_op_movl_T0_r6, | |
| 137 | + gen_op_movl_T0_r7, | |
| 138 | + gen_op_movl_T0_r8, | |
| 139 | + gen_op_movl_T0_r9, | |
| 140 | + gen_op_movl_T0_r10, | |
| 141 | + gen_op_movl_T0_r11, | |
| 142 | + gen_op_movl_T0_r12, | |
| 143 | + gen_op_movl_T0_r13, | |
| 144 | + gen_op_movl_T0_r14, | |
| 145 | + gen_op_movl_T0_r15, | |
| 146 | + }, | |
| 147 | + { | |
| 148 | + gen_op_movl_T1_r0, | |
| 149 | + gen_op_movl_T1_r1, | |
| 150 | + gen_op_movl_T1_r2, | |
| 151 | + gen_op_movl_T1_r3, | |
| 152 | + gen_op_movl_T1_r4, | |
| 153 | + gen_op_movl_T1_r5, | |
| 154 | + gen_op_movl_T1_r6, | |
| 155 | + gen_op_movl_T1_r7, | |
| 156 | + gen_op_movl_T1_r8, | |
| 157 | + gen_op_movl_T1_r9, | |
| 158 | + gen_op_movl_T1_r10, | |
| 159 | + gen_op_movl_T1_r11, | |
| 160 | + gen_op_movl_T1_r12, | |
| 161 | + gen_op_movl_T1_r13, | |
| 162 | + gen_op_movl_T1_r14, | |
| 163 | + gen_op_movl_T1_r15, | |
| 164 | + }, | |
| 165 | + { | |
| 166 | + gen_op_movl_T2_r0, | |
| 167 | + gen_op_movl_T2_r1, | |
| 168 | + gen_op_movl_T2_r2, | |
| 169 | + gen_op_movl_T2_r3, | |
| 170 | + gen_op_movl_T2_r4, | |
| 171 | + gen_op_movl_T2_r5, | |
| 172 | + gen_op_movl_T2_r6, | |
| 173 | + gen_op_movl_T2_r7, | |
| 174 | + gen_op_movl_T2_r8, | |
| 175 | + gen_op_movl_T2_r9, | |
| 176 | + gen_op_movl_T2_r10, | |
| 177 | + gen_op_movl_T2_r11, | |
| 178 | + gen_op_movl_T2_r12, | |
| 179 | + gen_op_movl_T2_r13, | |
| 180 | + gen_op_movl_T2_r14, | |
| 181 | + gen_op_movl_T2_r15, | |
| 182 | + }, | |
| 183 | +}; | |
| 184 | + | |
| 185 | +static GenOpFunc *gen_op_movl_reg_TN[2][16] = { | |
| 186 | + { | |
| 187 | + gen_op_movl_r0_T0, | |
| 188 | + gen_op_movl_r1_T0, | |
| 189 | + gen_op_movl_r2_T0, | |
| 190 | + gen_op_movl_r3_T0, | |
| 191 | + gen_op_movl_r4_T0, | |
| 192 | + gen_op_movl_r5_T0, | |
| 193 | + gen_op_movl_r6_T0, | |
| 194 | + gen_op_movl_r7_T0, | |
| 195 | + gen_op_movl_r8_T0, | |
| 196 | + gen_op_movl_r9_T0, | |
| 197 | + gen_op_movl_r10_T0, | |
| 198 | + gen_op_movl_r11_T0, | |
| 199 | + gen_op_movl_r12_T0, | |
| 200 | + gen_op_movl_r13_T0, | |
| 201 | + gen_op_movl_r14_T0, | |
| 202 | + gen_op_movl_r15_T0, | |
| 203 | + }, | |
| 204 | + { | |
| 205 | + gen_op_movl_r0_T1, | |
| 206 | + gen_op_movl_r1_T1, | |
| 207 | + gen_op_movl_r2_T1, | |
| 208 | + gen_op_movl_r3_T1, | |
| 209 | + gen_op_movl_r4_T1, | |
| 210 | + gen_op_movl_r5_T1, | |
| 211 | + gen_op_movl_r6_T1, | |
| 212 | + gen_op_movl_r7_T1, | |
| 213 | + gen_op_movl_r8_T1, | |
| 214 | + gen_op_movl_r9_T1, | |
| 215 | + gen_op_movl_r10_T1, | |
| 216 | + gen_op_movl_r11_T1, | |
| 217 | + gen_op_movl_r12_T1, | |
| 218 | + gen_op_movl_r13_T1, | |
| 219 | + gen_op_movl_r14_T1, | |
| 220 | + gen_op_movl_r15_T1, | |
| 221 | + }, | |
| 222 | +}; | |
| 223 | + | |
| 224 | +static GenOpFunc1 *gen_op_movl_TN_im[3] = { | |
| 225 | + gen_op_movl_T0_im, | |
| 226 | + gen_op_movl_T1_im, | |
| 227 | + gen_op_movl_T2_im, | |
| 228 | +}; | |
| 229 | + | |
| 230 | +static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t) | |
| 231 | +{ | |
| 232 | + int val; | |
| 233 | + | |
| 234 | + if (reg == 15) { | |
| 235 | + /* normaly, since we updated PC, we need only to add 4 */ | |
| 236 | + val = (long)s->pc + 4; | |
| 237 | + gen_op_movl_TN_im[t](val); | |
| 238 | + } else { | |
| 239 | + gen_op_movl_TN_reg[t][reg](); | |
| 240 | + } | |
| 241 | +} | |
| 242 | + | |
| 243 | +static inline void gen_movl_T0_reg(DisasContext *s, int reg) | |
| 244 | +{ | |
| 245 | + gen_movl_TN_reg(s, reg, 0); | |
| 246 | +} | |
| 247 | + | |
| 248 | +static inline void gen_movl_T1_reg(DisasContext *s, int reg) | |
| 249 | +{ | |
| 250 | + gen_movl_TN_reg(s, reg, 1); | |
| 251 | +} | |
| 252 | + | |
| 253 | +static inline void gen_movl_T2_reg(DisasContext *s, int reg) | |
| 254 | +{ | |
| 255 | + gen_movl_TN_reg(s, reg, 2); | |
| 256 | +} | |
| 257 | + | |
| 258 | +static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t) | |
| 259 | +{ | |
| 260 | + gen_op_movl_reg_TN[t][reg](); | |
| 261 | + if (reg == 15) { | |
| 262 | + s->is_jmp = DISAS_JUMP; | |
| 263 | + } | |
| 264 | +} | |
| 265 | + | |
| 266 | +static inline void gen_movl_reg_T0(DisasContext *s, int reg) | |
| 267 | +{ | |
| 268 | + gen_movl_reg_TN(s, reg, 0); | |
| 269 | +} | |
| 270 | + | |
| 271 | +static inline void gen_movl_reg_T1(DisasContext *s, int reg) | |
| 272 | +{ | |
| 273 | + gen_movl_reg_TN(s, reg, 1); | |
| 274 | +} | |
| 275 | + | |
| 276 | +static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) | |
| 277 | +{ | |
| 278 | + int val, rm, shift; | |
| 279 | + | |
| 280 | + if (!(insn & (1 << 25))) { | |
| 281 | + /* immediate */ | |
| 282 | + val = insn & 0xfff; | |
| 283 | + if (!(insn & (1 << 23))) | |
| 284 | + val = -val; | |
| 285 | + gen_op_addl_T1_im(val); | |
| 286 | + } else { | |
| 287 | + /* shift/register */ | |
| 288 | + rm = (insn) & 0xf; | |
| 289 | + shift = (insn >> 7) & 0x1f; | |
| 290 | + gen_movl_T2_reg(s, rm); | |
| 291 | + if (shift != 0) { | |
| 292 | + gen_shift_T2_im[(insn >> 5) & 3](shift); | |
| 293 | + } | |
| 294 | + if (!(insn & (1 << 23))) | |
| 295 | + gen_op_subl_T1_T2(); | |
| 296 | + else | |
| 297 | + gen_op_addl_T1_T2(); | |
| 298 | + } | |
| 299 | +} | |
| 300 | + | |
| 301 | +static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn) | |
| 302 | +{ | |
| 303 | + int val, rm; | |
| 304 | + | |
| 305 | + if (insn & (1 << 22)) { | |
| 306 | + /* immediate */ | |
| 307 | + val = (insn & 0xf) | ((insn >> 4) & 0xf0); | |
| 308 | + if (!(insn & (1 << 23))) | |
| 309 | + val = -val; | |
| 310 | + gen_op_addl_T1_im(val); | |
| 311 | + } else { | |
| 312 | + /* register */ | |
| 313 | + rm = (insn) & 0xf; | |
| 314 | + gen_movl_T2_reg(s, rm); | |
| 315 | + if (!(insn & (1 << 23))) | |
| 316 | + gen_op_subl_T1_T2(); | |
| 317 | + else | |
| 318 | + gen_op_addl_T1_T2(); | |
| 319 | + } | |
| 320 | +} | |
| 321 | + | |
| 322 | +static void disas_arm_insn(DisasContext *s) | |
| 323 | +{ | |
| 324 | + unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; | |
| 325 | + | |
| 326 | + insn = ldl(s->pc); | |
| 327 | + s->pc += 4; | |
| 328 | + | |
| 329 | + cond = insn >> 28; | |
| 330 | + if (cond == 0xf) | |
| 331 | + goto illegal_op; | |
| 332 | + if (cond != 0xe) { | |
| 333 | + /* if not always execute, we generate a conditional jump to | |
| 334 | + next instruction */ | |
| 335 | + gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); | |
| 336 | + s->is_jmp = 1; | |
| 337 | + } | |
| 338 | + if ((insn & 0x0c000000) == 0 && | |
| 339 | + (insn & 0x00000090) != 0x90) { | |
| 340 | + int set_cc, logic_cc, shiftop; | |
| 341 | + | |
| 342 | + op1 = (insn >> 21) & 0xf; | |
| 343 | + set_cc = (insn >> 20) & 1; | |
| 344 | + logic_cc = table_logic_cc[op1] & set_cc; | |
| 345 | + | |
| 346 | + /* data processing instruction */ | |
| 347 | + if (insn & (1 << 25)) { | |
| 348 | + /* immediate operand */ | |
| 349 | + val = insn & 0xff; | |
| 350 | + shift = ((insn >> 8) & 0xf) * 2; | |
| 351 | + if (shift) | |
| 352 | + val = (val >> shift) | (val << (32 - shift)); | |
| 353 | + gen_op_movl_T1_im(val); | |
| 354 | + /* XXX: is CF modified ? */ | |
| 355 | + } else { | |
| 356 | + /* register */ | |
| 357 | + rm = (insn) & 0xf; | |
| 358 | + gen_movl_T1_reg(s, rm); | |
| 359 | + shiftop = (insn >> 5) & 3; | |
| 360 | + if (!(insn & (1 << 4))) { | |
| 361 | + shift = (insn >> 7) & 0x1f; | |
| 362 | + if (shift != 0) { | |
| 363 | + if (logic_cc) { | |
| 364 | + gen_shift_T1_im_cc[shiftop](shift); | |
| 365 | + } else { | |
| 366 | + gen_shift_T1_im[shiftop](shift); | |
| 367 | + } | |
| 368 | + } | |
| 369 | + } else { | |
| 370 | + rs = (insn >> 16) & 0xf; | |
| 371 | + gen_movl_T0_reg(s, rs); | |
| 372 | + if (logic_cc) { | |
| 373 | + gen_shift_T1_T0_cc[shiftop](); | |
| 374 | + } else { | |
| 375 | + gen_shift_T1_T0[shiftop](); | |
| 376 | + } | |
| 377 | + } | |
| 378 | + } | |
| 379 | + if (op1 != 0x0f && op1 != 0x0d) { | |
| 380 | + rn = (insn >> 16) & 0xf; | |
| 381 | + gen_movl_T0_reg(s, rn); | |
| 382 | + } | |
| 383 | + rd = (insn >> 12) & 0xf; | |
| 384 | + switch(op1) { | |
| 385 | + case 0x00: | |
| 386 | + gen_op_andl_T0_T1(); | |
| 387 | + gen_movl_reg_T0(s, rd); | |
| 388 | + break; | |
| 389 | + case 0x01: | |
| 390 | + gen_op_xorl_T0_T1(); | |
| 391 | + gen_movl_reg_T0(s, rd); | |
| 392 | + break; | |
| 393 | + case 0x02: | |
| 394 | + if (set_cc) | |
| 395 | + gen_op_subl_T0_T1_cc(); | |
| 396 | + else | |
| 397 | + gen_op_subl_T0_T1(); | |
| 398 | + gen_movl_reg_T0(s, rd); | |
| 399 | + break; | |
| 400 | + case 0x03: | |
| 401 | + if (set_cc) | |
| 402 | + gen_op_rsbl_T0_T1_cc(); | |
| 403 | + else | |
| 404 | + gen_op_rsbl_T0_T1(); | |
| 405 | + gen_movl_reg_T0(s, rd); | |
| 406 | + break; | |
| 407 | + case 0x04: | |
| 408 | + if (set_cc) | |
| 409 | + gen_op_addl_T0_T1_cc(); | |
| 410 | + else | |
| 411 | + gen_op_addl_T0_T1(); | |
| 412 | + gen_movl_reg_T0(s, rd); | |
| 413 | + break; | |
| 414 | + case 0x05: | |
| 415 | + if (set_cc) | |
| 416 | + gen_op_adcl_T0_T1_cc(); | |
| 417 | + else | |
| 418 | + gen_op_adcl_T0_T1(); | |
| 419 | + gen_movl_reg_T0(s, rd); | |
| 420 | + break; | |
| 421 | + case 0x06: | |
| 422 | + if (set_cc) | |
| 423 | + gen_op_sbcl_T0_T1_cc(); | |
| 424 | + else | |
| 425 | + gen_op_sbcl_T0_T1(); | |
| 426 | + gen_movl_reg_T0(s, rd); | |
| 427 | + break; | |
| 428 | + case 0x07: | |
| 429 | + if (set_cc) | |
| 430 | + gen_op_rscl_T0_T1_cc(); | |
| 431 | + else | |
| 432 | + gen_op_rscl_T0_T1(); | |
| 433 | + gen_movl_reg_T0(s, rd); | |
| 434 | + break; | |
| 435 | + case 0x08: | |
| 436 | + if (set_cc) { | |
| 437 | + gen_op_andl_T0_T1(); | |
| 438 | + } | |
| 439 | + break; | |
| 440 | + case 0x09: | |
| 441 | + if (set_cc) { | |
| 442 | + gen_op_xorl_T0_T1(); | |
| 443 | + } | |
| 444 | + break; | |
| 445 | + case 0x0a: | |
| 446 | + if (set_cc) { | |
| 447 | + gen_op_subl_T0_T1_cc(); | |
| 448 | + } | |
| 449 | + break; | |
| 450 | + case 0x0b: | |
| 451 | + if (set_cc) { | |
| 452 | + gen_op_addl_T0_T1_cc(); | |
| 453 | + } | |
| 454 | + break; | |
| 455 | + case 0x0c: | |
| 456 | + gen_op_orl_T0_T1(); | |
| 457 | + gen_movl_reg_T0(s, rd); | |
| 458 | + break; | |
| 459 | + case 0x0d: | |
| 460 | + gen_movl_reg_T1(s, rd); | |
| 461 | + break; | |
| 462 | + case 0x0e: | |
| 463 | + gen_op_bicl_T0_T1(); | |
| 464 | + gen_movl_reg_T0(s, rd); | |
| 465 | + break; | |
| 466 | + default: | |
| 467 | + case 0x0f: | |
| 468 | + gen_op_notl_T1(); | |
| 469 | + gen_movl_reg_T1(s, rd); | |
| 470 | + break; | |
| 471 | + } | |
| 472 | + if (logic_cc) | |
| 473 | + gen_op_logic_cc(); | |
| 474 | + } else { | |
| 475 | + /* other instructions */ | |
| 476 | + op1 = (insn >> 24) & 0xf; | |
| 477 | + switch(op1) { | |
| 478 | + case 0x0: | |
| 479 | + case 0x1: | |
| 480 | + sh = (insn >> 5) & 3; | |
| 481 | + if (sh == 0) { | |
| 482 | + if (op1 == 0x0) { | |
| 483 | + rd = (insn >> 16) & 0xf; | |
| 484 | + rn = (insn >> 12) & 0xf; | |
| 485 | + rs = (insn >> 8) & 0xf; | |
| 486 | + rm = (insn) & 0xf; | |
| 487 | + if (!(insn & (1 << 23))) { | |
| 488 | + /* 32 bit mul */ | |
| 489 | + gen_movl_T0_reg(s, rs); | |
| 490 | + gen_movl_T1_reg(s, rm); | |
| 491 | + gen_op_mul_T0_T1(); | |
| 492 | + if (insn & (1 << 21)) { | |
| 493 | + gen_movl_T1_reg(s, rn); | |
| 494 | + gen_op_addl_T0_T1(); | |
| 495 | + } | |
| 496 | + if (insn & (1 << 20)) | |
| 497 | + gen_op_logic_cc(); | |
| 498 | + gen_movl_reg_T0(s, rd); | |
| 499 | + } else { | |
| 500 | + /* 64 bit mul */ | |
| 501 | + gen_movl_T0_reg(s, rs); | |
| 502 | + gen_movl_T1_reg(s, rm); | |
| 503 | + if (insn & (1 << 22)) | |
| 504 | + gen_op_mull_T0_T1(); | |
| 505 | + else | |
| 506 | + gen_op_imull_T0_T1(); | |
| 507 | + if (insn & (1 << 21)) | |
| 508 | + gen_op_addq_T0_T1(rn, rd); | |
| 509 | + if (insn & (1 << 20)) | |
| 510 | + gen_op_logicq_cc(); | |
| 511 | + gen_movl_reg_T0(s, rn); | |
| 512 | + gen_movl_reg_T1(s, rd); | |
| 513 | + } | |
| 514 | + } else { | |
| 515 | + /* SWP instruction */ | |
| 516 | + rn = (insn >> 16) & 0xf; | |
| 517 | + rd = (insn >> 12) & 0xf; | |
| 518 | + rm = (insn) & 0xf; | |
| 519 | + | |
| 520 | + gen_movl_T0_reg(s, rm); | |
| 521 | + gen_movl_T1_reg(s, rn); | |
| 522 | + if (insn & (1 << 22)) { | |
| 523 | + gen_op_swpb_T0_T1(); | |
| 524 | + } else { | |
| 525 | + gen_op_swpl_T0_T1(); | |
| 526 | + } | |
| 527 | + gen_movl_reg_T0(s, rd); | |
| 528 | + } | |
| 529 | + } else { | |
| 530 | + /* load/store half word */ | |
| 531 | + rn = (insn >> 16) & 0xf; | |
| 532 | + rd = (insn >> 12) & 0xf; | |
| 533 | + gen_movl_T1_reg(s, rn); | |
| 534 | + if (insn & (1 << 25)) | |
| 535 | + gen_add_datah_offset(s, insn); | |
| 536 | + if (insn & (1 << 20)) { | |
| 537 | + /* load */ | |
| 538 | + switch(sh) { | |
| 539 | + case 1: | |
| 540 | + gen_op_lduw_T0_T1(); | |
| 541 | + break; | |
| 542 | + case 2: | |
| 543 | + gen_op_ldsb_T0_T1(); | |
| 544 | + break; | |
| 545 | + default: | |
| 546 | + case 3: | |
| 547 | + gen_op_ldsw_T0_T1(); | |
| 548 | + break; | |
| 549 | + } | |
| 550 | + } else { | |
| 551 | + /* store */ | |
| 552 | + gen_op_stw_T0_T1(); | |
| 553 | + } | |
| 554 | + if (!(insn & (1 << 24))) | |
| 555 | + gen_add_datah_offset(s, insn); | |
| 556 | + if (insn & (1 << 21)) | |
| 557 | + gen_movl_reg_T1(s, rn); | |
| 558 | + } | |
| 559 | + break; | |
| 560 | + case 0x4: | |
| 561 | + case 0x5: | |
| 562 | + case 0x6: | |
| 563 | + case 0x7: | |
| 564 | + /* load/store byte/word */ | |
| 565 | + rn = (insn >> 16) & 0xf; | |
| 566 | + rd = (insn >> 12) & 0xf; | |
| 567 | + gen_movl_T1_reg(s, rn); | |
| 568 | + if (insn & (1 << 24)) | |
| 569 | + gen_add_data_offset(s, insn); | |
| 570 | + if (insn & (1 << 20)) { | |
| 571 | + /* load */ | |
| 572 | + if (insn & (1 << 22)) | |
| 573 | + gen_op_ldub_T0_T1(); | |
| 574 | + else | |
| 575 | + gen_op_ldl_T0_T1(); | |
| 576 | + gen_movl_reg_T0(s, rd); | |
| 577 | + } else { | |
| 578 | + /* store */ | |
| 579 | + gen_movl_T0_reg(s, rd); | |
| 580 | + if (insn & (1 << 22)) | |
| 581 | + gen_op_stb_T0_T1(); | |
| 582 | + else | |
| 583 | + gen_op_stl_T0_T1(); | |
| 584 | + } | |
| 585 | + if (!(insn & (1 << 24))) | |
| 586 | + gen_add_data_offset(s, insn); | |
| 587 | + if (insn & (1 << 21)) | |
| 588 | + gen_movl_reg_T1(s, rn); | |
| 589 | + break; | |
| 590 | + case 0x08: | |
| 591 | + case 0x09: | |
| 592 | + /* load/store multiple words */ | |
| 593 | + if (insn & (1 << 22)) | |
| 594 | + goto illegal_op; /* only usable in supervisor mode */ | |
| 595 | + rn = (insn >> 16) & 0xf; | |
| 596 | + gen_movl_T1_reg(s, rn); | |
| 597 | + val = 4; | |
| 598 | + if (!(insn & (1 << 23))) | |
| 599 | + val = -val; | |
| 600 | + for(i=0;i<16;i++) { | |
| 601 | + if (insn & (1 << i)) { | |
| 602 | + if (insn & (1 << 24)) | |
| 603 | + gen_op_addl_T1_im(val); | |
| 604 | + if (insn & (1 << 20)) { | |
| 605 | + /* load */ | |
| 606 | + gen_op_ldl_T0_T1(); | |
| 607 | + gen_movl_reg_T0(s, i); | |
| 608 | + } else { | |
| 609 | + /* store */ | |
| 610 | + gen_movl_T0_reg(s, i); | |
| 611 | + gen_op_stl_T0_T1(); | |
| 612 | + } | |
| 613 | + if (!(insn & (1 << 24))) | |
| 614 | + gen_op_addl_T1_im(val); | |
| 615 | + } | |
| 616 | + } | |
| 617 | + if (insn & (1 << 21)) | |
| 618 | + gen_movl_reg_T1(s, rn); | |
| 619 | + break; | |
| 620 | + case 0xa: | |
| 621 | + case 0xb: | |
| 622 | + { | |
| 623 | + int offset; | |
| 624 | + | |
| 625 | + /* branch (and link) */ | |
| 626 | + val = (int)s->pc; | |
| 627 | + if (insn & (1 << 24)) { | |
| 628 | + gen_op_movl_T0_im(val); | |
| 629 | + gen_op_movl_reg_TN[0][14](); | |
| 630 | + } | |
| 631 | + offset = (((int)insn << 8) >> 8); | |
| 632 | + val += (offset << 2) + 4; | |
| 633 | + gen_op_jmp((long)s->tb, val); | |
| 634 | + s->is_jmp = DISAS_TB_JUMP; | |
| 635 | + } | |
| 636 | + break; | |
| 637 | + case 0xf: | |
| 638 | + /* swi */ | |
| 639 | + gen_op_movl_T0_im((long)s->pc); | |
| 640 | + gen_op_movl_reg_TN[0][15](); | |
| 641 | + gen_op_swi(); | |
| 642 | + s->is_jmp = DISAS_JUMP; | |
| 643 | + break; | |
| 644 | + default: | |
| 645 | + illegal_op: | |
| 646 | + gen_op_movl_T0_im((long)s->pc - 4); | |
| 647 | + gen_op_movl_reg_TN[0][15](); | |
| 648 | + gen_op_undef_insn(); | |
| 649 | + s->is_jmp = DISAS_JUMP; | |
| 650 | + break; | |
| 651 | + } | |
| 652 | + } | |
| 653 | +} | |
| 654 | + | |
| 655 | +/* generate intermediate code in gen_opc_buf and gen_opparam_buf for | |
| 656 | + basic block 'tb'. If search_pc is TRUE, also generate PC | |
| 657 | + information for each intermediate instruction. */ | |
| 658 | +int gen_intermediate_code(TranslationBlock *tb, int search_pc) | |
| 659 | +{ | |
| 660 | + DisasContext dc1, *dc = &dc1; | |
| 661 | + uint16_t *gen_opc_end; | |
| 662 | + int j, lj; | |
| 663 | + uint8_t *pc_start; | |
| 664 | + | |
| 665 | + /* generate intermediate code */ | |
| 666 | + pc_start = (uint8_t *)tb->pc; | |
| 667 | + | |
| 668 | + dc->tb = tb; | |
| 669 | + | |
| 670 | + gen_opc_ptr = gen_opc_buf; | |
| 671 | + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; | |
| 672 | + gen_opparam_ptr = gen_opparam_buf; | |
| 673 | + | |
| 674 | + dc->is_jmp = DISAS_NEXT; | |
| 675 | + dc->pc = pc_start; | |
| 676 | + lj = -1; | |
| 677 | + do { | |
| 678 | + if (search_pc) { | |
| 679 | + j = gen_opc_ptr - gen_opc_buf; | |
| 680 | + if (lj < j) { | |
| 681 | + lj++; | |
| 682 | + while (lj < j) | |
| 683 | + gen_opc_instr_start[lj++] = 0; | |
| 684 | + gen_opc_pc[lj] = (uint32_t)dc->pc; | |
| 685 | + gen_opc_instr_start[lj] = 1; | |
| 686 | + } | |
| 687 | + } | |
| 688 | + disas_arm_insn(dc); | |
| 689 | + } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && | |
| 690 | + (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); | |
| 691 | + /* we must store the eflags state if it is not already done */ | |
| 692 | + if (dc->is_jmp != DISAS_TB_JUMP && | |
| 693 | + dc->is_jmp != DISAS_JUMP) { | |
| 694 | + gen_op_movl_T0_im((long)dc->pc - 4); | |
| 695 | + gen_op_movl_reg_TN[0][15](); | |
| 696 | + } | |
| 697 | + if (dc->is_jmp != DISAS_TB_JUMP) { | |
| 698 | + /* indicate that the hash table must be used to find the next TB */ | |
| 699 | + gen_op_movl_T0_0(); | |
| 700 | + } | |
| 701 | + *gen_opc_ptr = INDEX_op_end; | |
| 702 | + | |
| 703 | +#ifdef DEBUG_DISAS | |
| 704 | + if (loglevel) { | |
| 705 | + fprintf(logfile, "----------------\n"); | |
| 706 | + fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); | |
| 707 | + disas(logfile, pc_start, dc->pc - pc_start, 0, 0); | |
| 708 | + fprintf(logfile, "\n"); | |
| 709 | + | |
| 710 | + fprintf(logfile, "OP:\n"); | |
| 711 | + dump_ops(gen_opc_buf, gen_opparam_buf); | |
| 712 | + fprintf(logfile, "\n"); | |
| 713 | + } | |
| 714 | +#endif | |
| 715 | + if (!search_pc) | |
| 716 | + tb->size = dc->pc - pc_start; | |
| 717 | + return 0; | |
| 718 | +} | |
| 719 | + | |
| 720 | +CPUARMState *cpu_arm_init(void) | |
| 721 | +{ | |
| 722 | + CPUARMState *env; | |
| 723 | + | |
| 724 | + cpu_exec_init(); | |
| 725 | + | |
| 726 | + env = malloc(sizeof(CPUARMState)); | |
| 727 | + if (!env) | |
| 728 | + return NULL; | |
| 729 | + memset(env, 0, sizeof(CPUARMState)); | |
| 730 | + return env; | |
| 731 | +} | |
| 732 | + | |
| 733 | +void cpu_arm_close(CPUARMState *env) | |
| 734 | +{ | |
| 735 | + free(env); | |
| 736 | +} | |
| 737 | + | |
| 738 | +void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags) | |
| 739 | +{ | |
| 740 | + int i; | |
| 741 | + | |
| 742 | + for(i=0;i<16;i++) { | |
| 743 | + fprintf(f, "R%02d=%08x", i, env->regs[i]); | |
| 744 | + if ((i % 4) == 3) | |
| 745 | + fprintf(f, "\n"); | |
| 746 | + else | |
| 747 | + fprintf(f, " "); | |
| 748 | + } | |
| 749 | + fprintf(f, "CPSR=%08x", env->cpsr); | |
| 750 | +} | ... | ... |