Commit 5898e816840dd7cb2492c4cce85525e7383f8def

Authored by bellard
1 parent 394411ac

ARM emulation support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@232 c046a42c-6fe2-441c-8c8c-71466251a162
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 +}
... ...