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