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