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