xref: /openbmc/qemu/target/avr/translate.c (revision e03feba0)
1*e03feba0SMichael Rolnik /*
2*e03feba0SMichael Rolnik  * QEMU AVR CPU
3*e03feba0SMichael Rolnik  *
4*e03feba0SMichael Rolnik  * Copyright (c) 2019-2020 Michael Rolnik
5*e03feba0SMichael Rolnik  *
6*e03feba0SMichael Rolnik  * This library is free software; you can redistribute it and/or
7*e03feba0SMichael Rolnik  * modify it under the terms of the GNU Lesser General Public
8*e03feba0SMichael Rolnik  * License as published by the Free Software Foundation; either
9*e03feba0SMichael Rolnik  * version 2.1 of the License, or (at your option) any later version.
10*e03feba0SMichael Rolnik  *
11*e03feba0SMichael Rolnik  * This library is distributed in the hope that it will be useful,
12*e03feba0SMichael Rolnik  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*e03feba0SMichael Rolnik  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*e03feba0SMichael Rolnik  * Lesser General Public License for more details.
15*e03feba0SMichael Rolnik  *
16*e03feba0SMichael Rolnik  * You should have received a copy of the GNU Lesser General Public
17*e03feba0SMichael Rolnik  * License along with this library; if not, see
18*e03feba0SMichael Rolnik  * <http://www.gnu.org/licenses/lgpl-2.1.html>
19*e03feba0SMichael Rolnik  */
20*e03feba0SMichael Rolnik 
21*e03feba0SMichael Rolnik #include "qemu/osdep.h"
22*e03feba0SMichael Rolnik #include "qemu/qemu-print.h"
23*e03feba0SMichael Rolnik #include "tcg/tcg.h"
24*e03feba0SMichael Rolnik #include "cpu.h"
25*e03feba0SMichael Rolnik #include "exec/exec-all.h"
26*e03feba0SMichael Rolnik #include "tcg/tcg-op.h"
27*e03feba0SMichael Rolnik #include "exec/cpu_ldst.h"
28*e03feba0SMichael Rolnik #include "exec/helper-proto.h"
29*e03feba0SMichael Rolnik #include "exec/helper-gen.h"
30*e03feba0SMichael Rolnik #include "exec/log.h"
31*e03feba0SMichael Rolnik #include "exec/translator.h"
32*e03feba0SMichael Rolnik #include "exec/gen-icount.h"
33*e03feba0SMichael Rolnik 
34*e03feba0SMichael Rolnik /*
35*e03feba0SMichael Rolnik  *  Define if you want a BREAK instruction translated to a breakpoint
36*e03feba0SMichael Rolnik  *  Active debugging connection is assumed
37*e03feba0SMichael Rolnik  *  This is for
38*e03feba0SMichael Rolnik  *  https://github.com/seharris/qemu-avr-tests/tree/master/instruction-tests
39*e03feba0SMichael Rolnik  *  tests
40*e03feba0SMichael Rolnik  */
41*e03feba0SMichael Rolnik #undef BREAKPOINT_ON_BREAK
42*e03feba0SMichael Rolnik 
43*e03feba0SMichael Rolnik static TCGv cpu_pc;
44*e03feba0SMichael Rolnik 
45*e03feba0SMichael Rolnik static TCGv cpu_Cf;
46*e03feba0SMichael Rolnik static TCGv cpu_Zf;
47*e03feba0SMichael Rolnik static TCGv cpu_Nf;
48*e03feba0SMichael Rolnik static TCGv cpu_Vf;
49*e03feba0SMichael Rolnik static TCGv cpu_Sf;
50*e03feba0SMichael Rolnik static TCGv cpu_Hf;
51*e03feba0SMichael Rolnik static TCGv cpu_Tf;
52*e03feba0SMichael Rolnik static TCGv cpu_If;
53*e03feba0SMichael Rolnik 
54*e03feba0SMichael Rolnik static TCGv cpu_rampD;
55*e03feba0SMichael Rolnik static TCGv cpu_rampX;
56*e03feba0SMichael Rolnik static TCGv cpu_rampY;
57*e03feba0SMichael Rolnik static TCGv cpu_rampZ;
58*e03feba0SMichael Rolnik 
59*e03feba0SMichael Rolnik static TCGv cpu_r[NUMBER_OF_CPU_REGISTERS];
60*e03feba0SMichael Rolnik static TCGv cpu_eind;
61*e03feba0SMichael Rolnik static TCGv cpu_sp;
62*e03feba0SMichael Rolnik 
63*e03feba0SMichael Rolnik static TCGv cpu_skip;
64*e03feba0SMichael Rolnik 
65*e03feba0SMichael Rolnik static const char reg_names[NUMBER_OF_CPU_REGISTERS][8] = {
66*e03feba0SMichael Rolnik     "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
67*e03feba0SMichael Rolnik     "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
68*e03feba0SMichael Rolnik     "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
69*e03feba0SMichael Rolnik     "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
70*e03feba0SMichael Rolnik };
71*e03feba0SMichael Rolnik #define REG(x) (cpu_r[x])
72*e03feba0SMichael Rolnik 
73*e03feba0SMichael Rolnik enum {
74*e03feba0SMichael Rolnik     DISAS_EXIT   = DISAS_TARGET_0,  /* We want return to the cpu main loop.  */
75*e03feba0SMichael Rolnik     DISAS_LOOKUP = DISAS_TARGET_1,  /* We have a variable condition exit.  */
76*e03feba0SMichael Rolnik     DISAS_CHAIN  = DISAS_TARGET_2,  /* We have a single condition exit.  */
77*e03feba0SMichael Rolnik };
78*e03feba0SMichael Rolnik 
79*e03feba0SMichael Rolnik typedef struct DisasContext DisasContext;
80*e03feba0SMichael Rolnik 
81*e03feba0SMichael Rolnik /* This is the state at translation time. */
82*e03feba0SMichael Rolnik struct DisasContext {
83*e03feba0SMichael Rolnik     TranslationBlock *tb;
84*e03feba0SMichael Rolnik 
85*e03feba0SMichael Rolnik     CPUAVRState *env;
86*e03feba0SMichael Rolnik     CPUState *cs;
87*e03feba0SMichael Rolnik 
88*e03feba0SMichael Rolnik     target_long npc;
89*e03feba0SMichael Rolnik     uint32_t opcode;
90*e03feba0SMichael Rolnik 
91*e03feba0SMichael Rolnik     /* Routine used to access memory */
92*e03feba0SMichael Rolnik     int memidx;
93*e03feba0SMichael Rolnik     int bstate;
94*e03feba0SMichael Rolnik     int singlestep;
95*e03feba0SMichael Rolnik 
96*e03feba0SMichael Rolnik     /*
97*e03feba0SMichael Rolnik      * some AVR instructions can make the following instruction to be skipped
98*e03feba0SMichael Rolnik      * Let's name those instructions
99*e03feba0SMichael Rolnik      *     A   - instruction that can skip the next one
100*e03feba0SMichael Rolnik      *     B   - instruction that can be skipped. this depends on execution of A
101*e03feba0SMichael Rolnik      * there are two scenarios
102*e03feba0SMichael Rolnik      * 1. A and B belong to the same translation block
103*e03feba0SMichael Rolnik      * 2. A is the last instruction in the translation block and B is the last
104*e03feba0SMichael Rolnik      *
105*e03feba0SMichael Rolnik      * following variables are used to simplify the skipping logic, they are
106*e03feba0SMichael Rolnik      * used in the following manner (sketch)
107*e03feba0SMichael Rolnik      *
108*e03feba0SMichael Rolnik      * TCGLabel *skip_label = NULL;
109*e03feba0SMichael Rolnik      * if (ctx.skip_cond != TCG_COND_NEVER) {
110*e03feba0SMichael Rolnik      *     skip_label = gen_new_label();
111*e03feba0SMichael Rolnik      *     tcg_gen_brcond_tl(skip_cond, skip_var0, skip_var1, skip_label);
112*e03feba0SMichael Rolnik      * }
113*e03feba0SMichael Rolnik      *
114*e03feba0SMichael Rolnik      * if (free_skip_var0) {
115*e03feba0SMichael Rolnik      *     tcg_temp_free(skip_var0);
116*e03feba0SMichael Rolnik      *     free_skip_var0 = false;
117*e03feba0SMichael Rolnik      * }
118*e03feba0SMichael Rolnik      *
119*e03feba0SMichael Rolnik      * translate(&ctx);
120*e03feba0SMichael Rolnik      *
121*e03feba0SMichael Rolnik      * if (skip_label) {
122*e03feba0SMichael Rolnik      *     gen_set_label(skip_label);
123*e03feba0SMichael Rolnik      * }
124*e03feba0SMichael Rolnik      */
125*e03feba0SMichael Rolnik     TCGv skip_var0;
126*e03feba0SMichael Rolnik     TCGv skip_var1;
127*e03feba0SMichael Rolnik     TCGCond skip_cond;
128*e03feba0SMichael Rolnik     bool free_skip_var0;
129*e03feba0SMichael Rolnik };
130*e03feba0SMichael Rolnik 
131*e03feba0SMichael Rolnik static bool avr_have_feature(DisasContext *ctx, int feature)
132*e03feba0SMichael Rolnik {
133*e03feba0SMichael Rolnik     if (!avr_feature(ctx->env, feature)) {
134*e03feba0SMichael Rolnik         gen_helper_unsupported(cpu_env);
135*e03feba0SMichael Rolnik         ctx->bstate = DISAS_NORETURN;
136*e03feba0SMichael Rolnik         return false;
137*e03feba0SMichael Rolnik     }
138*e03feba0SMichael Rolnik     return true;
139*e03feba0SMichael Rolnik }
140*e03feba0SMichael Rolnik 
141*e03feba0SMichael Rolnik static bool decode_insn(DisasContext *ctx, uint16_t insn);
142*e03feba0SMichael Rolnik #include "decode_insn.inc.c"
143