[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v13 9/9] target-avr: adding instruction decoder
From: |
Michael Rolnik |
Subject: |
[Qemu-devel] [PATCH v13 9/9] target-avr: adding instruction decoder |
Date: |
Tue, 26 Jul 2016 06:50:14 +0300 |
Signed-off-by: Michael Rolnik <address@hidden>
---
target-avr/Makefile.objs | 1 +
target-avr/cpugen/src/.cpugen.cpp.swp | Bin 0 -> 24576 bytes
target-avr/decode.c | 693 +++++++++++++++
target-avr/helper.c | 2 +
target-avr/helper.h | 1 +
target-avr/translate-inst.c | 1529 +++++++++++++++++----------------
target-avr/translate.c | 29 +-
7 files changed, 1473 insertions(+), 782 deletions(-)
create mode 100644 target-avr/cpugen/src/.cpugen.cpp.swp
create mode 100644 target-avr/decode.c
diff --git a/target-avr/Makefile.objs b/target-avr/Makefile.objs
index fdafcd5..993a3a9 100644
--- a/target-avr/Makefile.objs
+++ b/target-avr/Makefile.objs
@@ -20,4 +20,5 @@
obj-y += translate.o cpu.o helper.o translate-inst.o
obj-y += gdbstub.o
+obj-y += decode.o
obj-$(CONFIG_SOFTMMU) += machine.o
diff --git a/target-avr/cpugen/src/.cpugen.cpp.swp
b/target-avr/cpugen/src/.cpugen.cpp.swp
new file mode 100644
index
0000000000000000000000000000000000000000..9c969c860d704e3b2a9c392742ec1beffe5f35f4
GIT binary patch
literal 24576
zcmeI450D&LS-|`7IN;y_;V2Om-VLysO=f3j!*SeglGROilB~CX;_fE7uoqIZv%R~W
z%+3tcy~*Z6?f^?l5w%M1fIAMY5~u=2z$)c9EK#&nkn%VX3b3>kia$buoFGuBfWPnk
z>3%&syLZvDEUf9;UwY>address@hidden)>K-ejqAVscu&q<mw*_4FWU|K00PK62u{S3ULa
zAn3Fj&address@hidden;^H`c>u5)ZdK(fL{u4!=BH-x#W$
z?+hok&T5$GkM;J(YS<i(JN04nv0QJrcgnv1tS^DS1h$jFMzS(=^L4?C_Ks8}%JU01
zsAoRo_;#`T;e848CD4~ZUjlsz^d-=jKwkoV3G^lK|4;%+`|98>+VwcwwpZKxRbBV1
z?f1mqf4=Ma<L&oX+WU99p8tsbzF_YcYyqwu8{EJ3CD4~ZUjlsz^d-=jKwkoV3G^k<
zmq1?veF^j>(3imff&^;IL2y0!-YgCP_Wzyz|GlRL!8hR%_y~LmHenZh>Zw8SS{R4N
z!{gu&t_y<8a0is&pPmu~_rMYO_LGC)9q>lD8-4>`1x<J<9Dx_Z4e%8B?zKViCHN$~
zA0C9?guCEQI0t880uI3t{22V;NkQ;^_%wVHJ^_CM?|@6N2^ZiLoP>address@hidden)`q5
zfj@)y!2|FXcr)A&zX-2^Uw}n81vkRe;address@hidden;Dzu!crH90
zo(k8&address@hidden&20wElQBk)AH20ntb<;@VnGL&address@hidden;~UZa51+3zM)P
zo&%r55%YFv!j16n^!vx)VYm<Og&CLz(TSU&$EDoWYS&xKp*o-ng?&NbLRX@&u^bb+
z)M~}a=xE$-L`l(vmQ>address@hidden
address@hidden&address@hidden>NEug{vZ7N~t~h1I
zlv%m*GAl}#S-J8um6FQR1Nl~_z3fRoi?Q5Nm$JU!h?>cZ_MS=9Qk1k-R^l*04=P#g
zBx+vVTyN|address@hidden>%QN8x`><FrisM&`GL*?Y%Q#M!(X^x!
zHCI(address@hidden@sP`<2GMIPa{1c(6stSr?Xfv
z1r|=1YjG~`qOX%)p{iM1mthknLt`sZCr)}LbQL%CIW;~#H99&Y!)-v9YLmwy&zDW@
zS6UratZgJMGUl;JwY(IrMosD=L5u<&7B-h9WY3-`8Km<r1?OAQGExgWHKe1)##FIK
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
NOk%P}0;T4`e*pxn!_fc$
literal 0
HcmV?d00001
diff --git a/target-avr/decode.c b/target-avr/decode.c
new file mode 100644
index 0000000..41e16e3
--- /dev/null
+++ b/target-avr/decode.c
@@ -0,0 +1,693 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include <stdint.h>
+#include "translate.h"
+
+void avr_decode(uint32_t pc, uint32_t *l, uint32_t c, translate_function_t *t)
+{
+ uint32_t opc = extract32(c, 0, 16);
+ switch (opc & 0x0000d000) {
+ case 0x00000000: {
+ switch (opc & 0x00002c00) {
+ case 0x00000000: {
+ switch (opc & 0x00000300) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_NOP;
+ break;
+ }
+ case 0x00000100: {
+ *l = 16;
+ *t = &avr_translate_MOVW;
+ break;
+ }
+ case 0x00000200: {
+ *l = 16;
+ *t = &avr_translate_MULS;
+ break;
+ }
+ case 0x00000300: {
+ switch (opc & 0x00000088) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_MULSU;
+ break;
+ }
+ case 0x00000008: {
+ *l = 16;
+ *t = &avr_translate_FMUL;
+ break;
+ }
+ case 0x00000080: {
+ *l = 16;
+ *t = &avr_translate_FMULS;
+ break;
+ }
+ case 0x00000088: {
+ *l = 16;
+ *t = &avr_translate_FMULSU;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000400: {
+ *l = 16;
+ *t = &avr_translate_CPC;
+ break;
+ }
+ case 0x00000800: {
+ *l = 16;
+ *t = &avr_translate_SBC;
+ break;
+ }
+ case 0x00000c00: {
+ *l = 16;
+ *t = &avr_translate_ADD;
+ break;
+ }
+ case 0x00002000: {
+ *l = 16;
+ *t = &avr_translate_AND;
+ break;
+ }
+ case 0x00002400: {
+ *l = 16;
+ *t = &avr_translate_EOR;
+ break;
+ }
+ case 0x00002800: {
+ *l = 16;
+ *t = &avr_translate_OR;
+ break;
+ }
+ case 0x00002c00: {
+ *l = 16;
+ *t = &avr_translate_MOV;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00001000: {
+ switch (opc & 0x00002000) {
+ case 0x00000000: {
+ switch (opc & 0x00000c00) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_CPSE;
+ break;
+ }
+ case 0x00000400: {
+ *l = 16;
+ *t = &avr_translate_CP;
+ break;
+ }
+ case 0x00000800: {
+ *l = 16;
+ *t = &avr_translate_SUB;
+ break;
+ }
+ case 0x00000c00: {
+ *l = 16;
+ *t = &avr_translate_ADC;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00002000: {
+ *l = 16;
+ *t = &avr_translate_CPI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00004000: {
+ switch (opc & 0x00002000) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_SBCI;
+ break;
+ }
+ case 0x00002000: {
+ *l = 16;
+ *t = &avr_translate_ORI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00005000: {
+ switch (opc & 0x00002000) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_SUBI;
+ break;
+ }
+ case 0x00002000: {
+ *l = 16;
+ *t = &avr_translate_ANDI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00008000: {
+ switch (opc & 0x00000208) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_LDDZ;
+ break;
+ }
+ case 0x00000008: {
+ *l = 16;
+ *t = &avr_translate_LDDY;
+ break;
+ }
+ case 0x00000200: {
+ *l = 16;
+ *t = &avr_translate_STDZ;
+ break;
+ }
+ case 0x00000208: {
+ *l = 16;
+ *t = &avr_translate_STDY;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00009000: {
+ switch (opc & 0x00002800) {
+ case 0x00000000: {
+ switch (opc & 0x00000600) {
+ case 0x00000000: {
+ switch (opc & 0x0000000f) {
+ case 0x00000000: {
+ *l = 32;
+ *t = &avr_translate_LDS;
+ break;
+ }
+ case 0x00000001: {
+ *l = 16;
+ *t = &avr_translate_LDZ2;
+ break;
+ }
+ case 0x00000002: {
+ *l = 16;
+ *t = &avr_translate_LDZ3;
+ break;
+ }
+ case 0x00000003: {
+ break;
+ }
+ case 0x00000004: {
+ *l = 16;
+ *t = &avr_translate_LPM2;
+ break;
+ }
+ case 0x00000005: {
+ *l = 16;
+ *t = &avr_translate_LPMX;
+ break;
+ }
+ case 0x00000006: {
+ *l = 16;
+ *t = &avr_translate_ELPM2;
+ break;
+ }
+ case 0x00000007: {
+ *l = 16;
+ *t = &avr_translate_ELPMX;
+ break;
+ }
+ case 0x00000008: {
+ break;
+ }
+ case 0x00000009: {
+ *l = 16;
+ *t = &avr_translate_LDY2;
+ break;
+ }
+ case 0x0000000a: {
+ *l = 16;
+ *t = &avr_translate_LDY3;
+ break;
+ }
+ case 0x0000000b: {
+ break;
+ }
+ case 0x0000000c: {
+ *l = 16;
+ *t = &avr_translate_LDX1;
+ break;
+ }
+ case 0x0000000d: {
+ *l = 16;
+ *t = &avr_translate_LDX2;
+ break;
+ }
+ case 0x0000000e: {
+ *l = 16;
+ *t = &avr_translate_LDX3;
+ break;
+ }
+ case 0x0000000f: {
+ *l = 16;
+ *t = &avr_translate_POP;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000200: {
+ switch (opc & 0x0000000f) {
+ case 0x00000000: {
+ *l = 32;
+ *t = &avr_translate_STS;
+ break;
+ }
+ case 0x00000001: {
+ *l = 16;
+ *t = &avr_translate_STZ2;
+ break;
+ }
+ case 0x00000002: {
+ *l = 16;
+ *t = &avr_translate_STZ3;
+ break;
+ }
+ case 0x00000003: {
+ break;
+ }
+ case 0x00000004: {
+ *l = 16;
+ *t = &avr_translate_XCH;
+ break;
+ }
+ case 0x00000005: {
+ *l = 16;
+ *t = &avr_translate_LAS;
+ break;
+ }
+ case 0x00000006: {
+ *l = 16;
+ *t = &avr_translate_LAC;
+ break;
+ }
+ case 0x00000007: {
+ *l = 16;
+ *t = &avr_translate_LAT;
+ break;
+ }
+ case 0x00000008: {
+ break;
+ }
+ case 0x00000009: {
+ *l = 16;
+ *t = &avr_translate_STY2;
+ break;
+ }
+ case 0x0000000a: {
+ *l = 16;
+ *t = &avr_translate_STY3;
+ break;
+ }
+ case 0x0000000b: {
+ break;
+ }
+ case 0x0000000c: {
+ *l = 16;
+ *t = &avr_translate_STX1;
+ break;
+ }
+ case 0x0000000d: {
+ *l = 16;
+ *t = &avr_translate_STX2;
+ break;
+ }
+ case 0x0000000e: {
+ *l = 16;
+ *t = &avr_translate_STX3;
+ break;
+ }
+ case 0x0000000f: {
+ *l = 16;
+ *t = &avr_translate_PUSH;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000400: {
+ switch (opc & 0x0000000e) {
+ case 0x00000000: {
+ switch (opc & 0x00000001) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_COM;
+ break;
+ }
+ case 0x00000001: {
+ *l = 16;
+ *t = &avr_translate_NEG;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000002: {
+ switch (opc & 0x00000001) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_SWAP;
+ break;
+ }
+ case 0x00000001: {
+ *l = 16;
+ *t = &avr_translate_INC;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000004: {
+ *l = 16;
+ *t = &avr_translate_ASR;
+ break;
+ }
+ case 0x00000006: {
+ switch (opc & 0x00000001) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_LSR;
+ break;
+ }
+ case 0x00000001: {
+ *l = 16;
+ *t = &avr_translate_ROR;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000008: {
+ switch (opc & 0x00000181) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_BSET;
+ break;
+ }
+ case 0x00000001: {
+ switch (opc & 0x00000010) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_IJMP;
+ break;
+ }
+ case 0x00000010: {
+ *l = 16;
+ *t = &avr_translate_EIJMP;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000080: {
+ *l = 16;
+ *t = &avr_translate_BCLR;
+ break;
+ }
+ case 0x00000081: {
+ break;
+ }
+ case 0x00000100: {
+ switch (opc & 0x00000010) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_RET;
+ break;
+ }
+ case 0x00000010: {
+ *l = 16;
+ *t = &avr_translate_RETI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000101: {
+ switch (opc & 0x00000010) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_ICALL;
+ break;
+ }
+ case 0x00000010: {
+ *l = 16;
+ *t = &avr_translate_EICALL;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000180: {
+ switch (opc & 0x00000070) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_SLEEP;
+ break;
+ }
+ case 0x00000010: {
+ *l = 16;
+ *t = &avr_translate_BREAK;
+ break;
+ }
+ case 0x00000020: {
+ *l = 16;
+ *t = &avr_translate_WDR;
+ break;
+ }
+ case 0x00000030: {
+ break;
+ }
+ case 0x00000040: {
+ *l = 16;
+ *t = &avr_translate_LPM1;
+ break;
+ }
+ case 0x00000050: {
+ *l = 16;
+ *t = &avr_translate_ELPM1;
+ break;
+ }
+ case 0x00000060: {
+ *l = 16;
+ *t = &avr_translate_SPM;
+ break;
+ }
+ case 0x00000070: {
+ *l = 16;
+ *t = &avr_translate_SPMX;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000181: {
+ break;
+ }
+ }
+ break;
+ }
+ case 0x0000000a: {
+ switch (opc & 0x00000001) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_DEC;
+ break;
+ }
+ case 0x00000001: {
+ *l = 16;
+ *t = &avr_translate_DES;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x0000000c: {
+ *l = 32;
+ *t = &avr_translate_JMP;
+ break;
+ }
+ case 0x0000000e: {
+ *l = 32;
+ *t = &avr_translate_CALL;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000600: {
+ switch (opc & 0x00000100) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_ADIW;
+ break;
+ }
+ case 0x00000100: {
+ *l = 16;
+ *t = &avr_translate_SBIW;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000800: {
+ switch (opc & 0x00000400) {
+ case 0x00000000: {
+ switch (opc & 0x00000300) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_CBI;
+ break;
+ }
+ case 0x00000100: {
+ *l = 16;
+ *t = &avr_translate_SBIC;
+ break;
+ }
+ case 0x00000200: {
+ *l = 16;
+ *t = &avr_translate_SBI;
+ break;
+ }
+ case 0x00000300: {
+ *l = 16;
+ *t = &avr_translate_SBIS;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000400: {
+ *l = 16;
+ *t = &avr_translate_MUL;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00002000: {
+ *l = 16;
+ *t = &avr_translate_IN;
+ break;
+ }
+ case 0x00002800: {
+ *l = 16;
+ *t = &avr_translate_OUT;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x0000c000: {
+ switch (opc & 0x00002000) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_RJMP;
+ break;
+ }
+ case 0x00002000: {
+ *l = 16;
+ *t = &avr_translate_LDI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x0000d000: {
+ switch (opc & 0x00002000) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_RCALL;
+ break;
+ }
+ case 0x00002000: {
+ switch (opc & 0x00000c00) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_BRBS;
+ break;
+ }
+ case 0x00000400: {
+ *l = 16;
+ *t = &avr_translate_BRBC;
+ break;
+ }
+ case 0x00000800: {
+ switch (opc & 0x00000200) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_BLD;
+ break;
+ }
+ case 0x00000200: {
+ *l = 16;
+ *t = &avr_translate_BST;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000c00: {
+ switch (opc & 0x00000200) {
+ case 0x00000000: {
+ *l = 16;
+ *t = &avr_translate_SBRC;
+ break;
+ }
+ case 0x00000200: {
+ *l = 16;
+ *t = &avr_translate_SBRS;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+}
+
diff --git a/target-avr/helper.c b/target-avr/helper.c
index 9635d38..bbb725e 100644
--- a/target-avr/helper.c
+++ b/target-avr/helper.c
@@ -153,6 +153,7 @@ void tlb_fill(CPUState *cs, target_ulong vaddr,
MMUAccessType access_type,
tlb_set_page_with_attrs(cs, vaddr, paddr, attrs, prot, mmu_idx, page_size);
}
+
void helper_sleep(CPUAVRState *env)
{
CPUState *cs = CPU(avr_env_get_cpu(env));
@@ -160,6 +161,7 @@ void helper_sleep(CPUAVRState *env)
cs->exception_index = EXCP_HLT;
cpu_loop_exit(cs);
}
+
void helper_unsupported(CPUAVRState *env)
{
CPUState *cs = CPU(avr_env_get_cpu(env));
diff --git a/target-avr/helper.h b/target-avr/helper.h
index 6036315..a533d2a 100644
--- a/target-avr/helper.h
+++ b/target-avr/helper.h
@@ -26,3 +26,4 @@ DEF_HELPER_3(outb, void, env, i32, i32)
DEF_HELPER_2(inb, tl, env, i32)
DEF_HELPER_3(fullwr, void, env, i32, i32)
DEF_HELPER_2(fullrd, tl, env, i32)
+
diff --git a/target-avr/translate-inst.c b/target-avr/translate-inst.c
index d1dce42..3afb0d8 100644
--- a/target-avr/translate-inst.c
+++ b/target-avr/translate-inst.c
@@ -28,14 +28,14 @@ static void gen_add_CHf(TCGv R, TCGv Rd, TCGv Rr)
TCGv t2 = tcg_temp_new_i32();
TCGv t3 = tcg_temp_new_i32();
- tcg_gen_and_tl(t1, Rd, Rr); /* t1 = Rd & Rr */
- tcg_gen_andc_tl(t2, Rd, R); /* t2 = Rd & ~R */
- tcg_gen_andc_tl(t3, Rr, R); /* t3 = Rr & ~R */
- tcg_gen_or_tl(t1, t1, t2); /* t1 = t1 | t2 | t3 */
+ tcg_gen_and_tl(t1, Rd, Rr); /* t1 = Rd & Rr */
+ tcg_gen_andc_tl(t2, Rd, R); /* t2 = Rd & ~R */
+ tcg_gen_andc_tl(t3, Rr, R); /* t3 = Rr & ~R */
+ tcg_gen_or_tl(t1, t1, t2); /* t1 = t1 | t2 | t3 */
tcg_gen_or_tl(t1, t1, t3);
- tcg_gen_shri_tl(cpu_Cf, t1, 7); /* Cf = t1(7) */
- tcg_gen_shri_tl(cpu_Hf, t1, 3); /* Hf = t1(3) */
+ tcg_gen_shri_tl(cpu_Cf, t1, 7); /* Cf = t1(7) */
+ tcg_gen_shri_tl(cpu_Hf, t1, 3); /* Hf = t1(3) */
tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
tcg_temp_free_i32(t3);
@@ -48,12 +48,12 @@ static void gen_add_Vf(TCGv R, TCGv Rd, TCGv Rr)
TCGv t1 = tcg_temp_new_i32();
TCGv t2 = tcg_temp_new_i32();
- /* t1 = Rd & Rr & ~R | ~Rd & ~Rr & R = (Rd ^ R) & ~(Rd ^ Rr) */
+ /* t1 = Rd & Rr & ~R | ~Rd & ~Rr & R = (Rd ^ R) & ~(Rd ^ Rr) */
tcg_gen_xor_tl(t1, Rd, R);
tcg_gen_xor_tl(t2, Rd, Rr);
tcg_gen_andc_tl(t1, t1, t2);
- tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
+ tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
@@ -65,14 +65,14 @@ static void gen_sub_CHf(TCGv R, TCGv Rd, TCGv Rr)
TCGv t2 = tcg_temp_new_i32();
TCGv t3 = tcg_temp_new_i32();
- /* Cf & Hf */
- tcg_gen_not_tl(t1, Rd); /* t1 = ~Rd */
- tcg_gen_and_tl(t2, t1, Rr); /* t2 = ~Rd & Rr */
- tcg_gen_or_tl(t3, t1, Rr); /* t3 = (~Rd | Rr) & R */
+ /* Cf & Hf */
+ tcg_gen_not_tl(t1, Rd); /* t1 = ~Rd */
+ tcg_gen_and_tl(t2, t1, Rr); /* t2 = ~Rd & Rr */
+ tcg_gen_or_tl(t3, t1, Rr); /* t3 = (~Rd | Rr) & R */
tcg_gen_and_tl(t3, t3, R);
- tcg_gen_or_tl(t2, t2, t3); /* t2 = ~Rd & Rr | ~Rd & R | R & Rr
*/
- tcg_gen_shri_tl(cpu_Cf, t2, 7); /* Cf = t2(7) */
- tcg_gen_shri_tl(cpu_Hf, t2, 3); /* Hf = t2(3) */
+ tcg_gen_or_tl(t2, t2, t3); /* t2 = ~Rd & Rr | ~Rd & R | R & Rr */
+ tcg_gen_shri_tl(cpu_Cf, t2, 7); /* Cf = t2(7) */
+ tcg_gen_shri_tl(cpu_Hf, t2, 3); /* Hf = t2(3) */
tcg_gen_andi_tl(cpu_Hf, cpu_Hf, 1);
tcg_temp_free_i32(t3);
@@ -85,12 +85,12 @@ static void gen_sub_Vf(TCGv R, TCGv Rd, TCGv Rr)
TCGv t1 = tcg_temp_new_i32();
TCGv t2 = tcg_temp_new_i32();
- /* Vf */
- /* t1 = Rd & ~Rr & ~R | ~Rd & Rr & R = (Rd ^ R) & (Rd ^ R)*/
+ /* Vf */
+ /* t1 = Rd & ~Rr & ~R | ~Rd & Rr & R = (Rd ^ R) & (Rd ^ R) */
tcg_gen_xor_tl(t1, Rd, R);
tcg_gen_xor_tl(t2, Rd, Rr);
tcg_gen_and_tl(t1, t1, t2);
- tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
+ tcg_gen_shri_tl(cpu_Vf, t1, 7); /* Vf = t1(7) */
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
@@ -98,15 +98,15 @@ static void gen_sub_Vf(TCGv R, TCGv Rd, TCGv Rr)
static void gen_NSf(TCGv R)
{
- tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
- tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+ tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
+ tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
}
static void gen_ZNSf(TCGv R)
{
- tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
- tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
- tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+ tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+ tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
+ tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
}
static void gen_push_ret(CPUAVRState *env, int ret)
@@ -189,11 +189,11 @@ static void gen_jmp_z(void)
}
/*
- in the gen_set_addr & gen_get_addr functions
- H assumed to be in 0x00ff0000 format
- M assumed to be in 0x000000ff format
- L assumed to be in 0x000000ff format
-*/
+ * in the gen_set_addr & gen_get_addr functions
+ * H assumed to be in 0x00ff0000 format
+ * M assumed to be in 0x000000ff format
+ * L assumed to be in 0x000000ff format
+ */
static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L)
{
@@ -227,84 +227,84 @@ static TCGv gen_get_addr(TCGv H, TCGv M, TCGv L)
tcg_gen_deposit_tl(addr, M, H, 8, 8);
tcg_gen_deposit_tl(addr, L, addr, 8, 16);
- return addr;
+ return addr;
}
static TCGv gen_get_xaddr(void)
{
- return gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]);
+ return gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]);
}
static TCGv gen_get_yaddr(void)
{
- return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
+ return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
}
static TCGv gen_get_zaddr(void)
{
- return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
+ return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
}
/*
- Adds two registers and the contents of the C Flag and places the result in
- the destination register Rd.
-*/
+ * Adds two registers and the contents of the C Flag and places the result in
+ * the destination register Rd.
+ */
int avr_translate_ADC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[ADC_Rd(opcode)];
TCGv Rr = cpu_r[ADC_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_add_tl(R, Rd, Rr); /* R = Rd + Rr + Cf */
+ /* op */
+ tcg_gen_add_tl(R, Rd, Rr); /* R = Rd + Rr + Cf */
tcg_gen_add_tl(R, R, cpu_Cf);
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_add_CHf(R, Rd, Rr);
gen_add_Vf(R, Rd, Rr);
gen_ZNSf(R);
- /* R */
+ /* R */
tcg_gen_mov_tl(Rd, R);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Adds two registers without the C Flag and places the result in the
- destination register Rd.
-*/
+ * Adds two registers without the C Flag and places the result in the
+ * destination register Rd.
+ */
int avr_translate_ADD(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[ADD_Rd(opcode)];
TCGv Rr = cpu_r[ADD_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_add_tl(R, Rd, Rr); /* Rd = Rd + Rr */
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ /* op */
+ tcg_gen_add_tl(R, Rd, Rr); /* Rd = Rd + Rr */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_add_CHf(R, Rd, Rr);
gen_add_Vf(R, Rd, Rr);
gen_ZNSf(R);
- /* R */
+ /* R */
tcg_gen_mov_tl(Rd, R);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Adds an immediate value (0 - 63) to a register pair and places the result
- in the register pair. This instruction operates on the upper four register
- pairs, and is well suited for operations on the pointer registers. This
- instruction is not available in all devices. Refer to the device specific
- instruction set summary.
-*/
+ * Adds an immediate value (0 - 63) to a register pair and places the result
+ * in the register pair. This instruction operates on the upper four register
+ * pairs, and is well suited for operations on the pointer registers. This
+ * instruction is not available in all devices. Refer to the device specific
+ * instruction set summary.
+ */
int avr_translate_ADIW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_ADIW_SBIW) == false) {
@@ -319,122 +319,122 @@ int avr_translate_ADIW(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv R = tcg_temp_new_i32();
TCGv Rd = tcg_temp_new_i32();
- /* op */
- tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
- tcg_gen_addi_tl(R, Rd, Imm); /* R = Rd + Imm */
- tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
+ /* op */
+ tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
+ tcg_gen_addi_tl(R, Rd, Imm); /* R = Rd + Imm */
+ tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
- /* Cf */
- tcg_gen_andc_tl(cpu_Cf, Rd, R); /* Cf = Rd & ~R */
+ /* Cf */
+ tcg_gen_andc_tl(cpu_Cf, Rd, R); /* Cf = Rd & ~R */
tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15);
- /* Vf */
- tcg_gen_andc_tl(cpu_Vf, R, Rd); /* Vf = R & ~Rd */
+ /* Vf */
+ tcg_gen_andc_tl(cpu_Vf, R, Rd); /* Vf = R & ~Rd */
tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15);
- /* Zf */
- tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+ /* Zf */
+ tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
- /* Nf */
- tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
+ /* Nf */
+ tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
- /* Sf */
- tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);/* Sf = Nf ^ Vf */
+ /* Sf */
+ tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf);/* Sf = Nf ^ Vf */
- /* R */
+ /* R */
tcg_gen_andi_tl(RdL, R, 0xff);
tcg_gen_shri_tl(RdH, R, 8);
tcg_temp_free_i32(Rd);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Performs the logical AND between the contents of register Rd and register
- Rr and places the result in the destination register Rd.
-*/
+ * Performs the logical AND between the contents of register Rd and register
+ * Rr and places the result in the destination register Rd.
+ */
int avr_translate_AND(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[AND_Rd(opcode)];
TCGv Rr = cpu_r[AND_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_and_tl(R, Rd, Rr); /* Rd = Rd and Rr */
+ /* op */
+ tcg_gen_and_tl(R, Rd, Rr); /* Rd = Rd and Rr */
- /* Vf */
- tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+ /* Vf */
+ tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
- /* Zf */
- tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+ /* Zf */
+ tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
gen_ZNSf(R);
- /* R */
+ /* R */
tcg_gen_mov_tl(Rd, R);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Performs the logical AND between the contents of register Rd and a constant
- and places the result in the destination register Rd.
-*/
+ * Performs the logical AND between the contents of register Rd and a constant
+ * and places the result in the destination register Rd.
+ */
int avr_translate_ANDI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[16 + ANDI_Rd(opcode)];
int Imm = (ANDI_Imm(opcode));
- /* op */
- tcg_gen_andi_tl(Rd, Rd, Imm); /* Rd = Rd & Imm */
+ /* op */
+ tcg_gen_andi_tl(Rd, Rd, Imm); /* Rd = Rd & Imm */
- tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+ tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
gen_ZNSf(Rd);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Shifts all bits in Rd one place to the right. Bit 7 is held constant. Bit 0
- is loaded into the C Flag of the SREG. This operation effectively divides a
- signed value by two without changing its sign. The Carry Flag can be used
to
- round the result.
-*/
+ * Shifts all bits in Rd one place to the right. Bit 7 is held constant. Bit 0
+ * is loaded into the C Flag of the SREG. This operation effectively divides a
+ * signed value by two without changing its sign. The Carry Flag can be used
to
+ * round the result.
+ */
int avr_translate_ASR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[ASR_Rd(opcode)];
TCGv t1 = tcg_temp_new_i32();
TCGv t2 = tcg_temp_new_i32();
- /* op */
- tcg_gen_andi_tl(t1, Rd, 0x80); /* t1 = (Rd & 0x80) | (Rd >> 1) */
+ /* op */
+ tcg_gen_andi_tl(t1, Rd, 0x80); /* t1 = (Rd & 0x80) | (Rd >> 1) */
tcg_gen_shri_tl(t2, Rd, 1);
tcg_gen_or_tl(t1, t1, t2);
- /* Cf */
- tcg_gen_andi_tl(cpu_Cf, Rd, 1); /* Cf = Rd(0) */
+ /* Cf */
+ tcg_gen_andi_tl(cpu_Cf, Rd, 1); /* Cf = Rd(0) */
- /* Vf */
- tcg_gen_and_tl(cpu_Vf, cpu_Nf, cpu_Cf);/* Vf = Nf & Cf */
+ /* Vf */
+ tcg_gen_and_tl(cpu_Vf, cpu_Nf, cpu_Cf);/* Vf = Nf & Cf */
gen_ZNSf(t1);
- /* op */
+ /* op */
tcg_gen_mov_tl(Rd, t1);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Clears a single Flag in SREG.
-*/
+ * Clears a single Flag in SREG.
+ */
int avr_translate_BCLR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
switch (BCLR_Bit(opcode)) {
@@ -472,36 +472,36 @@ int avr_translate_BCLR(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
}
}
- return BS_NONE;
+ return BS_NONE;
}
/*
- Copies the T Flag in the SREG (Status Register) to bit b in register Rd.
-*/
+ * Copies the T Flag in the SREG (Status Register) to bit b in register Rd.
+ */
int avr_translate_BLD(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[BLD_Rd(opcode)];
TCGv t1 = tcg_temp_new_i32();
- tcg_gen_andi_tl(Rd, Rd, ~(1u << BLD_Bit(opcode))); /* clear bit */
- tcg_gen_shli_tl(t1, cpu_Tf, BLD_Bit(opcode)); /* create mask */
+ tcg_gen_andi_tl(Rd, Rd, ~(1u << BLD_Bit(opcode))); /* clear bit */
+ tcg_gen_shli_tl(t1, cpu_Tf, BLD_Bit(opcode)); /* create mask */
tcg_gen_or_tl(Rd, Rd, t1);
tcg_temp_free_i32(t1);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Conditional relative branch. Tests a single bit in SREG and branches
- relatively to PC if the bit is cleared. This instruction branches
relatively
- to PC in either direction (PC - 63 < = destination <= PC + 64). The
- parameter k is the offset from PC and is represented in two’s complement
- form.
-*/
+ * Conditional relative branch. Tests a single bit in SREG and branches
+ * relatively to PC if the bit is cleared. This instruction branches
relatively
+ * to PC in either direction (PC - 63 < = destination <= PC + 64). The
+ * parameter k is the offset from PC and is represented in two’s complement
+ * form.
+ */
int avr_translate_BRBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
- TCGLabel *taken = gen_new_label();
+ TCGLabel *taken = gen_new_label();
int Imm = sextract32(BRBC_Imm(opcode), 0, 7);
switch (BRBC_Bit(opcode)) {
@@ -547,14 +547,14 @@ int avr_translate_BRBC(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
}
/*
- Conditional relative branch. Tests a single bit in SREG and branches
- relatively to PC if the bit is set. This instruction branches relatively to
- PC in either direction (PC - 63 < = destination <= PC + 64). The parameter
k
- is the offset from PC and is represented in two’s complement form.
-*/
+ * Conditional relative branch. Tests a single bit in SREG and branches
+ * relatively to PC if the bit is set. This instruction branches relatively to
+ * PC in either direction (PC - 63 < = destination <= PC + 64). The parameter
k
+ * is the offset from PC and is represented in two’s complement form.
+ */
int avr_translate_BRBS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
- TCGLabel *taken = gen_new_label();
+ TCGLabel *taken = gen_new_label();
int Imm = sextract32(BRBS_Imm(opcode), 0, 7);
switch (BRBS_Bit(opcode)) {
@@ -600,8 +600,8 @@ int avr_translate_BRBS(CPUAVRState *env, DisasContext *ctx,
uint32_t opcode)
}
/*
- Sets a single Flag or bit in SREG.
-*/
+ * Sets a single Flag or bit in SREG.
+ */
int avr_translate_BSET(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
switch (BSET_Bit(opcode)) {
@@ -639,19 +639,19 @@ int avr_translate_BSET(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
}
}
- return BS_NONE;
+ return BS_NONE;
}
/*
- The BREAK instruction is used by the On-chip Debug system, and is
- normally not used in the application software. When the BREAK instruction
is
- executed, the AVR CPU is set in the Stopped Mode. This gives the On-chip
- Debugger access to internal resources. If any Lock bits are set, or either
- the JTAGEN or OCDEN Fuses are unprogrammed, the CPU will treat the BREAK
- instruction as a NOP and will not enter the Stopped mode. This instruction
- is not available in all devices. Refer to the device specific instruction
- set summary.
-*/
+ * The BREAK instruction is used by the On-chip Debug system, and is
+ * normally not used in the application software. When the BREAK instruction
is
+ * executed, the AVR CPU is set in the Stopped Mode. This gives the On-chip
+ * Debugger access to internal resources. If any Lock bits are set, or either
+ * the JTAGEN or OCDEN Fuses are unprogrammed, the CPU will treat the BREAK
+ * instruction as a NOP and will not enter the Stopped mode. This instruction
+ * is not available in all devices. Refer to the device specific instruction
+ * set summary.
+ */
int avr_translate_BREAK(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_BREAK) == false) {
@@ -660,13 +660,13 @@ int avr_translate_BREAK(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
return BS_EXCP;
}
- /* TODO: ??? */
- return BS_NONE;
+ /* TODO: ??? */
+ return BS_NONE;
}
/*
- Stores bit b from Rd to the T Flag in SREG (Status Register).
-*/
+ * Stores bit b from Rd to the T Flag in SREG (Status Register).
+ */
int avr_translate_BST(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[BST_Rd(opcode)];
@@ -674,16 +674,16 @@ int avr_translate_BST(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_andi_tl(cpu_Tf, Rd, 1 << BST_Bit(opcode));
tcg_gen_shri_tl(cpu_Tf, cpu_Tf, BST_Bit(opcode));
- return BS_NONE;
+ return BS_NONE;
}
/*
- Calls to a subroutine within the entire Program memory. The return
- address (to the instruction after the CALL) will be stored onto the Stack.
- (See also RCALL). The Stack Pointer uses a post-decrement scheme during
- CALL. This instruction is not available in all devices. Refer to the
device
- specific instruction set summary.
-*/
+ * Calls to a subroutine within the entire Program memory. The return
+ * address (to the instruction after the CALL) will be stored onto the Stack.
+ * (See also RCALL). The Stack Pointer uses a post-decrement scheme during
+ * CALL. This instruction is not available in all devices. Refer to the
device
+ * specific instruction set summary.
+ */
int avr_translate_CALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_JMP_CALL) == false) {
@@ -699,12 +699,13 @@ int avr_translate_CALL(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
gen_goto_tb(env, ctx, 0, Imm);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- Clears a specified bit in an I/O Register. This instruction operates on
- the lower 32 I/O Registers – addresses 0-31. */
+ * Clears a specified bit in an I/O Register. This instruction operates on
+ * the lower 32 I/O Registers – addresses 0-31.
+ */
int avr_translate_CBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv data = cpu_io[CBI_Imm(opcode)];
@@ -713,14 +714,14 @@ int avr_translate_CBI(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_andi_tl(data, data, ~(1 << CBI_Bit(opcode)));
gen_helper_outb(cpu_env, port, data);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Clears the specified bits in register Rd. Performs the logical AND
- between the contents of register Rd and the complement of the constant mask
- K. The result will be placed in register Rd.
-*/
+ * Clears the specified bits in register Rd. Performs the logical AND
+ * between the contents of register Rd and the complement of the constant mask
+ * K. The result will be placed in register Rd.
+ */
int avr_translate_COM(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[COM_Rd(opcode)];
@@ -728,29 +729,29 @@ int avr_translate_COM(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_xori_tl(Rd, Rd, 0xff);
- tcg_gen_movi_tl(cpu_Cf, 1); /* Cf = 1 */
- tcg_gen_movi_tl(cpu_Vf, 0); /* Vf = 0 */
+ tcg_gen_movi_tl(cpu_Cf, 1); /* Cf = 1 */
+ tcg_gen_movi_tl(cpu_Vf, 0); /* Vf = 0 */
gen_ZNSf(Rd);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs a compare between two registers Rd and Rr.
- None of the registers are changed. All conditional branches can be used
- after this instruction.
-*/
+ * This instruction performs a compare between two registers Rd and Rr.
+ * None of the registers are changed. All conditional branches can be used
+ * after this instruction.
+ */
int avr_translate_CP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[CP_Rd(opcode)];
TCGv Rr = cpu_r[CP_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ /* op */
+ tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_sub_CHf(R, Rd, Rr);
gen_sub_Vf(R, Rd, Rr);
@@ -758,44 +759,44 @@ int avr_translate_CP(CPUAVRState *env, DisasContext *ctx,
uint32_t opcode)
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs a compare between two registers Rd and Rr and
- also takes into account the previous carry. None of the registers are
- changed. All conditional branches can be used after this instruction.
-*/
+ * This instruction performs a compare between two registers Rd and Rr and
+ * also takes into account the previous carry. None of the registers are
+ * changed. All conditional branches can be used after this instruction.
+ */
int avr_translate_CPC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[CPC_Rd(opcode)];
TCGv Rr = cpu_r[CPC_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+ /* op */
+ tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
tcg_gen_sub_tl(R, R, cpu_Cf);
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_sub_CHf(R, Rd, Rr);
gen_sub_Vf(R, Rd, Rr);
gen_NSf(R);
- /* Previous value remains unchanged when the result is zero;
- cleared otherwise.
- */
+ /* Previous value remains unchanged when the result is zero;
+ * cleared otherwise.
+ */
tcg_gen_or_tl(cpu_Zf, cpu_Zf, R);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs a compare between register Rd and a constant.
- The register is not changed. All conditional branches can be used after
this
- instruction.
-*/
+ * This instruction performs a compare between register Rd and a constant.
+ * The register is not changed. All conditional branches can be used after
this
+ * instruction.
+ */
int avr_translate_CPI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[16 + CPI_Rd(opcode)];
@@ -803,9 +804,9 @@ int avr_translate_CPI(CPUAVRState *env, DisasContext *ctx,
uint32_t opcode)
TCGv Rr = tcg_const_i32(Imm);
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ /* op */
+ tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_sub_CHf(R, Rd, Rr);
gen_sub_Vf(R, Rd, Rr);
@@ -813,92 +814,91 @@ int avr_translate_CPI(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs a compare between two registers Rd and Rr, and
- skips the next instruction if Rd = Rr.
-*/
+ * This instruction performs a compare between two registers Rd and Rr, and
+ * skips the next instruction if Rd = Rr.
+ */
int avr_translate_CPSE(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[CPSE_Rd(opcode)];
TCGv Rr = cpu_r[CPSE_Rr(opcode)];
TCGLabel *skip = gen_new_label();
- /* PC if next inst is skipped */
+ /* PC if next inst is skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
tcg_gen_brcond_i32(TCG_COND_EQ, Rd, Rr, skip);
- /* PC if next inst is not skipped */
+ /* PC if next inst is not skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
gen_set_label(skip);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- Subtracts one -1- from the contents of register Rd and places the result
- in the destination register Rd. The C Flag in SREG is not affected by the
- operation, thus allowing the DEC instruction to be used on a loop counter
in
- multiple-precision computations. When operating on unsigned values, only
- BREQ and BRNE branches can be expected to perform consistently. When
- operating on two’s complement values, all signed branches are available.
-*/
+ * Subtracts one -1- from the contents of register Rd and places the result
+ * in the destination register Rd. The C Flag in SREG is not affected by the
+ * operation, thus allowing the DEC instruction to be used on a loop counter
in
+ * multiple-precision computations. When operating on unsigned values, only
+ * BREQ and BRNE branches can be expected to perform consistently. When
+ * operating on two’s complement values, all signed branches are available.
+ */
int avr_translate_DEC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[DEC_Rd(opcode)];
- tcg_gen_subi_tl(Rd, Rd, 1); /* Rd = Rd - 1 */
- tcg_gen_andi_tl(Rd, Rd, 0xff); /* make it 8 bits */
+ tcg_gen_subi_tl(Rd, Rd, 1); /* Rd = Rd - 1 */
+ tcg_gen_andi_tl(Rd, Rd, 0xff); /* make it 8 bits */
- /* cpu_Vf = Rd == 0x7f */
+ /* cpu_Vf = Rd == 0x7f */
tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x7f);
gen_ZNSf(Rd);
- return BS_NONE;
-}
-
-/*
-
- The module is an instruction set extension to the AVR CPU, performing
- DES iterations. The 64-bit data block (plaintext or ciphertext) is placed
in
- the CPU register file, registers R0-R7, where LSB of data is placed in LSB
- of R0 and MSB of data is placed in MSB of R7. The full 64-bit key
(including
- parity bits) is placed in registers R8- R15, organized in the register file
- with LSB of key in LSB of R8 and MSB of key in MSB of R15. Executing one
DES
- instruction performs one round in the DES algorithm. Sixteen rounds must be
- executed in increasing order to form the correct DES ciphertext or
- plaintext. Intermediate results are stored in the register file (R0-R15)
- after each DES instruction. The instruction's operand (K) determines which
- round is executed, and the half carry flag (H) determines whether
encryption
- or decryption is performed. The DES algorithm is described in
- “Specifications for the Data Encryption Standard” (Federal Information
- Processing Standards Publication 46). Intermediate results in this
- implementation differ from the standard because the initial permutation and
- the inverse initial permutation are performed each iteration. This does not
- affect the result in the final ciphertext or plaintext, but reduces
- execution time.
-*/
+ return BS_NONE;
+}
+
+/*
+ * The module is an instruction set extension to the AVR CPU, performing
+ * DES iterations. The 64-bit data block (plaintext or ciphertext) is placed
in
+ * the CPU register file, registers R0-R7, where LSB of data is placed in LSB
+ * of R0 and MSB of data is placed in MSB of R7. The full 64-bit key
(including
+ * parity bits) is placed in registers R8- R15, organized in the register file
+ * with LSB of key in LSB of R8 and MSB of key in MSB of R15. Executing one
DES
+ * instruction performs one round in the DES algorithm. Sixteen rounds must be
+ * executed in increasing order to form the correct DES ciphertext or
+ * plaintext. Intermediate results are stored in the register file (R0-R15)
+ * after each DES instruction. The instruction's operand (K) determines which
+ * round is executed, and the half carry flag (H) determines whether
encryption
+ * or decryption is performed. The DES algorithm is described in
+ * “Specifications for the Data Encryption Standard” (Federal Information
+ * Processing Standards Publication 46). Intermediate results in this
+ * implementation differ from the standard because the initial permutation and
+ * the inverse initial permutation are performed each iteration. This does not
+ * affect the result in the final ciphertext or plaintext, but reduces
+ * execution time.
+ */
int avr_translate_DES(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
- /* TODO: */
+ /* TODO: */
if (avr_feature(env, AVR_FEATURE_DES) == false) {
gen_helper_unsupported(cpu_env);
return BS_EXCP;
}
- return BS_NONE;
+ return BS_NONE;
}
/*
- Indirect call of a subroutine pointed to by the Z (16 bits) Pointer
- Register in the Register File and the EIND Register in the I/O space. This
- instruction allows for indirect calls to the entire 4M (words) Program
- memory space. See also ICALL. The Stack Pointer uses a post-decrement
scheme
- during EICALL. This instruction is not available in all devices. Refer to
- the device specific instruction set summary.
-*/
+ * Indirect call of a subroutine pointed to by the Z (16 bits) Pointer
+ * Register in the Register File and the EIND Register in the I/O space. This
+ * instruction allows for indirect calls to the entire 4M (words) Program
+ * memory space. See also ICALL. The Stack Pointer uses a post-decrement
scheme
+ * during EICALL. This instruction is not available in all devices. Refer to
+ * the device specific instruction set summary.
+ */
int avr_translate_EICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_EIJMP_EICALL) == false) {
@@ -917,12 +917,12 @@ int avr_translate_EICALL(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
}
/*
- Indirect jump to the address pointed to by the Z (16 bits) Pointer
- Register in the Register File and the EIND Register in the I/O space. This
- instruction allows for indirect jumps to the entire 4M (words) Program
- memory space. See also IJMP. This instruction is not available in all
- devices. Refer to the device specific instruction set summary.
-*/
+ * Indirect jump to the address pointed to by the Z (16 bits) Pointer
+ * Register in the Register File and the EIND Register in the I/O space. This
+ * instruction allows for indirect jumps to the entire 4M (words) Program
+ * memory space. See also IJMP. This instruction is not available in all
+ * devices. Refer to the device specific instruction set summary.
+ */
int avr_translate_EIJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_EIJMP_EICALL) == false) {
@@ -937,21 +937,21 @@ int avr_translate_EIJMP(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
}
/*
- Loads one byte pointed to by the Z-register and the RAMPZ Register in
- the I/O space, and places this byte in the destination register Rd. This
- instruction features a 100% space effective constant initialization or
- constant data fetch. The Program memory is organized in 16-bit words while
- the Z-pointer is a byte address. Thus, the least significant bit of the
- Z-pointer selects either low byte (ZLSB = 0) or high byte (ZLSB = 1). This
- instruction can address the entire Program memory space. The Z-pointer
- Register can either be left unchanged by the operation, or it can be
- incremented. The incrementation applies to the entire 24-bit concatenation
- of the RAMPZ and Z-pointer Registers. Devices with Self-Programming
- capability can use the ELPM instruction to read the Fuse and Lock bit
value.
- Refer to the device documentation for a detailed description. This
- instruction is not available in all devices. Refer to the device specific
- instruction set summary.
-*/
+ * Loads one byte pointed to by the Z-register and the RAMPZ Register in
+ * the I/O space, and places this byte in the destination register Rd. This
+ * instruction features a 100% space effective constant initialization or
+ * constant data fetch. The Program memory is organized in 16-bit words while
+ * the Z-pointer is a byte address. Thus, the least significant bit of the
+ * Z-pointer selects either low byte (ZLSB = 0) or high byte (ZLSB = 1). This
+ * instruction can address the entire Program memory space. The Z-pointer
+ * Register can either be left unchanged by the operation, or it can be
+ * incremented. The incrementation applies to the entire 24-bit concatenation
+ * of the RAMPZ and Z-pointer Registers. Devices with Self-Programming
+ * capability can use the ELPM instruction to read the Fuse and Lock bit
value.
+ * Refer to the device documentation for a detailed description. This
+ * instruction is not available in all devices. Refer to the device specific
+ * instruction set summary.
+ */
int avr_translate_ELPM1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_ELPM) == false) {
@@ -963,11 +963,11 @@ int avr_translate_ELPM1(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[0];
TCGv addr = gen_get_zaddr();
- tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+ tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_ELPM2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -981,11 +981,11 @@ int avr_translate_ELPM2(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[ELPM2_Rd(opcode)];
TCGv addr = gen_get_zaddr();
- tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+ tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_ELPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -999,21 +999,21 @@ int avr_translate_ELPMX(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[ELPMX_Rd(opcode)];
TCGv addr = gen_get_zaddr();
- tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+ tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
- tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+ tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
gen_set_zaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Performs the logical EOR between the contents of register Rd and
- register Rr and places the result in the destination register Rd.
-*/
+ * Performs the logical EOR between the contents of register Rd and
+ * register Rr and places the result in the destination register Rd.
+ */
int avr_translate_EOR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[EOR_Rd(opcode)];
@@ -1024,13 +1024,13 @@ int avr_translate_EOR(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_movi_tl(cpu_Vf, 0);
gen_ZNSf(Rd);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs 8-bit x 8-bit -> 16-bit unsigned
- multiplication and shifts the result one bit left.
-*/
+ * This instruction performs 8-bit x 8-bit -> 16-bit unsigned
+ * multiplication and shifts the result one bit left.
+ */
int avr_translate_FMUL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_MUL) == false) {
@@ -1045,25 +1045,25 @@ int avr_translate_FMUL(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rr = cpu_r[16 + FMUL_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
+ tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
tcg_gen_shli_tl(R, R, 1);
tcg_gen_andi_tl(R0, R, 0xff);
tcg_gen_shri_tl(R, R, 8);
tcg_gen_andi_tl(R1, R, 0xff);
- tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+ tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
- and shifts the result one bit left.
-*/
+ * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
+ * and shifts the result one bit left.
+ */
int avr_translate_FMULS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_MUL) == false) {
@@ -1080,29 +1080,29 @@ int avr_translate_FMULS(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv t0 = tcg_temp_new_i32();
TCGv t1 = tcg_temp_new_i32();
- tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
- tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
- tcg_gen_mul_tl(R, t0, t1); /* R = Rd *Rr */
+ tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+ tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
+ tcg_gen_mul_tl(R, t0, t1); /* R = Rd *Rr */
tcg_gen_shli_tl(R, R, 1);
tcg_gen_andi_tl(R0, R, 0xff);
tcg_gen_shri_tl(R, R, 8);
tcg_gen_andi_tl(R1, R, 0xff);
- tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+ tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
- and shifts the result one bit left.
-*/
+ * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication
+ * and shifts the result one bit left.
+ */
int avr_translate_FMULSU(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_MUL) == false) {
@@ -1118,30 +1118,30 @@ int avr_translate_FMULSU(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv R = tcg_temp_new_i32();
TCGv t0 = tcg_temp_new_i32();
- tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
- tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
+ tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+ tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
tcg_gen_shli_tl(R, R, 1);
tcg_gen_andi_tl(R0, R, 0xff);
tcg_gen_shri_tl(R, R, 8);
tcg_gen_andi_tl(R1, R, 0xff);
- tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+ tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
tcg_gen_andi_tl(cpu_Zf, R, 0x0000ffff);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Calls to a subroutine within the entire 4M (words) Program memory. The
- return address (to the instruction after the CALL) will be stored onto the
- Stack. See also RCALL. The Stack Pointer uses a post-decrement scheme
during
- CALL. This instruction is not available in all devices. Refer to the
device
- specific instruction set summary.
-*/
+ * Calls to a subroutine within the entire 4M (words) Program memory. The
+ * return address (to the instruction after the CALL) will be stored onto the
+ * Stack. See also RCALL. The Stack Pointer uses a post-decrement scheme
during
+ * CALL. This instruction is not available in all devices. Refer to the
device
+ * specific instruction set summary.
+ */
int avr_translate_ICALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_IJMP_ICALL) == false) {
@@ -1159,12 +1159,12 @@ int avr_translate_ICALL(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
}
/*
- Indirect jump to the address pointed to by the Z (16 bits) Pointer
- Register in the Register File. The Z-pointer Register is 16 bits wide and
- allows jump within the lowest 64K words (128KB) section of Program memory.
- This instruction is not available in all devices. Refer to the device
- specific instruction set summary.
-*/
+ * Indirect jump to the address pointed to by the Z (16 bits) Pointer
+ * Register in the Register File. The Z-pointer Register is 16 bits wide and
+ * allows jump within the lowest 64K words (128KB) section of Program memory.
+ * This instruction is not available in all devices. Refer to the device
+ * specific instruction set summary.
+ */
int avr_translate_IJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_IJMP_ICALL) == false) {
@@ -1179,9 +1179,9 @@ int avr_translate_IJMP(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
}
/*
- Loads data from the I/O Space (Ports, Timers, Configuration Registers,
- etc.) into register Rd in the Register File.
-*/
+ * Loads data from the I/O Space (Ports, Timers, Configuration Registers,
+ * etc.) into register Rd in the Register File.
+ */
int avr_translate_IN(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[IN_Rd(opcode)];
@@ -1192,17 +1192,17 @@ int avr_translate_IN(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
gen_helper_inb(data, cpu_env, port);
tcg_gen_mov_tl(Rd, data);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Adds one -1- to the contents of register Rd and places the result in the
- destination register Rd. The C Flag in SREG is not affected by the
- operation, thus allowing the INC instruction to be used on a loop counter
in
- multiple-precision computations. When operating on unsigned numbers, only
- BREQ and BRNE branches can be expected to perform consistently. When
- operating on two’s complement values, all signed branches are available.
-*/
+ * Adds one -1- to the contents of register Rd and places the result in the
+ * destination register Rd. The C Flag in SREG is not affected by the
+ * operation, thus allowing the INC instruction to be used on a loop counter
in
+ * multiple-precision computations. When operating on unsigned numbers, only
+ * BREQ and BRNE branches can be expected to perform consistently. When
+ * operating on two’s complement values, all signed branches are available.
+ */
int avr_translate_INC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[INC_Rd(opcode)];
@@ -1210,17 +1210,17 @@ int avr_translate_INC(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_addi_tl(Rd, Rd, 1);
tcg_gen_andi_tl(Rd, Rd, 0xff);
- /* cpu_Vf = Rd == 0x80 */
+ /* cpu_Vf = Rd == 0x80 */
tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Vf, Rd, 0x80);
gen_ZNSf(Rd);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Jump to an address within the entire 4M (words) Program memory. See also
- RJMP. This instruction is not available in all devices. Refer to the
device
- specific instruction set summary.0
-*/
+ * Jump to an address within the entire 4M (words) Program memory. See also
+ * RJMP. This instruction is not available in all devices. Refer to the
device
+ * specific instruction set summary.0
+ */
int avr_translate_JMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_JMP_CALL) == false) {
@@ -1230,25 +1230,25 @@ int avr_translate_JMP(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
}
gen_goto_tb(env, ctx, 0, JMP_Imm(opcode));
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- Load one byte indirect from data space to register and stores an clear
- the bits in data space specified by the register. The instruction can only
- be used towards internal SRAM. The data location is pointed to by the Z
(16
- bits) Pointer Register in the Register File. Memory access is limited to
the
- current data segment of 64KB. To access another data segment in devices
with
- more than 64KB data space, the RAMPZ in register in the I/O area has to be
- changed. The Z-pointer Register is left unchanged by the operation. This
- instruction is especially suited for clearing status bits stored in SRAM.
-*/
+ * Load one byte indirect from data space to register and stores an clear
+ * the bits in data space specified by the register. The instruction can only
+ * be used towards internal SRAM. The data location is pointed to by the Z
(16
+ * bits) Pointer Register in the Register File. Memory access is limited to
the
+ * current data segment of 64KB. To access another data segment in devices
with
+ * more than 64KB data space, the RAMPZ in register in the I/O area has to be
+ * changed. The Z-pointer Register is left unchanged by the operation. This
+ * instruction is especially suited for clearing status bits stored in SRAM.
+ */
static void gen_data_store(DisasContext *ctx, TCGv data, TCGv addr)
{
if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) {
gen_helper_fullwr(cpu_env, data, addr);
} else {
- tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX); /* mem[addr] = data */
+ tcg_gen_qemu_st8(data, addr, MMU_DATA_IDX); /* mem[addr] = data */
}
}
@@ -1257,7 +1257,7 @@ static void gen_data_load(DisasContext *ctx, TCGv data,
TCGv addr)
if (ctx->tb->flags & TB_FLAGS_FULL_ACCESS) {
gen_helper_fullrd(data, cpu_env, addr);
} else {
- tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX); /* data = mem[addr] */
+ tcg_gen_qemu_ld8u(data, addr, MMU_DATA_IDX); /* data = mem[addr] */
}
}
@@ -1274,30 +1274,30 @@ int avr_translate_LAC(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv t0 = tcg_temp_new_i32();
TCGv t1 = tcg_temp_new_i32();
- gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
- /* t1 = t0 & (0xff - Rr) = t0 and ~Rr */
+ gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+ /* t1 = t0 & (0xff - Rr) = t0 and ~Rr */
tcg_gen_andc_tl(t1, t0, Rr);
- tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
- gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+ tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+ gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Load one byte indirect from data space to register and set bits in data
- space specified by the register. The instruction can only be used towards
- internal SRAM. The data location is pointed to by the Z (16 bits) Pointer
- Register in the Register File. Memory access is limited to the current data
- segment of 64KB. To access another data segment in devices with more than
- 64KB data space, the RAMPZ in register in the I/O area has to be changed.
- The Z-pointer Register is left unchanged by the operation. This instruction
- is especially suited for setting status bits stored in SRAM.
-*/
+ * Load one byte indirect from data space to register and set bits in data
+ * space specified by the register. The instruction can only be used towards
+ * internal SRAM. The data location is pointed to by the Z (16 bits) Pointer
+ * Register in the Register File. Memory access is limited to the current data
+ * segment of 64KB. To access another data segment in devices with more than
+ * 64KB data space, the RAMPZ in register in the I/O area has to be changed.
+ * The Z-pointer Register is left unchanged by the operation. This instruction
+ * is especially suited for setting status bits stored in SRAM.
+ */
int avr_translate_LAS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_RMW) == false) {
@@ -1311,29 +1311,29 @@ int avr_translate_LAS(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv t0 = tcg_temp_new_i32();
TCGv t1 = tcg_temp_new_i32();
- gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+ gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
tcg_gen_or_tl(t1, t0, Rr);
- tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
- gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+ tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+ gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Load one byte indirect from data space to register and toggles bits in
- the data space specified by the register. The instruction can only be used
- towards SRAM. The data location is pointed to by the Z (16 bits) Pointer
- Register in the Register File. Memory access is limited to the current data
- segment of 64KB. To access another data segment in devices with more than
- 64KB data space, the RAMPZ in register in the I/O area has to be changed.
- The Z-pointer Register is left unchanged by the operation. This instruction
- is especially suited for changing status bits stored in SRAM.
-*/
+ * Load one byte indirect from data space to register and toggles bits in
+ * the data space specified by the register. The instruction can only be used
+ * towards SRAM. The data location is pointed to by the Z (16 bits) Pointer
+ * Register in the Register File. Memory access is limited to the current data
+ * segment of 64KB. To access another data segment in devices with more than
+ * 64KB data space, the RAMPZ in register in the I/O area has to be changed.
+ * The Z-pointer Register is left unchanged by the operation. This instruction
+ * is especially suited for changing status bits stored in SRAM.
+ */
int avr_translate_LAT(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_RMW) == false) {
@@ -1347,44 +1347,44 @@ int avr_translate_LAT(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv t0 = tcg_temp_new_i32();
TCGv t1 = tcg_temp_new_i32();
- gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
+ gen_data_load(ctx, t0, addr); /* t0 = mem[addr] */
tcg_gen_xor_tl(t1, t0, Rr);
- tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
- gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
+ tcg_gen_mov_tl(Rr, t0); /* Rr = t0 */
+ gen_data_store(ctx, t1, addr); /* mem[addr] = t1 */
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(addr);
- return BS_NONE;
-}
-
-/*
- Loads one byte indirect from the data space to a register. For parts
- with SRAM, the data space consists of the Register File, I/O memory and
- internal SRAM (and external SRAM if applicable). For parts without SRAM,
the
- data space consists of the Register File only. In some parts the Flash
- Memory has been mapped to the data space and can be read using this
command.
- The EEPROM has a separate address space. The data location is pointed to
by
- the X (16 bits) Pointer Register in the Register File. Memory access is
- limited to the current data segment of 64KB. To access another data segment
- in devices with more than 64KB data space, the RAMPX in register in the I/O
- area has to be changed. The X-pointer Register can either be left
unchanged
- by the operation, or it can be post-incremented or predecremented. These
- features are especially suited for accessing arrays, tables, and Stack
- Pointer usage of the X-pointer Register. Note that only the low byte of the
- X-pointer is updated in devices with no more than 256 bytes data space. For
- such devices, the high byte of the pointer is not used by this instruction
- and can be used for other purposes. The RAMPX Register in the I/O area is
- updated in parts with more than 64KB data space or more than 64KB Program
- memory, and the increment/decrement is added to the entire 24-bit address
on
- such devices. Not all variants of this instruction is available in all
- devices. Refer to the device specific instruction set summary. In the
- Reduced Core tinyAVR the LD instruction can be used to achieve the same
- operation as LPM since the program memory is mapped to the data memory
- space.
-*/
+ return BS_NONE;
+}
+
+/*
+ * Loads one byte indirect from the data space to a register. For parts
+ * with SRAM, the data space consists of the Register File, I/O memory and
+ * internal SRAM (and external SRAM if applicable). For parts without SRAM,
the
+ * data space consists of the Register File only. In some parts the Flash
+ * Memory has been mapped to the data space and can be read using this
command.
+ * The EEPROM has a separate address space. The data location is pointed to
by
+ * the X (16 bits) Pointer Register in the Register File. Memory access is
+ * limited to the current data segment of 64KB. To access another data segment
+ * in devices with more than 64KB data space, the RAMPX in register in the I/O
+ * area has to be changed. The X-pointer Register can either be left
unchanged
+ * by the operation, or it can be post-incremented or predecremented. These
+ * features are especially suited for accessing arrays, tables, and Stack
+ * Pointer usage of the X-pointer Register. Note that only the low byte of the
+ * X-pointer is updated in devices with no more than 256 bytes data space. For
+ * such devices, the high byte of the pointer is not used by this instruction
+ * and can be used for other purposes. The RAMPX Register in the I/O area is
+ * updated in parts with more than 64KB data space or more than 64KB Program
+ * memory, and the increment/decrement is added to the entire 24-bit address
on
+ * such devices. Not all variants of this instruction is available in all
+ * devices. Refer to the device specific instruction set summary. In the
+ * Reduced Core tinyAVR the LD instruction can be used to achieve the same
+ * operation as LPM since the program memory is mapped to the data memory
+ * space.
+ */
int avr_translate_LDX1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[LDX1_Rd(opcode)];
@@ -1394,7 +1394,7 @@ int avr_translate_LDX1(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_LDX2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -1403,13 +1403,13 @@ int avr_translate_LDX2(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv addr = gen_get_xaddr();
gen_data_load(ctx, Rd, addr);
- tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+ tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
gen_set_xaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_LDX3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -1417,53 +1417,53 @@ int avr_translate_LDX3(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[LDX3_Rd(opcode)];
TCGv addr = gen_get_xaddr();
- tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+ tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
gen_data_load(ctx, Rd, addr);
gen_set_xaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
-}
-
-/*
- Loads one byte indirect with or without displacement from the data space
- to a register. For parts with SRAM, the data space consists of the Register
- File, I/O memory and internal SRAM (and external SRAM if applicable). For
- parts without SRAM, the data space consists of the Register File only. In
- some parts the Flash Memory has been mapped to the data space and can be
- read using this command. The EEPROM has a separate address space. The data
- location is pointed to by the Y (16 bits) Pointer Register in the Register
- File. Memory access is limited to the current data segment of 64KB. To
- access another data segment in devices with more than 64KB data space, the
- RAMPY in register in the I/O area has to be changed. The Y-pointer
Register
- can either be left unchanged by the operation, or it can be
post-incremented
- or predecremented. These features are especially suited for accessing
- arrays, tables, and Stack Pointer usage of the Y-pointer Register. Note
that
- only the low byte of the Y-pointer is updated in devices with no more than
- 256 bytes data space. For such devices, the high byte of the pointer is not
- used by this instruction and can be used for other purposes. The RAMPY
- Register in the I/O area is updated in parts with more than 64KB data space
- or more than 64KB Program memory, and the increment/decrement/displacement
- is added to the entire 24-bit address on such devices. Not all variants of
- this instruction is available in all devices. Refer to the device specific
- instruction set summary. In the Reduced Core tinyAVR the LD instruction
can
- be used to achieve the same operation as LPM since the program memory is
- mapped to the data memory space.
-*/
+ return BS_NONE;
+}
+
+/*
+ * Loads one byte indirect with or without displacement from the data space
+ * to a register. For parts with SRAM, the data space consists of the Register
+ * File, I/O memory and internal SRAM (and external SRAM if applicable). For
+ * parts without SRAM, the data space consists of the Register File only. In
+ * some parts the Flash Memory has been mapped to the data space and can be
+ * read using this command. The EEPROM has a separate address space. The data
+ * location is pointed to by the Y (16 bits) Pointer Register in the Register
+ * File. Memory access is limited to the current data segment of 64KB. To
+ * access another data segment in devices with more than 64KB data space, the
+ * RAMPY in register in the I/O area has to be changed. The Y-pointer
Register
+ * can either be left unchanged by the operation, or it can be
post-incremented
+ * or predecremented. These features are especially suited for accessing
+ * arrays, tables, and Stack Pointer usage of the Y-pointer Register. Note
that
+ * only the low byte of the Y-pointer is updated in devices with no more than
+ * 256 bytes data space. For such devices, the high byte of the pointer is not
+ * used by this instruction and can be used for other purposes. The RAMPY
+ * Register in the I/O area is updated in parts with more than 64KB data space
+ * or more than 64KB Program memory, and the increment/decrement/displacement
+ * is added to the entire 24-bit address on such devices. Not all variants of
+ * this instruction is available in all devices. Refer to the device specific
+ * instruction set summary. In the Reduced Core tinyAVR the LD instruction
can
+ * be used to achieve the same operation as LPM since the program memory is
+ * mapped to the data memory space.
+ */
int avr_translate_LDY2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[LDY2_Rd(opcode)];
TCGv addr = gen_get_yaddr();
gen_data_load(ctx, Rd, addr);
- tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+ tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
gen_set_yaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_LDY3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -1471,13 +1471,13 @@ int avr_translate_LDY3(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[LDY3_Rd(opcode)];
TCGv addr = gen_get_yaddr();
- tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+ tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
gen_data_load(ctx, Rd, addr);
gen_set_yaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_LDDY(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -1485,57 +1485,56 @@ int avr_translate_LDDY(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[LDDY_Rd(opcode)];
TCGv addr = gen_get_yaddr();
- tcg_gen_addi_tl(addr, addr, LDDY_Imm(opcode));
- /* addr = addr + q */
+ tcg_gen_addi_tl(addr, addr, LDDY_Imm(opcode)); /* addr = addr + q */
gen_data_load(ctx, Rd, addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
-}
-
-/*
- Loads one byte indirect with or without displacement from the data space
- to a register. For parts with SRAM, the data space consists of the Register
- File, I/O memory and internal SRAM (and external SRAM if applicable). For
- parts without SRAM, the data space consists of the Register File only. In
- some parts the Flash Memory has been mapped to the data space and can be
- read using this command. The EEPROM has a separate address space. The data
- location is pointed to by the Z (16 bits) Pointer Register in the Register
- File. Memory access is limited to the current data segment of 64KB. To
- access another data segment in devices with more than 64KB data space, the
- RAMPZ in register in the I/O area has to be changed. The Z-pointer
Register
- can either be left unchanged by the operation, or it can be
post-incremented
- or predecremented. These features are especially suited for Stack Pointer
- usage of the Z-pointer Register, however because the Z-pointer Register can
- be used for indirect subroutine calls, indirect jumps and table lookup, it
- is often more convenient to use the X or Y-pointer as a dedicated Stack
- Pointer. Note that only the low byte of the Z-pointer is updated in devices
- with no more than 256 bytes data space. For such devices, the high byte of
- the pointer is not used by this instruction and can be used for other
- purposes. The RAMPZ Register in the I/O area is updated in parts with more
- than 64KB data space or more than 64KB Program memory, and the
- increment/decrement/displacement is added to the entire 24-bit address on
- such devices. Not all variants of this instruction is available in all
- devices. Refer to the device specific instruction set summary. In the
- Reduced Core tinyAVR the LD instruction can be used to achieve the same
- operation as LPM since the program memory is mapped to the data memory
- space. For using the Z-pointer for table lookup in Program memory see the
- LPM and ELPM instructions.
-*/
+ return BS_NONE;
+}
+
+/*
+ * Loads one byte indirect with or without displacement from the data space
+ * to a register. For parts with SRAM, the data space consists of the Register
+ * File, I/O memory and internal SRAM (and external SRAM if applicable). For
+ * parts without SRAM, the data space consists of the Register File only. In
+ * some parts the Flash Memory has been mapped to the data space and can be
+ * read using this command. The EEPROM has a separate address space. The data
+ * location is pointed to by the Z (16 bits) Pointer Register in the Register
+ * File. Memory access is limited to the current data segment of 64KB. To
+ * access another data segment in devices with more than 64KB data space, the
+ * RAMPZ in register in the I/O area has to be changed. The Z-pointer
Register
+ * can either be left unchanged by the operation, or it can be
post-incremented
+ * or predecremented. These features are especially suited for Stack Pointer
+ * usage of the Z-pointer Register, however because the Z-pointer Register can
+ * be used for indirect subroutine calls, indirect jumps and table lookup, it
+ * is often more convenient to use the X or Y-pointer as a dedicated Stack
+ * Pointer. Note that only the low byte of the Z-pointer is updated in devices
+ * with no more than 256 bytes data space. For such devices, the high byte of
+ * the pointer is not used by this instruction and can be used for other
+ * purposes. The RAMPZ Register in the I/O area is updated in parts with more
+ * than 64KB data space or more than 64KB Program memory, and the
+ * increment/decrement/displacement is added to the entire 24-bit address on
+ * such devices. Not all variants of this instruction is available in all
+ * devices. Refer to the device specific instruction set summary. In the
+ * Reduced Core tinyAVR the LD instruction can be used to achieve the same
+ * operation as LPM since the program memory is mapped to the data memory
+ * space. For using the Z-pointer for table lookup in Program memory see the
+ * LPM and ELPM instructions.
+ */
int avr_translate_LDZ2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[LDZ2_Rd(opcode)];
TCGv addr = gen_get_zaddr();
gen_data_load(ctx, Rd, addr);
- tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+ tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
gen_set_zaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_LDZ3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -1543,14 +1542,14 @@ int avr_translate_LDZ3(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[LDZ3_Rd(opcode)];
TCGv addr = gen_get_zaddr();
- tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+ tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
gen_data_load(ctx, Rd, addr);
gen_set_zaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_LDDZ(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -1559,17 +1558,17 @@ int avr_translate_LDDZ(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv addr = gen_get_zaddr();
tcg_gen_addi_tl(addr, addr, LDDZ_Imm(opcode));
- /* addr = addr + q */
+ /* addr = addr + q */
gen_data_load(ctx, Rd, addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
/*
Loads an 8 bit constant directly to register 16 to 31.
-*/
+ */
int avr_translate_LDI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[16 + LDI_Rd(opcode)];
@@ -1577,28 +1576,28 @@ int avr_translate_LDI(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_movi_tl(Rd, imm);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Loads one byte from the data space to a register. For parts with SRAM,
- the data space consists of the Register File, I/O memory and internal SRAM
- (and external SRAM if applicable). For parts without SRAM, the data space
- consists of the register file only. The EEPROM has a separate address
space.
- A 16-bit address must be supplied. Memory access is limited to the current
- data segment of 64KB. The LDS instruction uses the RAMPD Register to access
- memory above 64KB. To access another data segment in devices with more than
- 64KB data space, the RAMPD in register in the I/O area has to be changed.
- This instruction is not available in all devices. Refer to the device
- specific instruction set summary.
-*/
+ * Loads one byte from the data space to a register. For parts with SRAM,
+ * the data space consists of the Register File, I/O memory and internal SRAM
+ * (and external SRAM if applicable). For parts without SRAM, the data space
+ * consists of the register file only. The EEPROM has a separate address
space.
+ * A 16-bit address must be supplied. Memory access is limited to the current
+ * data segment of 64KB. The LDS instruction uses the RAMPD Register to access
+ * memory above 64KB. To access another data segment in devices with more than
+ * 64KB data space, the RAMPD in register in the I/O area has to be changed.
+ * This instruction is not available in all devices. Refer to the device
+ * specific instruction set summary.
+ */
int avr_translate_LDS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[LDS_Rd(opcode)];
TCGv addr = tcg_temp_new_i32();
TCGv H = cpu_rampD;
- tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
+ tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
tcg_gen_shli_tl(addr, addr, 16);
tcg_gen_ori_tl(addr, addr, LDS_Imm(opcode));
@@ -1606,24 +1605,24 @@ int avr_translate_LDS(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Loads one byte pointed to by the Z-register into the destination
- register Rd. This instruction features a 100% space effective constant
- initialization or constant data fetch. The Program memory is organized in
- 16-bit words while the Z-pointer is a byte address. Thus, the least
- significant bit of the Z-pointer selects either low byte (ZLSB = 0) or high
- byte (ZLSB = 1). This instruction can address the first 64KB (32K words) of
- Program memory. The Zpointer Register can either be left unchanged by the
- operation, or it can be incremented. The incrementation does not apply to
- the RAMPZ Register. Devices with Self-Programming capability can use the
- LPM instruction to read the Fuse and Lock bit values. Refer to the device
- documentation for a detailed description. The LPM instruction is not
- available in all devices. Refer to the device specific instruction set
- summary
-*/
+ * Loads one byte pointed to by the Z-register into the destination
+ * register Rd. This instruction features a 100% space effective constant
+ * initialization or constant data fetch. The Program memory is organized in
+ * 16-bit words while the Z-pointer is a byte address. Thus, the least
+ * significant bit of the Z-pointer selects either low byte (ZLSB = 0) or high
+ * byte (ZLSB = 1). This instruction can address the first 64KB (32K words) of
+ * Program memory. The Zpointer Register can either be left unchanged by the
+ * operation, or it can be incremented. The incrementation does not apply to
+ * the RAMPZ Register. Devices with Self-Programming capability can use the
+ * LPM instruction to read the Fuse and Lock bit values. Refer to the device
+ * documentation for a detailed description. The LPM instruction is not
+ * available in all devices. Refer to the device specific instruction set
+ * summary
+ */
int avr_translate_LPM1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_LPM) == false) {
@@ -1637,14 +1636,14 @@ int avr_translate_LPM1(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv H = cpu_r[31];
TCGv L = cpu_r[30];
- tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+ tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
tcg_gen_or_tl(addr, addr, L);
- tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+ tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_LPM2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -1660,14 +1659,14 @@ int avr_translate_LPM2(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv H = cpu_r[31];
TCGv L = cpu_r[30];
- tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+ tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
tcg_gen_or_tl(addr, addr, L);
- tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+ tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_LPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -1683,12 +1682,12 @@ int avr_translate_LPMX(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv H = cpu_r[31];
TCGv L = cpu_r[30];
- tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
+ tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
tcg_gen_or_tl(addr, addr, L);
- tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
+ tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
- tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+ tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
tcg_gen_andi_tl(L, addr, 0xff);
@@ -1697,14 +1696,14 @@ int avr_translate_LPMX(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Shifts all bits in Rd one place to the right. Bit 7 is cleared. Bit 0 is
- loaded into the C Flag of the SREG. This operation effectively divides an
- unsigned value by two. The C Flag can be used to round the result.
-*/
+ * Shifts all bits in Rd one place to the right. Bit 7 is cleared. Bit 0 is
+ * loaded into the C Flag of the SREG. This operation effectively divides an
+ * unsigned value by two. The C Flag can be used to round the result.
+ */
int avr_translate_LSR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[LSR_Rd(opcode)];
@@ -1715,14 +1714,14 @@ int avr_translate_LSR(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
gen_ZNSf(Rd);
tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction makes a copy of one register into another. The source
- register Rr is left unchanged, while the destination register Rd is loaded
- with a copy of Rr.
-*/
+ * This instruction makes a copy of one register into another. The source
+ * register Rr is left unchanged, while the destination register Rd is loaded
+ * with a copy of Rr.
+ */
int avr_translate_MOV(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[MOV_Rd(opcode)];
@@ -1730,16 +1729,16 @@ int avr_translate_MOV(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_mov_tl(Rd, Rr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction makes a copy of one register pair into another register
- pair. The source register pair Rr+1:Rr is left unchanged, while the
- destination register pair Rd+1:Rd is loaded with a copy of Rr + 1:Rr. This
- instruction is not available in all devices. Refer to the device specific
- instruction set summary.
-*/
+ * This instruction makes a copy of one register pair into another register
+ * pair. The source register pair Rr+1:Rr is left unchanged, while the
+ * destination register pair Rd+1:Rd is loaded with a copy of Rr + 1:Rr. This
+ * instruction is not available in all devices. Refer to the device specific
+ * instruction set summary.
+ */
int avr_translate_MOVW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_MOVW) == false) {
@@ -1756,12 +1755,12 @@ int avr_translate_MOVW(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_mov_tl(RdH, RrH);
tcg_gen_mov_tl(RdL, RrL);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication.
-*/
+ * This instruction performs 8-bit x 8-bit -> 16-bit unsigned multiplication.
+ */
int avr_translate_MUL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_MUL) == false) {
@@ -1776,24 +1775,24 @@ int avr_translate_MUL(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rr = cpu_r[MUL_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
+ tcg_gen_mul_tl(R, Rd, Rr); /* R = Rd *Rr */
tcg_gen_mov_tl(R0, R);
tcg_gen_andi_tl(R0, R0, 0xff);
tcg_gen_shri_tl(R, R, 8);
tcg_gen_mov_tl(R1, R);
- tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
+ tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
tcg_gen_mov_tl(cpu_Zf, R);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication.
-*/
+ * This instruction performs 8-bit x 8-bit -> 16-bit signed multiplication.
+ */
int avr_translate_MULS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_MUL) == false) {
@@ -1810,9 +1809,9 @@ int avr_translate_MULS(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv t0 = tcg_temp_new_i32();
TCGv t1 = tcg_temp_new_i32();
- tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
- tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
- tcg_gen_mul_tl(R, t0, t1); /* R = Rd * Rr */
+ tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+ tcg_gen_ext8s_tl(t1, Rr); /* make Rr full 32 bit signed */
+ tcg_gen_mul_tl(R, t0, t1); /* R = Rd * Rr */
tcg_gen_mov_tl(R0, R);
tcg_gen_andi_tl(R0, R0, 0xff);
@@ -1820,20 +1819,20 @@ int avr_translate_MULS(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_mov_tl(R1, R);
tcg_gen_andi_tl(R1, R0, 0xff);
- tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
+ tcg_gen_shri_tl(cpu_Cf, R, 15); /* Cf = R(16) */
tcg_gen_mov_tl(cpu_Zf, R);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a
- signed and an unsigned number.
-*/
+ * This instruction performs 8-bit x 8-bit -> 16-bit multiplication of a
+ * signed and an unsigned number.
+ */
int avr_translate_MULSU(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_MUL) == false) {
@@ -1849,8 +1848,8 @@ int avr_translate_MULSU(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv R = tcg_temp_new_i32();
TCGv t0 = tcg_temp_new_i32();
- tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
- tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
+ tcg_gen_ext8s_tl(t0, Rd); /* make Rd full 32 bit signed */
+ tcg_gen_mul_tl(R, t0, Rr); /* R = Rd *Rr */
tcg_gen_mov_tl(R0, R);
tcg_gen_andi_tl(R0, R0, 0xff);
@@ -1858,57 +1857,57 @@ int avr_translate_MULSU(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_mov_tl(R1, R);
tcg_gen_andi_tl(R1, R0, 0xff);
- tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
+ tcg_gen_shri_tl(cpu_Cf, R, 16); /* Cf = R(16) */
tcg_gen_mov_tl(cpu_Zf, R);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Replaces the contents of register Rd with its two’s complement; the
- value $80 is left unchanged.
-*/
+ * Replaces the contents of register Rd with its two’s complement; the
+ * value $80 is left unchanged.
+ */
int avr_translate_NEG(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[SUB_Rd(opcode)];
TCGv t0 = tcg_const_i32(0);
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_sub_tl(R, t0, Rd); /* R = 0 - Rd */
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ /* op */
+ tcg_gen_sub_tl(R, t0, Rd); /* R = 0 - Rd */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_sub_CHf(R, t0, Rd);
gen_sub_Vf(R, t0, Rd);
gen_ZNSf(R);
- /* R */
+ /* R */
tcg_gen_mov_tl(Rd, R);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction performs a single cycle No Operation.
-*/
+ * This instruction performs a single cycle No Operation.
+ */
int avr_translate_NOP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
- /* NOP */
+ /* NOP */
- return BS_NONE;
+ return BS_NONE;
}
/*
- Performs the logical OR between the contents of register Rd and register
- Rr and places the result in the destination register Rd.
-*/
+ * Performs the logical OR between the contents of register Rd and register
+ * Rr and places the result in the destination register Rd.
+ */
int avr_translate_OR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[OR_Rd(opcode)];
@@ -1922,29 +1921,30 @@ int avr_translate_OR(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Performs the logical OR between the contents of register Rd and a
- constant and places the result in the destination register Rd.
-*/
+ * Performs the logical OR between the contents of register Rd and a
+ * constant and places the result in the destination register Rd.
+ */
int avr_translate_ORI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[16 + ORI_Rd(opcode)];
int Imm = (ORI_Imm(opcode));
- tcg_gen_ori_tl(Rd, Rd, Imm); /* Rd = Rd | Imm */
+ tcg_gen_ori_tl(Rd, Rd, Imm); /* Rd = Rd | Imm */
- tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
+ tcg_gen_movi_tl(cpu_Vf, 0x00); /* Vf = 0 */
gen_ZNSf(Rd);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Stores data from register Rr in the Register File to I/O Space (Ports,
- Timers, Configuration Registers, etc.). */
+ * Stores data from register Rr in the Register File to I/O Space (Ports,
+ * Timers, Configuration Registers, etc.).
+ */
int avr_translate_OUT(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[OUT_Rd(opcode)];
@@ -1955,15 +1955,15 @@ int avr_translate_OUT(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_mov_tl(data, Rd);
gen_helper_outb(cpu_env, port, data);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction loads register Rd with a byte from the STACK. The Stack
- Pointer is pre-incremented by 1 before the POP. This instruction is not
- available in all devices. Refer to the device specific instruction set
- summary.
-*/
+ * This instruction loads register Rd with a byte from the STACK. The Stack
+ * Pointer is pre-incremented by 1 before the POP. This instruction is not
+ * available in all devices. Refer to the device specific instruction set
+ * summary.
+ */
int avr_translate_POP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[POP_Rd(opcode)];
@@ -1971,15 +1971,15 @@ int avr_translate_POP(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
gen_data_load(ctx, Rd, cpu_sp);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction stores the contents of register Rr on the STACK. The
- Stack Pointer is post-decremented by 1 after the PUSH. This instruction is
- not available in all devices. Refer to the device specific instruction set
- summary.
-*/
+ * This instruction stores the contents of register Rr on the STACK. The
+ * Stack Pointer is post-decremented by 1 after the PUSH. This instruction is
+ * not available in all devices. Refer to the device specific instruction set
+ * summary.
+ */
int avr_translate_PUSH(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[PUSH_Rd(opcode)];
@@ -1987,17 +1987,17 @@ int avr_translate_PUSH(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
gen_data_store(ctx, Rd, cpu_sp);
tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Relative call to an address within PC - 2K + 1 and PC + 2K (words). The
- return address (the instruction after the RCALL) is stored onto the Stack.
- See also CALL. For AVR microcontrollers with Program memory not exceeding
4K
- words (8KB) this instruction can address the entire memory from every
- address location. The Stack Pointer uses a post-decrement scheme during
- RCALL.
-*/
+ * Relative call to an address within PC - 2K + 1 and PC + 2K (words). The
+ * return address (the instruction after the RCALL) is stored onto the Stack.
+ * See also CALL. For AVR microcontrollers with Program memory not exceeding
4K
+ * words (8KB) this instruction can address the entire memory from every
+ * address location. The Stack Pointer uses a post-decrement scheme during
+ * RCALL.
+ */
int avr_translate_RCALL(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
int ret = ctx->inst[0].npc;
@@ -2007,30 +2007,30 @@ int avr_translate_RCALL(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
gen_goto_tb(env, ctx, 0, dst);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- Returns from subroutine. The return address is loaded from the STACK.
- The Stack Pointer uses a preincrement scheme during RET.
-*/
+ * Returns from subroutine. The return address is loaded from the STACK.
+ * The Stack Pointer uses a preincrement scheme during RET.
+ */
int avr_translate_RET(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
gen_pop_ret(env, cpu_pc);
tcg_gen_exit_tb(0);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- Returns from interrupt. The return address is loaded from the STACK and
- the Global Interrupt Flag is set. Note that the Status Register is not
- automatically stored when entering an interrupt routine, and it is not
- restored when returning from an interrupt routine. This must be handled by
- the application program. The Stack Pointer uses a pre-increment scheme
- during RETI.
-*/
+ * Returns from interrupt. The return address is loaded from the STACK and
+ * the Global Interrupt Flag is set. Note that the Status Register is not
+ * automatically stored when entering an interrupt routine, and it is not
+ * restored when returning from an interrupt routine. This must be handled by
+ * the application program. The Stack Pointer uses a pre-increment scheme
+ * during RETI.
+ */
int avr_translate_RETI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
gen_pop_ret(env, cpu_pc);
@@ -2039,31 +2039,31 @@ int avr_translate_RETI(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_exit_tb(0);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- Relative jump to an address within PC - 2K +1 and PC + 2K (words). For
- AVR microcontrollers with Program memory not exceeding 4K words (8KB) this
- instruction can address the entire memory from every address location. See
- also JMP.
-*/
+ * Relative jump to an address within PC - 2K +1 and PC + 2K (words). For
+ * AVR microcontrollers with Program memory not exceeding 4K words (8KB) this
+ * instruction can address the entire memory from every address location. See
+ * also JMP.
+ */
int avr_translate_RJMP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
int dst = ctx->inst[0].npc + sextract32(RJMP_Imm(opcode), 0, 12);
gen_goto_tb(env, ctx, 0, dst);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- Shifts all bits in Rd one place to the right. The C Flag is shifted into
- bit 7 of Rd. Bit 0 is shifted into the C Flag. This operation, combined
- with ASR, effectively divides multi-byte signed values by two. Combined
with
- LSR it effectively divides multi-byte unsigned values by two. The Carry
Flag
- can be used to round the result.
-*/
+ * Shifts all bits in Rd one place to the right. The C Flag is shifted into
+ * bit 7 of Rd. Bit 0 is shifted into the C Flag. This operation, combined
+ * with ASR, effectively divides multi-byte signed values by two. Combined
with
+ * LSR it effectively divides multi-byte unsigned values by two. The Carry
Flag
+ * can be used to round the result.
+ */
int avr_translate_ROR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[ROR_Rd(opcode)];
@@ -2079,65 +2079,66 @@ int avr_translate_ROR(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(t0);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Subtracts two registers and subtracts with the C Flag and places the
- result in the destination register Rd.
-*/
+ * Subtracts two registers and subtracts with the C Flag and places the
+ * result in the destination register Rd.
+ */
int avr_translate_SBC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[SBC_Rd(opcode)];
TCGv Rr = cpu_r[SBC_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+ /* op */
+ tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
tcg_gen_sub_tl(R, R, cpu_Cf);
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_sub_CHf(R, Rd, Rr);
gen_sub_Vf(R, Rd, Rr);
gen_ZNSf(R);
- /* R */
+ /* R */
tcg_gen_mov_tl(Rd, R);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- SBCI – Subtract Immediate with Carry
-*/
+ * SBCI – Subtract Immediate with Carry
+ */
int avr_translate_SBCI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[16 + SBCI_Rd(opcode)];
TCGv Rr = tcg_const_i32(SBCI_Imm(opcode));
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
+ /* op */
+ tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr - Cf */
tcg_gen_sub_tl(R, R, cpu_Cf);
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_sub_CHf(R, Rd, Rr);
gen_sub_Vf(R, Rd, Rr);
gen_ZNSf(R);
- /* R */
+ /* R */
tcg_gen_mov_tl(Rd, R);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Sets a specified bit in an I/O Register. This instruction operates on
- the lower 32 I/O Registers – addresses 0-31. */
+ * Sets a specified bit in an I/O Register. This instruction operates on
+ * the lower 32 I/O Registers – addresses 0-31.
+ */
int avr_translate_SBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv data = cpu_io[SBI_Imm(opcode)];
@@ -2146,62 +2147,64 @@ int avr_translate_SBI(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_gen_ori_tl(data, data, 1 << SBI_Bit(opcode));
gen_helper_outb(cpu_env, port, data);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction tests a single bit in an I/O Register and skips the
- next instruction if the bit is cleared. This instruction operates on the
- lower 32 I/O Registers – addresses 0-31. */
+ * This instruction tests a single bit in an I/O Register and skips the
+ * next instruction if the bit is cleared. This instruction operates on the
+ * lower 32 I/O Registers – addresses 0-31.
+ */
int avr_translate_SBIC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv io = cpu_io[SBIC_Imm(opcode)];
TCGv t0 = tcg_temp_new_i32();
- TCGLabel *skip = gen_new_label();
+ TCGLabel *skip = gen_new_label();
- /* PC if next inst is skipped */
+ /* PC if next inst is skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
tcg_gen_andi_tl(t0, io, 1 << SBIC_Bit(opcode));
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, skip);
- /* PC if next inst is not skipped */
+ /* PC if next inst is not skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
gen_set_label(skip);
tcg_temp_free_i32(t0);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- This instruction tests a single bit in an I/O Register and skips the
- next instruction if the bit is set. This instruction operates on the lower
- 32 I/O Registers – addresses 0-31. */
+ * This instruction tests a single bit in an I/O Register and skips the
+ * next instruction if the bit is set. This instruction operates on the lower
+ * 32 I/O Registers – addresses 0-31.
+ */
int avr_translate_SBIS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv io = cpu_io[SBIS_Imm(opcode)];
TCGv t0 = tcg_temp_new_i32();
- TCGLabel *skip = gen_new_label();
+ TCGLabel *skip = gen_new_label();
- /* PC if next inst is skipped */
+ /* PC if next inst is skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
tcg_gen_andi_tl(t0, io, 1 << SBIS_Bit(opcode));
tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, skip);
- /* PC if next inst is not skipped */
+ /* PC if next inst is not skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
gen_set_label(skip);
tcg_temp_free_i32(t0);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- Subtracts an immediate value (0-63) from a register pair and places the
- result in the register pair. This instruction operates on the upper four
- register pairs, and is well suited for operations on the Pointer Registers.
- This instruction is not available in all devices. Refer to the device
- specific instruction set summary.
-*/
+ * Subtracts an immediate value (0-63) from a register pair and places the
+ * result in the register pair. This instruction operates on the upper four
+ * register pairs, and is well suited for operations on the Pointer Registers.
+ * This instruction is not available in all devices. Refer to the device
+ * specific instruction set summary.
+ */
int avr_translate_SBIW(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_ADIW_SBIW) == false) {
@@ -2216,112 +2219,112 @@ int avr_translate_SBIW(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv R = tcg_temp_new_i32();
TCGv Rd = tcg_temp_new_i32();
- /* op */
- tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
- tcg_gen_subi_tl(R, Rd, Imm); /* R = Rd - Imm */
- tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
+ /* op */
+ tcg_gen_deposit_tl(Rd, RdL, RdH, 8, 8); /* Rd = RdH:RdL */
+ tcg_gen_subi_tl(R, Rd, Imm); /* R = Rd - Imm */
+ tcg_gen_andi_tl(R, R, 0xffff); /* make it 16 bits */
- /* Cf */
+ /* Cf */
tcg_gen_andc_tl(cpu_Cf, R, Rd);
- tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15); /* Cf = R & ~Rd */
+ tcg_gen_shri_tl(cpu_Cf, cpu_Cf, 15); /* Cf = R & ~Rd */
- /* Vf */
+ /* Vf */
tcg_gen_andc_tl(cpu_Vf, Rd, R);
- tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15); /* Vf = Rd & ~R */
+ tcg_gen_shri_tl(cpu_Vf, cpu_Vf, 15); /* Vf = Rd & ~R */
- /* Zf */
- tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
+ /* Zf */
+ tcg_gen_mov_tl(cpu_Zf, R); /* Zf = R */
- /* Nf */
- tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
+ /* Nf */
+ tcg_gen_shri_tl(cpu_Nf, R, 15); /* Nf = R(15) */
- /* Sf */
- tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+ /* Sf */
+ tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
- /* R */
+ /* R */
tcg_gen_andi_tl(RdL, R, 0xff);
tcg_gen_shri_tl(RdH, R, 8);
tcg_temp_free_i32(Rd);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction tests a single bit in a register and skips the next
- instruction if the bit is cleared.
-*/
+ * This instruction tests a single bit in a register and skips the next
+ * instruction if the bit is cleared.
+ */
int avr_translate_SBRC(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rr = cpu_r[SBRC_Rr(opcode)];
TCGv t0 = tcg_temp_new_i32();
TCGLabel *skip = gen_new_label();
- /* PC if next inst is skipped */
+ /* PC if next inst is skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
tcg_gen_andi_tl(t0, Rr, 1 << SBRC_Bit(opcode));
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, skip);
- /* PC if next inst is not skipped */
+ /* PC if next inst is not skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
gen_set_label(skip);
tcg_temp_free_i32(t0);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- This instruction tests a single bit in a register and skips the next
- instruction if the bit is set.
-*/
+ * This instruction tests a single bit in a register and skips the next
+ * instruction if the bit is set.
+ */
int avr_translate_SBRS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rr = cpu_r[SBRS_Rr(opcode)];
TCGv t0 = tcg_temp_new_i32();
- TCGLabel *skip = gen_new_label();
+ TCGLabel *skip = gen_new_label();
- /* PC if next inst is skipped */
+ /* PC if next inst is skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[1].npc);
tcg_gen_andi_tl(t0, Rr, 1 << SBRS_Bit(opcode));
tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, skip);
- /* PC if next inst is not skipped */
+ /* PC if next inst is not skipped */
tcg_gen_movi_tl(cpu_pc, ctx->inst[0].npc);
gen_set_label(skip);
tcg_temp_free_i32(t0);
- return BS_BRANCH;
+ return BS_BRANCH;
}
/*
- This instruction sets the circuit in sleep mode defined by the MCU
- Control Register.
-*/
+ * This instruction sets the circuit in sleep mode defined by the MCU
+ * Control Register.
+ */
int avr_translate_SLEEP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
gen_helper_sleep(cpu_env);
- return BS_EXCP;
-}
-
-/*
- SPM can be used to erase a page in the Program memory, to write a page
- in the Program memory (that is already erased), and to set Boot Loader Lock
- bits. In some devices, the Program memory can be written one word at a
time,
- in other devices an entire page can be programmed simultaneously after
first
- filling a temporary page buffer. In all cases, the Program memory must be
- erased one page at a time. When erasing the Program memory, the RAMPZ and
- Z-register are used as page address. When writing the Program memory, the
- RAMPZ and Z-register are used as page or word address, and the R1:R0
- register pair is used as data(1). When setting the Boot Loader Lock bits,
- the R1:R0 register pair is used as data. Refer to the device documentation
- for detailed description of SPM usage. This instruction can address the
- entire Program memory. The SPM instruction is not available in all
devices.
- Refer to the device specific instruction set summary. Note: 1. R1
- determines the instruction high byte, and R0 determines the instruction low
- byte.
-*/
+ return BS_EXCP;
+}
+
+/*
+ * SPM can be used to erase a page in the Program memory, to write a page
+ * in the Program memory (that is already erased), and to set Boot Loader Lock
+ * bits. In some devices, the Program memory can be written one word at a
time,
+ * in other devices an entire page can be programmed simultaneously after
first
+ * filling a temporary page buffer. In all cases, the Program memory must be
+ * erased one page at a time. When erasing the Program memory, the RAMPZ and
+ * Z-register are used as page address. When writing the Program memory, the
+ * RAMPZ and Z-register are used as page or word address, and the R1:R0
+ * register pair is used as data(1). When setting the Boot Loader Lock bits,
+ * the R1:R0 register pair is used as data. Refer to the device documentation
+ * for detailed description of SPM usage. This instruction can address the
+ * entire Program memory. The SPM instruction is not available in all
devices.
+ * Refer to the device specific instruction set summary. Note: 1. R1
+ * determines the instruction high byte, and R0 determines the instruction low
+ * byte.
+ */
int avr_translate_SPM(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_SPM) == false) {
@@ -2330,8 +2333,8 @@ int avr_translate_SPM(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
return BS_EXCP;
}
- /* TODO: ??? */
- return BS_NONE;
+ /* TODO: ??? */
+ return BS_NONE;
}
int avr_translate_SPMX(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2342,8 +2345,8 @@ int avr_translate_SPMX(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
return BS_EXCP;
}
- /* TODO: ??? */
- return BS_NONE;
+ /* TODO: ??? */
+ return BS_NONE;
}
int avr_translate_STX1(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2355,7 +2358,7 @@ int avr_translate_STX1(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_STX2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2364,12 +2367,12 @@ int avr_translate_STX2(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv addr = gen_get_xaddr();
gen_data_store(ctx, Rd, addr);
- tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+ tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
gen_set_xaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_STX3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2377,13 +2380,13 @@ int avr_translate_STX3(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[STX3_Rr(opcode)];
TCGv addr = gen_get_xaddr();
- tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+ tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
gen_data_store(ctx, Rd, addr);
gen_set_xaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_STY2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2392,12 +2395,12 @@ int avr_translate_STY2(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv addr = gen_get_yaddr();
gen_data_store(ctx, Rd, addr);
- tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+ tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
gen_set_yaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_STY3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2405,13 +2408,13 @@ int avr_translate_STY3(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[STY3_Rd(opcode)];
TCGv addr = gen_get_yaddr();
- tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+ tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
gen_data_store(ctx, Rd, addr);
gen_set_yaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_STDY(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2420,12 +2423,12 @@ int avr_translate_STDY(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv addr = gen_get_yaddr();
tcg_gen_addi_tl(addr, addr, STDY_Imm(opcode));
- /* addr = addr + q */
+ /* addr = addr + q */
gen_data_store(ctx, Rd, addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_STZ2(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2434,13 +2437,13 @@ int avr_translate_STZ2(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv addr = gen_get_zaddr();
gen_data_store(ctx, Rd, addr);
- tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
+ tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
gen_set_zaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_STZ3(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2448,14 +2451,14 @@ int avr_translate_STZ3(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv Rd = cpu_r[STZ3_Rd(opcode)];
TCGv addr = gen_get_zaddr();
- tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
+ tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
gen_data_store(ctx, Rd, addr);
gen_set_zaddr(addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
int avr_translate_STDZ(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
@@ -2464,33 +2467,33 @@ int avr_translate_STDZ(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
TCGv addr = gen_get_zaddr();
tcg_gen_addi_tl(addr, addr, STDZ_Imm(opcode));
- /* addr = addr + q */
+ /* addr = addr + q */
gen_data_store(ctx, Rd, addr);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Stores one byte from a Register to the data space. For parts with SRAM,
- the data space consists of the Register File, I/O memory and internal SRAM
- (and external SRAM if applicable). For parts without SRAM, the data space
- consists of the Register File only. The EEPROM has a separate address
space.
- A 16-bit address must be supplied. Memory access is limited to the current
- data segment of 64KB. The STS instruction uses the RAMPD Register to access
- memory above 64KB. To access another data segment in devices with more than
- 64KB data space, the RAMPD in register in the I/O area has to be changed.
- This instruction is not available in all devices. Refer to the device
- specific instruction set summary.
-*/
+ * Stores one byte from a Register to the data space. For parts with SRAM,
+ * the data space consists of the Register File, I/O memory and internal SRAM
+ * (and external SRAM if applicable). For parts without SRAM, the data space
+ * consists of the Register File only. The EEPROM has a separate address
space.
+ * A 16-bit address must be supplied. Memory access is limited to the current
+ * data segment of 64KB. The STS instruction uses the RAMPD Register to access
+ * memory above 64KB. To access another data segment in devices with more than
+ * 64KB data space, the RAMPD in register in the I/O area has to be changed.
+ * This instruction is not available in all devices. Refer to the device
+ * specific instruction set summary.
+ */
int avr_translate_STS(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[STS_Rd(opcode)];
TCGv addr = tcg_temp_new_i32();
TCGv H = cpu_rampD;
- tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
+ tcg_gen_mov_tl(addr, H); /* addr = H:M:L */
tcg_gen_shli_tl(addr, addr, 16);
tcg_gen_ori_tl(addr, addr, STS_Imm(opcode));
@@ -2498,67 +2501,67 @@ int avr_translate_STS(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Subtracts two registers and places the result in the destination
- register Rd.
-*/
+ * Subtracts two registers and places the result in the destination
+ * register Rd.
+ */
int avr_translate_SUB(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[SUB_Rd(opcode)];
TCGv Rr = cpu_r[SUB_Rr(opcode)];
TCGv R = tcg_temp_new_i32();
- /* op */
- tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ /* op */
+ tcg_gen_sub_tl(R, Rd, Rr); /* R = Rd - Rr */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_sub_CHf(R, Rd, Rr);
gen_sub_Vf(R, Rd, Rr);
gen_ZNSf(R);
- /* R */
+ /* R */
tcg_gen_mov_tl(Rd, R);
tcg_temp_free_i32(R);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Subtracts a register and a constant and places the result in the
- destination register Rd. This instruction is working on Register R16 to R31
- and is very well suited for operations on the X, Y, and Z-pointers.
-*/
+ * Subtracts a register and a constant and places the result in the
+ * destination register Rd. This instruction is working on Register R16 to R31
+ * and is very well suited for operations on the X, Y, and Z-pointers.
+ */
int avr_translate_SUBI(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[16 + SUBI_Rd(opcode)];
TCGv Rr = tcg_const_i32(SUBI_Imm(opcode));
TCGv R = tcg_temp_new_i32();
- /* op */
+ /* op */
tcg_gen_sub_tl(R, Rd, Rr);
- /* R = Rd - Imm */
- tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
+ /* R = Rd - Imm */
+ tcg_gen_andi_tl(R, R, 0xff); /* make it 8 bits */
gen_sub_CHf(R, Rd, Rr);
gen_sub_Vf(R, Rd, Rr);
gen_ZNSf(R);
- /* R */
+ /* R */
tcg_gen_mov_tl(Rd, R);
tcg_temp_free_i32(R);
tcg_temp_free_i32(Rr);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Swaps high and low nibbles in a register.
-*/
+ * Swaps high and low nibbles in a register.
+ */
int avr_translate_SWAP(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
TCGv Rd = cpu_r[SWAP_Rd(opcode)];
@@ -2574,30 +2577,30 @@ int avr_translate_SWAP(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
- return BS_NONE;
+ return BS_NONE;
}
/*
- This instruction resets the Watchdog Timer. This instruction must be
- executed within a limited time given by the WD prescaler. See the Watchdog
- Timer hardware specification.
-*/
+ * This instruction resets the Watchdog Timer. This instruction must be
+ * executed within a limited time given by the WD prescaler. See the Watchdog
+ * Timer hardware specification.
+ */
int avr_translate_WDR(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
gen_helper_wdr(cpu_env);
- return BS_NONE;
+ return BS_NONE;
}
/*
- Exchanges one byte indirect between register and data space. The data
- location is pointed to by the Z (16 bits) Pointer Register in the Register
- File. Memory access is limited to the current data segment of 64KB. To
- access another data segment in devices with more than 64KB data space, the
- RAMPZ in register in the I/O area has to be changed. The Z-pointer
Register
- is left unchanged by the operation. This instruction is especially suited
- for writing/reading status bits stored in SRAM.
-*/
+ * Exchanges one byte indirect between register and data space. The data
+ * location is pointed to by the Z (16 bits) Pointer Register in the Register
+ * File. Memory access is limited to the current data segment of 64KB. To
+ * access another data segment in devices with more than 64KB data space, the
+ * RAMPZ in register in the I/O area has to be changed. The Z-pointer
Register
+ * is left unchanged by the operation. This instruction is especially suited
+ * for writing/reading status bits stored in SRAM.
+ */
int avr_translate_XCH(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
{
if (avr_feature(env, AVR_FEATURE_RMW) == false) {
@@ -2617,6 +2620,6 @@ int avr_translate_XCH(CPUAVRState *env, DisasContext
*ctx, uint32_t opcode)
tcg_temp_free_i32(t0);
tcg_temp_free_i32(addr);
- return BS_NONE;
+ return BS_NONE;
}
diff --git a/target-avr/translate.c b/target-avr/translate.c
index 88e2e24..1bc979b 100644
--- a/target-avr/translate.c
+++ b/target-avr/translate.c
@@ -90,18 +90,6 @@ void avr_translate_init(void)
done_init = 1;
}
-static int translate_nop(CPUAVRState *env, DisasContext *ctx, uint32_t opcode)
-{
- return BS_NONE;
-}
-
-void avr_decode(uint32_t pc, uint32_t *length, uint32_t opcode,
- translate_function_t *translate)
-{
- *length = 32;
- *translate = &translate_nop;
-}
-
static void decode_opc(AVRCPU *cpu, DisasContext *ctx, InstInfo *inst)
{
CPUAVRState *env = &cpu->env;
@@ -154,8 +142,8 @@ void gen_intermediate_code(CPUAVRState *env, struct
TranslationBlock *tb)
if (tb->flags & TB_FLAGS_FULL_ACCESS) {
/*
this flag is set by ST/LD instruction
- we will regenerate ONLY it with mem/cpu memory access
- insttead of mem access
+ we will regenerate it ONLY with mem/cpu memory access
+ instead of mem access
*/
max_insns = 1;
}
@@ -178,14 +166,17 @@ void gen_intermediate_code(CPUAVRState *env, struct
TranslationBlock *tb)
tcg_gen_insn_start(cpc);
num_insns++;
- if (unlikely(cpu_breakpoint_test(cs, cpc * 2, BP_ANY))) {
+ /*
+ * this is due to some strange GDB behavior
+ * let's assume main is has 0x100 address
+ * b main - sets a breakpoint to 0x00000100 address (code)
+ * b *0x100 - sets a breakpoint to 0x00800100 address (data)
+ */
+ if (unlikely(cpu_breakpoint_test(cs, PHYS_BASE_CODE + cpc * 2, BP_ANY))
+ || cpu_breakpoint_test(cs, PHYS_BASE_DATA + cpc * 2, BP_ANY))
{
tcg_gen_movi_i32(cpu_pc, cpc);
gen_helper_debug(cpu_env);
ctx.bstate = BS_EXCP;
- /* The address covered by the breakpoint must be included in
- [tb->pc, tb->pc + tb->size) in order to for it to be
- properly cleared -- thus we increment the PC here so that
- the logic setting tb->size below does the right thing. */
goto done_generating;
}
--
2.4.9 (Apple Git-60)
- [Qemu-devel] [PATCH v13 0/9] 8bit AVR cores, Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 2/9] target-avr: adding AVR CPU features/flavors, Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 5/9] target-avr: adding AVR interrupt handling, Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 1/9] target-avr: AVR cores support is added., Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 6/9] target-avr: adding helpers for IN, OUT, SLEEP, WBR & unsupported instructions, Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 3/9] target-avr: adding a sample AVR board, Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 4/9] target-avr: adding instructions encodings, Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 8/9] target-avr: instruction decoder generator, Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 7/9] target-avr: adding instruction translation, Michael Rolnik, 2016/07/25
- [Qemu-devel] [PATCH v13 9/9] target-avr: adding instruction decoder,
Michael Rolnik <=