qemu/target/moxie/translate.c
<<
>>
Prefs
   1/*
   2 *  Moxie emulation for qemu: main translation routines.
   3 *
   4 *  Copyright (c) 2009, 2013 Anthony Green
   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 License
   8 * as published by the Free Software Foundation; either version 2 of
   9 * the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful, but
  12 * 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 General Public License
  17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20/* For information on the Moxie architecture, see
  21 *    http://moxielogic.org/wiki
  22 */
  23
  24#include "qemu/osdep.h"
  25
  26#include "cpu.h"
  27#include "exec/exec-all.h"
  28#include "disas/disas.h"
  29#include "tcg-op.h"
  30#include "exec/cpu_ldst.h"
  31
  32#include "exec/helper-proto.h"
  33#include "exec/helper-gen.h"
  34#include "exec/log.h"
  35
  36/* This is the state at translation time.  */
  37typedef struct DisasContext {
  38    struct TranslationBlock *tb;
  39    target_ulong pc, saved_pc;
  40    uint32_t opcode;
  41    uint32_t fp_status;
  42    /* Routine used to access memory */
  43    int memidx;
  44    int bstate;
  45    target_ulong btarget;
  46    int singlestep_enabled;
  47} DisasContext;
  48
  49enum {
  50    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an
  51                      * exception condition */
  52    BS_STOP     = 1, /* We want to stop translation for any reason */
  53    BS_BRANCH   = 2, /* We reached a branch condition     */
  54    BS_EXCP     = 3, /* We reached an exception condition */
  55};
  56
  57static TCGv cpu_pc;
  58static TCGv cpu_gregs[16];
  59static TCGv cc_a, cc_b;
  60
  61#include "exec/gen-icount.h"
  62
  63#define REG(x) (cpu_gregs[x])
  64
  65/* Extract the signed 10-bit offset from a 16-bit branch
  66   instruction.  */
  67static int extract_branch_offset(int opcode)
  68{
  69  return (((signed short)((opcode & ((1 << 10) - 1)) << 6)) >> 6) << 1;
  70}
  71
  72void moxie_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
  73                          int flags)
  74{
  75    MoxieCPU *cpu = MOXIE_CPU(cs);
  76    CPUMoxieState *env = &cpu->env;
  77    int i;
  78    cpu_fprintf(f, "pc=0x%08x\n", env->pc);
  79    cpu_fprintf(f, "$fp=0x%08x $sp=0x%08x $r0=0x%08x $r1=0x%08x\n",
  80                env->gregs[0], env->gregs[1], env->gregs[2], env->gregs[3]);
  81    for (i = 4; i < 16; i += 4) {
  82        cpu_fprintf(f, "$r%d=0x%08x $r%d=0x%08x $r%d=0x%08x $r%d=0x%08x\n",
  83                    i-2, env->gregs[i], i-1, env->gregs[i + 1],
  84                    i, env->gregs[i + 2], i+1, env->gregs[i + 3]);
  85    }
  86    for (i = 4; i < 16; i += 4) {
  87        cpu_fprintf(f, "sr%d=0x%08x sr%d=0x%08x sr%d=0x%08x sr%d=0x%08x\n",
  88                    i-2, env->sregs[i], i-1, env->sregs[i + 1],
  89                    i, env->sregs[i + 2], i+1, env->sregs[i + 3]);
  90    }
  91}
  92
  93void moxie_translate_init(void)
  94{
  95    int i;
  96    static const char * const gregnames[16] = {
  97        "$fp", "$sp", "$r0", "$r1",
  98        "$r2", "$r3", "$r4", "$r5",
  99        "$r6", "$r7", "$r8", "$r9",
 100        "$r10", "$r11", "$r12", "$r13"
 101    };
 102
 103    cpu_pc = tcg_global_mem_new_i32(cpu_env,
 104                                    offsetof(CPUMoxieState, pc), "$pc");
 105    for (i = 0; i < 16; i++)
 106        cpu_gregs[i] = tcg_global_mem_new_i32(cpu_env,
 107                                              offsetof(CPUMoxieState, gregs[i]),
 108                                              gregnames[i]);
 109
 110    cc_a = tcg_global_mem_new_i32(cpu_env,
 111                                  offsetof(CPUMoxieState, cc_a), "cc_a");
 112    cc_b = tcg_global_mem_new_i32(cpu_env,
 113                                  offsetof(CPUMoxieState, cc_b), "cc_b");
 114}
 115
 116static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
 117{
 118    if (unlikely(ctx->singlestep_enabled)) {
 119        return false;
 120    }
 121
 122#ifndef CONFIG_USER_ONLY
 123    return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
 124#else
 125    return true;
 126#endif
 127}
 128
 129static inline void gen_goto_tb(CPUMoxieState *env, DisasContext *ctx,
 130                               int n, target_ulong dest)
 131{
 132    if (use_goto_tb(ctx, dest)) {
 133        tcg_gen_goto_tb(n);
 134        tcg_gen_movi_i32(cpu_pc, dest);
 135        tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
 136    } else {
 137        tcg_gen_movi_i32(cpu_pc, dest);
 138        if (ctx->singlestep_enabled) {
 139            gen_helper_debug(cpu_env);
 140        }
 141        tcg_gen_exit_tb(0);
 142    }
 143}
 144
 145static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
 146{
 147    CPUMoxieState *env = &cpu->env;
 148
 149    /* Local cache for the instruction opcode.  */
 150    int opcode;
 151    /* Set the default instruction length.  */
 152    int length = 2;
 153
 154    /* Examine the 16-bit opcode.  */
 155    opcode = ctx->opcode;
 156
 157    /* Decode instruction.  */
 158    if (opcode & (1 << 15)) {
 159        if (opcode & (1 << 14)) {
 160            /* This is a Form 3 instruction.  */
 161            int inst = (opcode >> 10 & 0xf);
 162
 163#define BRANCH(cond)                                                         \
 164    do {                                                                     \
 165        TCGLabel *l1 = gen_new_label();                                      \
 166        tcg_gen_brcond_i32(cond, cc_a, cc_b, l1);                            \
 167        gen_goto_tb(env, ctx, 1, ctx->pc+2);                                 \
 168        gen_set_label(l1);                                                   \
 169        gen_goto_tb(env, ctx, 0, extract_branch_offset(opcode) + ctx->pc+2); \
 170        ctx->bstate = BS_BRANCH;                                             \
 171    } while (0)
 172
 173            switch (inst) {
 174            case 0x00: /* beq */
 175                BRANCH(TCG_COND_EQ);
 176                break;
 177            case 0x01: /* bne */
 178                BRANCH(TCG_COND_NE);
 179                break;
 180            case 0x02: /* blt */
 181                BRANCH(TCG_COND_LT);
 182                break;
 183            case 0x03: /* bgt */
 184                BRANCH(TCG_COND_GT);
 185                break;
 186            case 0x04: /* bltu */
 187                BRANCH(TCG_COND_LTU);
 188                break;
 189            case 0x05: /* bgtu */
 190                BRANCH(TCG_COND_GTU);
 191                break;
 192            case 0x06: /* bge */
 193                BRANCH(TCG_COND_GE);
 194                break;
 195            case 0x07: /* ble */
 196                BRANCH(TCG_COND_LE);
 197                break;
 198            case 0x08: /* bgeu */
 199                BRANCH(TCG_COND_GEU);
 200                break;
 201            case 0x09: /* bleu */
 202                BRANCH(TCG_COND_LEU);
 203                break;
 204            default:
 205                {
 206                    TCGv temp = tcg_temp_new_i32();
 207                    tcg_gen_movi_i32(cpu_pc, ctx->pc);
 208                    tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
 209                    gen_helper_raise_exception(cpu_env, temp);
 210                    tcg_temp_free_i32(temp);
 211                }
 212                break;
 213            }
 214        } else {
 215            /* This is a Form 2 instruction.  */
 216            int inst = (opcode >> 12 & 0x3);
 217            switch (inst) {
 218            case 0x00: /* inc */
 219                {
 220                    int a = (opcode >> 8) & 0xf;
 221                    unsigned int v = (opcode & 0xff);
 222                    tcg_gen_addi_i32(REG(a), REG(a), v);
 223                }
 224                break;
 225            case 0x01: /* dec */
 226                {
 227                    int a = (opcode >> 8) & 0xf;
 228                    unsigned int v = (opcode & 0xff);
 229                    tcg_gen_subi_i32(REG(a), REG(a), v);
 230                }
 231                break;
 232            case 0x02: /* gsr */
 233                {
 234                    int a = (opcode >> 8) & 0xf;
 235                    unsigned v = (opcode & 0xff);
 236                    tcg_gen_ld_i32(REG(a), cpu_env,
 237                                   offsetof(CPUMoxieState, sregs[v]));
 238                }
 239                break;
 240            case 0x03: /* ssr */
 241                {
 242                    int a = (opcode >> 8) & 0xf;
 243                    unsigned v = (opcode & 0xff);
 244                    tcg_gen_st_i32(REG(a), cpu_env,
 245                                   offsetof(CPUMoxieState, sregs[v]));
 246                }
 247                break;
 248            default:
 249                {
 250                    TCGv temp = tcg_temp_new_i32();
 251                    tcg_gen_movi_i32(cpu_pc, ctx->pc);
 252                    tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
 253                    gen_helper_raise_exception(cpu_env, temp);
 254                    tcg_temp_free_i32(temp);
 255                }
 256                break;
 257            }
 258        }
 259    } else {
 260        /* This is a Form 1 instruction.  */
 261        int inst = opcode >> 8;
 262        switch (inst) {
 263        case 0x00: /* nop */
 264            break;
 265        case 0x01: /* ldi.l (immediate) */
 266            {
 267                int reg = (opcode >> 4) & 0xf;
 268                int val = cpu_ldl_code(env, ctx->pc+2);
 269                tcg_gen_movi_i32(REG(reg), val);
 270                length = 6;
 271            }
 272            break;
 273        case 0x02: /* mov (register-to-register) */
 274            {
 275                int dest  = (opcode >> 4) & 0xf;
 276                int src = opcode & 0xf;
 277                tcg_gen_mov_i32(REG(dest), REG(src));
 278            }
 279            break;
 280        case 0x03: /* jsra */
 281            {
 282                TCGv t1 = tcg_temp_new_i32();
 283                TCGv t2 = tcg_temp_new_i32();
 284
 285                tcg_gen_movi_i32(t1, ctx->pc + 6);
 286
 287                /* Make space for the static chain and return address.  */
 288                tcg_gen_subi_i32(t2, REG(1), 8);
 289                tcg_gen_mov_i32(REG(1), t2);
 290                tcg_gen_qemu_st32(t1, REG(1), ctx->memidx);
 291
 292                /* Push the current frame pointer.  */
 293                tcg_gen_subi_i32(t2, REG(1), 4);
 294                tcg_gen_mov_i32(REG(1), t2);
 295                tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx);
 296
 297                /* Set the pc and $fp.  */
 298                tcg_gen_mov_i32(REG(0), REG(1));
 299
 300                gen_goto_tb(env, ctx, 0, cpu_ldl_code(env, ctx->pc+2));
 301
 302                tcg_temp_free_i32(t1);
 303                tcg_temp_free_i32(t2);
 304
 305                ctx->bstate = BS_BRANCH;
 306                length = 6;
 307            }
 308            break;
 309        case 0x04: /* ret */
 310            {
 311                TCGv t1 = tcg_temp_new_i32();
 312
 313                /* The new $sp is the old $fp.  */
 314                tcg_gen_mov_i32(REG(1), REG(0));
 315
 316                /* Pop the frame pointer.  */
 317                tcg_gen_qemu_ld32u(REG(0), REG(1), ctx->memidx);
 318                tcg_gen_addi_i32(t1, REG(1), 4);
 319                tcg_gen_mov_i32(REG(1), t1);
 320
 321
 322                /* Pop the return address and skip over the static chain
 323                   slot.  */
 324                tcg_gen_qemu_ld32u(cpu_pc, REG(1), ctx->memidx);
 325                tcg_gen_addi_i32(t1, REG(1), 8);
 326                tcg_gen_mov_i32(REG(1), t1);
 327
 328                tcg_temp_free_i32(t1);
 329
 330                /* Jump... */
 331                tcg_gen_exit_tb(0);
 332
 333                ctx->bstate = BS_BRANCH;
 334            }
 335            break;
 336        case 0x05: /* add.l */
 337            {
 338                int a = (opcode >> 4) & 0xf;
 339                int b = opcode & 0xf;
 340
 341                tcg_gen_add_i32(REG(a), REG(a), REG(b));
 342            }
 343            break;
 344        case 0x06: /* push */
 345            {
 346                int a = (opcode >> 4) & 0xf;
 347                int b = opcode & 0xf;
 348
 349                TCGv t1 = tcg_temp_new_i32();
 350                tcg_gen_subi_i32(t1, REG(a), 4);
 351                tcg_gen_mov_i32(REG(a), t1);
 352                tcg_gen_qemu_st32(REG(b), REG(a), ctx->memidx);
 353                tcg_temp_free_i32(t1);
 354            }
 355            break;
 356        case 0x07: /* pop */
 357            {
 358                int a = (opcode >> 4) & 0xf;
 359                int b = opcode & 0xf;
 360                TCGv t1 = tcg_temp_new_i32();
 361
 362                tcg_gen_qemu_ld32u(REG(b), REG(a), ctx->memidx);
 363                tcg_gen_addi_i32(t1, REG(a), 4);
 364                tcg_gen_mov_i32(REG(a), t1);
 365                tcg_temp_free_i32(t1);
 366            }
 367            break;
 368        case 0x08: /* lda.l */
 369            {
 370                int reg = (opcode >> 4) & 0xf;
 371
 372                TCGv ptr = tcg_temp_new_i32();
 373                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
 374                tcg_gen_qemu_ld32u(REG(reg), ptr, ctx->memidx);
 375                tcg_temp_free_i32(ptr);
 376
 377                length = 6;
 378            }
 379            break;
 380        case 0x09: /* sta.l */
 381            {
 382                int val = (opcode >> 4) & 0xf;
 383
 384                TCGv ptr = tcg_temp_new_i32();
 385                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
 386                tcg_gen_qemu_st32(REG(val), ptr, ctx->memidx);
 387                tcg_temp_free_i32(ptr);
 388
 389                length = 6;
 390            }
 391            break;
 392        case 0x0a: /* ld.l (register indirect) */
 393            {
 394                int src  = opcode & 0xf;
 395                int dest = (opcode >> 4) & 0xf;
 396
 397                tcg_gen_qemu_ld32u(REG(dest), REG(src), ctx->memidx);
 398            }
 399            break;
 400        case 0x0b: /* st.l */
 401            {
 402                int dest = (opcode >> 4) & 0xf;
 403                int val  = opcode & 0xf;
 404
 405                tcg_gen_qemu_st32(REG(val), REG(dest), ctx->memidx);
 406            }
 407            break;
 408        case 0x0c: /* ldo.l */
 409            {
 410                int a = (opcode >> 4) & 0xf;
 411                int b = opcode & 0xf;
 412
 413                TCGv t1 = tcg_temp_new_i32();
 414                TCGv t2 = tcg_temp_new_i32();
 415                tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
 416                tcg_gen_qemu_ld32u(t2, t1, ctx->memidx);
 417                tcg_gen_mov_i32(REG(a), t2);
 418
 419                tcg_temp_free_i32(t1);
 420                tcg_temp_free_i32(t2);
 421
 422                length = 6;
 423            }
 424            break;
 425        case 0x0d: /* sto.l */
 426            {
 427                int a = (opcode >> 4) & 0xf;
 428                int b = opcode & 0xf;
 429
 430                TCGv t1 = tcg_temp_new_i32();
 431                TCGv t2 = tcg_temp_new_i32();
 432                tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
 433                tcg_gen_qemu_st32(REG(b), t1, ctx->memidx);
 434
 435                tcg_temp_free_i32(t1);
 436                tcg_temp_free_i32(t2);
 437
 438                length = 6;
 439            }
 440            break;
 441        case 0x0e: /* cmp */
 442            {
 443                int a  = (opcode >> 4) & 0xf;
 444                int b  = opcode & 0xf;
 445
 446                tcg_gen_mov_i32(cc_a, REG(a));
 447                tcg_gen_mov_i32(cc_b, REG(b));
 448            }
 449            break;
 450        case 0x19: /* jsr */
 451            {
 452                int fnreg = (opcode >> 4) & 0xf;
 453
 454                /* Load the stack pointer into T0.  */
 455                TCGv t1 = tcg_temp_new_i32();
 456                TCGv t2 = tcg_temp_new_i32();
 457
 458                tcg_gen_movi_i32(t1, ctx->pc+2);
 459
 460                /* Make space for the static chain and return address.  */
 461                tcg_gen_subi_i32(t2, REG(1), 8);
 462                tcg_gen_mov_i32(REG(1), t2);
 463                tcg_gen_qemu_st32(t1, REG(1), ctx->memidx);
 464
 465                /* Push the current frame pointer.  */
 466                tcg_gen_subi_i32(t2, REG(1), 4);
 467                tcg_gen_mov_i32(REG(1), t2);
 468                tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx);
 469
 470                /* Set the pc and $fp.  */
 471                tcg_gen_mov_i32(REG(0), REG(1));
 472                tcg_gen_mov_i32(cpu_pc, REG(fnreg));
 473                tcg_temp_free_i32(t1);
 474                tcg_temp_free_i32(t2);
 475                tcg_gen_exit_tb(0);
 476                ctx->bstate = BS_BRANCH;
 477            }
 478            break;
 479        case 0x1a: /* jmpa */
 480            {
 481                tcg_gen_movi_i32(cpu_pc, cpu_ldl_code(env, ctx->pc+2));
 482                tcg_gen_exit_tb(0);
 483                ctx->bstate = BS_BRANCH;
 484                length = 6;
 485            }
 486            break;
 487        case 0x1b: /* ldi.b (immediate) */
 488            {
 489                int reg = (opcode >> 4) & 0xf;
 490                int val = cpu_ldl_code(env, ctx->pc+2);
 491                tcg_gen_movi_i32(REG(reg), val);
 492                length = 6;
 493            }
 494            break;
 495        case 0x1c: /* ld.b (register indirect) */
 496            {
 497                int src  = opcode & 0xf;
 498                int dest = (opcode >> 4) & 0xf;
 499
 500                tcg_gen_qemu_ld8u(REG(dest), REG(src), ctx->memidx);
 501            }
 502            break;
 503        case 0x1d: /* lda.b */
 504            {
 505                int reg = (opcode >> 4) & 0xf;
 506
 507                TCGv ptr = tcg_temp_new_i32();
 508                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
 509                tcg_gen_qemu_ld8u(REG(reg), ptr, ctx->memidx);
 510                tcg_temp_free_i32(ptr);
 511
 512                length = 6;
 513            }
 514            break;
 515        case 0x1e: /* st.b */
 516            {
 517                int dest = (opcode >> 4) & 0xf;
 518                int val  = opcode & 0xf;
 519
 520                tcg_gen_qemu_st8(REG(val), REG(dest), ctx->memidx);
 521            }
 522            break;
 523        case 0x1f: /* sta.b */
 524            {
 525                int val = (opcode >> 4) & 0xf;
 526
 527                TCGv ptr = tcg_temp_new_i32();
 528                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
 529                tcg_gen_qemu_st8(REG(val), ptr, ctx->memidx);
 530                tcg_temp_free_i32(ptr);
 531
 532                length = 6;
 533            }
 534            break;
 535        case 0x20: /* ldi.s (immediate) */
 536            {
 537                int reg = (opcode >> 4) & 0xf;
 538                int val = cpu_ldl_code(env, ctx->pc+2);
 539                tcg_gen_movi_i32(REG(reg), val);
 540                length = 6;
 541            }
 542            break;
 543        case 0x21: /* ld.s (register indirect) */
 544            {
 545                int src  = opcode & 0xf;
 546                int dest = (opcode >> 4) & 0xf;
 547
 548                tcg_gen_qemu_ld16u(REG(dest), REG(src), ctx->memidx);
 549            }
 550            break;
 551        case 0x22: /* lda.s */
 552            {
 553                int reg = (opcode >> 4) & 0xf;
 554
 555                TCGv ptr = tcg_temp_new_i32();
 556                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
 557                tcg_gen_qemu_ld16u(REG(reg), ptr, ctx->memidx);
 558                tcg_temp_free_i32(ptr);
 559
 560                length = 6;
 561            }
 562            break;
 563        case 0x23: /* st.s */
 564            {
 565                int dest = (opcode >> 4) & 0xf;
 566                int val  = opcode & 0xf;
 567
 568                tcg_gen_qemu_st16(REG(val), REG(dest), ctx->memidx);
 569            }
 570            break;
 571        case 0x24: /* sta.s */
 572            {
 573                int val = (opcode >> 4) & 0xf;
 574
 575                TCGv ptr = tcg_temp_new_i32();
 576                tcg_gen_movi_i32(ptr, cpu_ldl_code(env, ctx->pc+2));
 577                tcg_gen_qemu_st16(REG(val), ptr, ctx->memidx);
 578                tcg_temp_free_i32(ptr);
 579
 580                length = 6;
 581            }
 582            break;
 583        case 0x25: /* jmp */
 584            {
 585                int reg = (opcode >> 4) & 0xf;
 586                tcg_gen_mov_i32(cpu_pc, REG(reg));
 587                tcg_gen_exit_tb(0);
 588                ctx->bstate = BS_BRANCH;
 589            }
 590            break;
 591        case 0x26: /* and */
 592            {
 593                int a = (opcode >> 4) & 0xf;
 594                int b = opcode & 0xf;
 595
 596                tcg_gen_and_i32(REG(a), REG(a), REG(b));
 597            }
 598            break;
 599        case 0x27: /* lshr */
 600            {
 601                int a = (opcode >> 4) & 0xf;
 602                int b = opcode & 0xf;
 603
 604                TCGv sv = tcg_temp_new_i32();
 605                tcg_gen_andi_i32(sv, REG(b), 0x1f);
 606                tcg_gen_shr_i32(REG(a), REG(a), sv);
 607                tcg_temp_free_i32(sv);
 608            }
 609            break;
 610        case 0x28: /* ashl */
 611            {
 612                int a = (opcode >> 4) & 0xf;
 613                int b = opcode & 0xf;
 614
 615                TCGv sv = tcg_temp_new_i32();
 616                tcg_gen_andi_i32(sv, REG(b), 0x1f);
 617                tcg_gen_shl_i32(REG(a), REG(a), sv);
 618                tcg_temp_free_i32(sv);
 619            }
 620            break;
 621        case 0x29: /* sub.l */
 622            {
 623                int a = (opcode >> 4) & 0xf;
 624                int b = opcode & 0xf;
 625
 626                tcg_gen_sub_i32(REG(a), REG(a), REG(b));
 627            }
 628            break;
 629        case 0x2a: /* neg */
 630            {
 631                int a = (opcode >> 4) & 0xf;
 632                int b = opcode & 0xf;
 633
 634                tcg_gen_neg_i32(REG(a), REG(b));
 635            }
 636            break;
 637        case 0x2b: /* or */
 638            {
 639                int a = (opcode >> 4) & 0xf;
 640                int b = opcode & 0xf;
 641
 642                tcg_gen_or_i32(REG(a), REG(a), REG(b));
 643            }
 644            break;
 645        case 0x2c: /* not */
 646            {
 647                int a = (opcode >> 4) & 0xf;
 648                int b = opcode & 0xf;
 649
 650                tcg_gen_not_i32(REG(a), REG(b));
 651            }
 652            break;
 653        case 0x2d: /* ashr */
 654            {
 655                int a = (opcode >> 4) & 0xf;
 656                int b = opcode & 0xf;
 657
 658                TCGv sv = tcg_temp_new_i32();
 659                tcg_gen_andi_i32(sv, REG(b), 0x1f);
 660                tcg_gen_sar_i32(REG(a), REG(a), sv);
 661                tcg_temp_free_i32(sv);
 662            }
 663            break;
 664        case 0x2e: /* xor */
 665            {
 666                int a = (opcode >> 4) & 0xf;
 667                int b = opcode & 0xf;
 668
 669                tcg_gen_xor_i32(REG(a), REG(a), REG(b));
 670            }
 671            break;
 672        case 0x2f: /* mul.l */
 673            {
 674                int a = (opcode >> 4) & 0xf;
 675                int b = opcode & 0xf;
 676
 677                tcg_gen_mul_i32(REG(a), REG(a), REG(b));
 678            }
 679            break;
 680        case 0x30: /* swi */
 681            {
 682                int val = cpu_ldl_code(env, ctx->pc+2);
 683
 684                TCGv temp = tcg_temp_new_i32();
 685                tcg_gen_movi_i32(temp, val);
 686                tcg_gen_st_i32(temp, cpu_env,
 687                               offsetof(CPUMoxieState, sregs[3]));
 688                tcg_gen_movi_i32(cpu_pc, ctx->pc);
 689                tcg_gen_movi_i32(temp, MOXIE_EX_SWI);
 690                gen_helper_raise_exception(cpu_env, temp);
 691                tcg_temp_free_i32(temp);
 692
 693                length = 6;
 694            }
 695            break;
 696        case 0x31: /* div.l */
 697            {
 698                int a = (opcode >> 4) & 0xf;
 699                int b = opcode & 0xf;
 700                tcg_gen_movi_i32(cpu_pc, ctx->pc);
 701                gen_helper_div(REG(a), cpu_env, REG(a), REG(b));
 702            }
 703            break;
 704        case 0x32: /* udiv.l */
 705            {
 706                int a = (opcode >> 4) & 0xf;
 707                int b = opcode & 0xf;
 708                tcg_gen_movi_i32(cpu_pc, ctx->pc);
 709                gen_helper_udiv(REG(a), cpu_env, REG(a), REG(b));
 710            }
 711            break;
 712        case 0x33: /* mod.l */
 713            {
 714                int a = (opcode >> 4) & 0xf;
 715                int b = opcode & 0xf;
 716                tcg_gen_rem_i32(REG(a), REG(a), REG(b));
 717            }
 718            break;
 719        case 0x34: /* umod.l */
 720            {
 721                int a = (opcode >> 4) & 0xf;
 722                int b = opcode & 0xf;
 723                tcg_gen_remu_i32(REG(a), REG(a), REG(b));
 724            }
 725            break;
 726        case 0x35: /* brk */
 727            {
 728                TCGv temp = tcg_temp_new_i32();
 729                tcg_gen_movi_i32(cpu_pc, ctx->pc);
 730                tcg_gen_movi_i32(temp, MOXIE_EX_BREAK);
 731                gen_helper_raise_exception(cpu_env, temp);
 732                tcg_temp_free_i32(temp);
 733            }
 734            break;
 735        case 0x36: /* ldo.b */
 736            {
 737                int a = (opcode >> 4) & 0xf;
 738                int b = opcode & 0xf;
 739
 740                TCGv t1 = tcg_temp_new_i32();
 741                TCGv t2 = tcg_temp_new_i32();
 742                tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
 743                tcg_gen_qemu_ld8u(t2, t1, ctx->memidx);
 744                tcg_gen_mov_i32(REG(a), t2);
 745
 746                tcg_temp_free_i32(t1);
 747                tcg_temp_free_i32(t2);
 748
 749                length = 6;
 750            }
 751            break;
 752        case 0x37: /* sto.b */
 753            {
 754                int a = (opcode >> 4) & 0xf;
 755                int b = opcode & 0xf;
 756
 757                TCGv t1 = tcg_temp_new_i32();
 758                TCGv t2 = tcg_temp_new_i32();
 759                tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
 760                tcg_gen_qemu_st8(REG(b), t1, ctx->memidx);
 761
 762                tcg_temp_free_i32(t1);
 763                tcg_temp_free_i32(t2);
 764
 765                length = 6;
 766            }
 767            break;
 768        case 0x38: /* ldo.s */
 769            {
 770                int a = (opcode >> 4) & 0xf;
 771                int b = opcode & 0xf;
 772
 773                TCGv t1 = tcg_temp_new_i32();
 774                TCGv t2 = tcg_temp_new_i32();
 775                tcg_gen_addi_i32(t1, REG(b), cpu_ldl_code(env, ctx->pc+2));
 776                tcg_gen_qemu_ld16u(t2, t1, ctx->memidx);
 777                tcg_gen_mov_i32(REG(a), t2);
 778
 779                tcg_temp_free_i32(t1);
 780                tcg_temp_free_i32(t2);
 781
 782                length = 6;
 783            }
 784            break;
 785        case 0x39: /* sto.s */
 786            {
 787                int a = (opcode >> 4) & 0xf;
 788                int b = opcode & 0xf;
 789
 790                TCGv t1 = tcg_temp_new_i32();
 791                TCGv t2 = tcg_temp_new_i32();
 792                tcg_gen_addi_i32(t1, REG(a), cpu_ldl_code(env, ctx->pc+2));
 793                tcg_gen_qemu_st16(REG(b), t1, ctx->memidx);
 794                tcg_temp_free_i32(t1);
 795                tcg_temp_free_i32(t2);
 796
 797                length = 6;
 798            }
 799            break;
 800        default:
 801            {
 802                TCGv temp = tcg_temp_new_i32();
 803                tcg_gen_movi_i32(cpu_pc, ctx->pc);
 804                tcg_gen_movi_i32(temp, MOXIE_EX_BAD);
 805                gen_helper_raise_exception(cpu_env, temp);
 806                tcg_temp_free_i32(temp);
 807             }
 808            break;
 809        }
 810    }
 811
 812    return length;
 813}
 814
 815/* generate intermediate code for basic block 'tb'.  */
 816void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
 817{
 818    CPUMoxieState *env = cs->env_ptr;
 819    MoxieCPU *cpu = moxie_env_get_cpu(env);
 820    DisasContext ctx;
 821    target_ulong pc_start;
 822    int num_insns, max_insns;
 823
 824    pc_start = tb->pc;
 825    ctx.pc = pc_start;
 826    ctx.saved_pc = -1;
 827    ctx.tb = tb;
 828    ctx.memidx = 0;
 829    ctx.singlestep_enabled = 0;
 830    ctx.bstate = BS_NONE;
 831    num_insns = 0;
 832    max_insns = tb_cflags(tb) & CF_COUNT_MASK;
 833    if (max_insns == 0) {
 834        max_insns = CF_COUNT_MASK;
 835    }
 836    if (max_insns > TCG_MAX_INSNS) {
 837        max_insns = TCG_MAX_INSNS;
 838    }
 839
 840    gen_tb_start(tb);
 841    do {
 842        tcg_gen_insn_start(ctx.pc);
 843        num_insns++;
 844
 845        if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
 846            tcg_gen_movi_i32(cpu_pc, ctx.pc);
 847            gen_helper_debug(cpu_env);
 848            ctx.bstate = BS_EXCP;
 849            /* The address covered by the breakpoint must be included in
 850               [tb->pc, tb->pc + tb->size) in order to for it to be
 851               properly cleared -- thus we increment the PC here so that
 852               the logic setting tb->size below does the right thing.  */
 853            ctx.pc += 2;
 854            goto done_generating;
 855        }
 856
 857        ctx.opcode = cpu_lduw_code(env, ctx.pc);
 858        ctx.pc += decode_opc(cpu, &ctx);
 859
 860        if (num_insns >= max_insns) {
 861            break;
 862        }
 863        if (cs->singlestep_enabled) {
 864            break;
 865        }
 866        if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) {
 867            break;
 868        }
 869    } while (ctx.bstate == BS_NONE && !tcg_op_buf_full());
 870
 871    if (cs->singlestep_enabled) {
 872        tcg_gen_movi_tl(cpu_pc, ctx.pc);
 873        gen_helper_debug(cpu_env);
 874    } else {
 875        switch (ctx.bstate) {
 876        case BS_STOP:
 877        case BS_NONE:
 878            gen_goto_tb(env, &ctx, 0, ctx.pc);
 879            break;
 880        case BS_EXCP:
 881            tcg_gen_exit_tb(0);
 882            break;
 883        case BS_BRANCH:
 884        default:
 885            break;
 886        }
 887    }
 888 done_generating:
 889    gen_tb_end(tb, num_insns);
 890
 891    tb->size = ctx.pc - pc_start;
 892    tb->icount = num_insns;
 893}
 894
 895void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb,
 896                          target_ulong *data)
 897{
 898    env->pc = data[0];
 899}
 900