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