From patchwork Tue Jul 26 03:50:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Michael Rolnik X-Patchwork-Id: 9247589 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AE36C60757 for ; Tue, 26 Jul 2016 04:02:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 92E4B212D9 for ; Tue, 26 Jul 2016 04:02:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 86510252D2; Tue, 26 Jul 2016 04:02:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, NORMAL_HTTP_TO_IP, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B0563212D9 for ; Tue, 26 Jul 2016 04:02:52 +0000 (UTC) Received: from localhost ([::1]:37315 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bRtZz-0005bt-O2 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 26 Jul 2016 00:02:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50484) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bRtOk-0004tB-DP for qemu-devel@nongnu.org; Mon, 25 Jul 2016 23:51:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bRtOW-0001ST-HF for qemu-devel@nongnu.org; Mon, 25 Jul 2016 23:51:13 -0400 Received: from mail-wm0-x244.google.com ([2a00:1450:400c:c09::244]:33929) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bRtOV-0001SO-P4 for qemu-devel@nongnu.org; Mon, 25 Jul 2016 23:51:00 -0400 Received: by mail-wm0-x244.google.com with SMTP id q128so19423092wma.1 for ; Mon, 25 Jul 2016 20:50:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PQDHNPXDhGuHoq3XWAYnrJFydcmnVPGsA0MWvTrI7bo=; b=uP7dJYFO1nicjjViFwaOQcVB3CPqxfX1+386vniLQ4KzLqBKkVvbMGvb0DYBPZCEX4 GIT2dzIHiwANz8gJWmR70DLso11IReggeXTyHBl2J6iOy0NSNNl/iWU9aYvY5/pCdUX1 FahVSQj/jq7fMU8BE1qD9tDnorQOyv37ZRwe+d7xbhFXlMkkgtytlD+p1t1a5eF3Rpcc X6sjU/DYuvvhYDqeXBVN8noevkVynblAbtdBR+8bjfOUfwrf2ZbpPHCzzfGdeZN/CjDo 4QYQU/1af0y4nwYZxyvmreYuXHWK/bam4AO0CkiKJHYq592xxWZc0+t0Dwz3dTe1TRGz pUNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PQDHNPXDhGuHoq3XWAYnrJFydcmnVPGsA0MWvTrI7bo=; b=k7XSU8uaJ1BJ80t47iP81oe5ucSbvg1yjip04Zm5in3iCQLYTFGimU9/Cu33ag+4uj dY1UeSQjxLjNfKA0cvqZp7gSt88uzITVB3hGwe2MfHU3BhC3iGmM/8nv7xn6diq3q1Bs cB0FT2T51dA1JyLmTd1VKS+dvPAAYQ4kdEyj/TJR5xgOEbIJmLJykn+UOy3zNMra55+9 GAH0G0beQfkUkUtlJou3jZITf0ckqqQMIRoIzeJFq0jhTgWscLjCIyzqFTIR+gkmic/M WD9PlU97I+K7fZYl2Yp0L/lQrRU7DJcDBVRXx0WE4h5uAUJHtO4cNVuWpicnxrdz/Q7d yWSA== X-Gm-Message-State: AEkoouvbVkZ9QJpJT8650mg1YtoO0WksFD1/nE+eGPoyd6rqEdtYwktJ7Wb/L5EfVnmh+A== X-Received: by 10.28.109.214 with SMTP id b83mr22631947wmi.19.1469505056932; Mon, 25 Jul 2016 20:50:56 -0700 (PDT) Received: from a0999b0126e1.ant.amazon.com ([31.210.187.232]) by smtp.gmail.com with ESMTPSA id g8sm18860757wjj.48.2016.07.25.20.50.55 (version=TLS1 cipher=AES128-SHA bits=128/128); Mon, 25 Jul 2016 20:50:56 -0700 (PDT) From: Michael Rolnik To: qemu-devel@nongnu.org Date: Tue, 26 Jul 2016 06:50:14 +0300 Message-Id: <1469505014-62480-10-git-send-email-mrolnik@gmail.com> X-Mailer: git-send-email 2.4.9 (Apple Git-60) In-Reply-To: <1469505014-62480-1-git-send-email-mrolnik@gmail.com> References: <1469505014-62480-1-git-send-email-mrolnik@gmail.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::244 Subject: [Qemu-devel] [PATCH v13 9/9] target-avr: adding instruction decoder X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, Michael Rolnik , rth@twiddle.net Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Michael Rolnik --- 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>C`}@7`y?)>K-ejqAVscu&qu5)ZdK(fL{u4!=BH-x#W$ z?+hok&T5$GkM;J(YS+VwcwwpZKxRbBV1 z?f1mqf4=Ma(3imff&^;IL2y0!-YgCP_Wzyz|GlRL!8hR%_y~LmHenZh>Zw8SS{R4N z!{gu&t_y<8a0is&pPmu~_rMYO_LGC)9q>lD8-4>`1xk02X@1^o)`q5 zfj@)y!2|FXcr)A&zX-2^Uw}n81vkRe;44oEf-l4G!@ckdScVfY4ljY5;Dzu!crH90 zo(k8&m#?9{@Yiq`+zD&20wElQBk)AH20ntb<;@VnGL&EsTnC@WQS;~UZa51+3zM)P zo&%r55%YFv!j16n^!vx)VYmVSX_ZaFl8X_=XKKxhXId-8f+`FSdU@F_I$^s}tA}T5jYct- zL19P@6-ufwG*s}DT~-&?qDH8SwuUzx@XIBptE=1}wTuxpB4vz>NEug{vZ7N~t~h1I zlv%m*GAl}#S-J8um6FQR1Nl~_z3fRoi?Q5Nm$JU!h?>cZ_MS=9Qk1k-R^l*04=P#g zBx+vVTyN|h9ldROs@e$UB#_$OM2ikPtyyl>%QN8x`>y~@Hwb4vMI!zapiBC&m=MJz* z_w31p>kC$L=qW>K10q!0Nl+5yo2@IObwQ*dO|@m~tkAbKh-om+1dwW)siD?NJ0N-SU%*F+EP2=YPe~NN|Wt3q8-aJVse(r!4HXA>$PS?4YOov3;aOjM5mV5{IEu} zPWSpDD-^)I;|E1DBXxz<$*mDB`OzdOY9T1Kdl=Nh(W;uCJ-l#oe6CuSfZ5{d@@WO!d&hf`fO`8dnxIWqCQ}Nch=n=6mej)R97WrlPEO8OOKN;>a-Qte;knuAlB@3c@r9$a zbMq4Q(Co2ObCXAoE~ulkQxjDJ4_0-dQ&n}C=i@V{)S;>I$?1}s7@r zlM6G|`FRsn9UGrpm^^fRYJ5%|J3e=8mUfNLOsJXJnaP>Mb5x@`U7cAdi(F=ARrLg4 z)cn!$sVT{7a{AcRWObs%(?e6oC#2E`k>t$m0`-}mT&PaaJ}oaKJvTnHFe!C8tfs4T zhmP{q$;ma+^@*CCSI6dNPfSjbLtz}j&a-%u&XA6>d7YA+q^-A3&QOKwZO7)MS+jHG zCKF6l;zzOKWxgK8G1G^86t78fOCeK>9@+UAa+dgR6hOo+VS0mZ?V~x0snsa=WnBTFq5J(jpG@A99E^b(47&aP`S=7uI zae*1BwUHVwK#6oBaW~y%SuO| zYByIpeF5~Zz6AOb=u6;-PXfjW%SwpTKAtv?{KlBpMLwKy#iNj72YsPn*@Mc{s5LP%XjtM?k z!$nehhL3(AVRCuS5|U$-nSiNQZ5j7rdn55YT)H)pUAVI(;3>Y!Mkp>CFPioT8L!B0 z_n3@%J)d73Ic-g@&P8V`c1bJT!~>=k($vvZxL0gX(gYIRmq+K;8Hd3wvIQc*<>-8b}ael?# znb->T$b%=6)cVf0s<1Q2an_;FPVkvpWS^wr_Nv$7&=ZFXw)aMOo~7I#wHJ$P>m}Ah znDl-WHdx7zs8^^Wi|Q5aw_6T32lJ6_pRa{$XVlypdzb~g*ctrQSapj-mcc{6 zSf7Qg<1uBL8=+AqS*?m?Yp=^HY{Zx%=&-4HS-e+FBV%gBpBp5)lgjqG6WCn!&2@Z_ z=tE;oRMvQ!o#MKryCt1WG5Uk_f;Z7fq~03hO6#E_o;aMAxx(a;(-2ee0d4+;$zsJ$ zCK7e4cn;uoO8rq1C9g;MZ}Qwqx4jXsomr~Y&*|-x#ppE6m&g7!FrbQNn`Q(R5ltCX zlt&7>U%8;c?(UIF+H@5cNvAV<2Zu|ud-Tn z+c+qVVi_&+g(e$+2rb5)S{xC#y|_SU^maq+R7X!9n7q8BAi>yY=;_Gx`D(IewKkR+ zBakY0S}nFpa<7g|=(fUHK(}ngUF(TfYj&4pw@;jIWRXL0qZvo5&2V|py~}q@7w3|Q z9Bfs4_hFV-k6ttn(|%0*5aDP6lSKQV<%^!>kvL*TotDCmOwQ{ee$M9V%7!?Bh$ONV z`~N3ckUl~7d9nZ9`Tj3r?>_|h!^@!!v+!b&GXMkdJ#7EKhkM{|sKXLe;78#fu>ao! z?}irK2;av3{}y}{9)jP2yWn;hhwI@Q_!##8!ysn`ZiDB*kHa^y{l5VZ!98#Xl;Eq_ z`Qi(>4;Dee=dkNP3-5wgLmOJ~Qjq=oz3^oC8ut9B;VrNPldum)paR#zBiQd>fqw?s ztA8u}Hq>AkzRTYGci`LbAUpuChF8HH{2V+F9>Lf0b@(`Z4DN+B*L&dI@aqu4&w%XLS6~>fg(rga?KQB|WnLTU4jntG>$P*?nRYGe z6q$&bjcc2zt{#fnD<=CSLzF1!pq?@K$gb69Ntw~?O(;4dzBw0>rK-+6NwN%zFx>y_-i!DHSQTPHic|7G@${J3^8 z!-GA0(u&(HJ6}+Y&Jb_p8MBeF-^3V0`g+SY&@C`cmG_~O+P0|>J8i$D(@EOxuAQd! z0lyuCY%!q>q6fBeydQLh#^iN99W|$Go0Hk9Z%WVJ#YbE1%0k{RrtGgyV&6CuHISID zyTsNh6x4vOWiGHwLnM)OncmFSD=eqKA{2Srz5Hs17yNLiMf%m|rhPUEy%hl^^z3M9 zp55S=<>sQXU$#FS&||M%SD&&>dimzo)djThiZ<-2jcaP&7LmNm`9+8s6TG#&Lk?Xp z${wk#d8X5J*=Hi`9x2Q~&AlD{65Tk~%DnY#g5P`Q2m%iBUgt^%blHPj)iJHAh!~49 zn=s51Bx8&O+Xd!}XAk73zWg_7^A>ww0`r#~dKgu^v}Lc?z_L~G zD7EK+o$x(Dx%exxD<8OT?!HxU^2AdG$#Yk27e?<&)<-V29-89m&_@;a$pH*k0d>}! zcwKzCi!$oo>|P_9R-lq;i@eu}%VFEpsY06%SCZ6@p00rtxFX$M_q(-XBrcli1@XGY z0>Keg*2jtDg>Ao^^Fci-B!Y97skO_JLqL(uaIejBvAHc3(ZZ(M2&OTlZbQ!*=fJz~$iX=_n<@%sV|g?T5W@bK+tMZjpj?Z#s5&>Q*N< zxp#MFWyJR8Hk~hNdi1F*&HSu-kI6t%yDJ?;ahENhKIm>_&)0f(T$CBB+qbKw(Cu!s z^{ne=n8xH^Cw6U)EXlH4kb$ee+_%26oS!qFqlm|36t1_Ei+HOMZ!RZq`Zh(nqBB!N z3QXT}-r7@Vyk+qzvE@ovt1IN_oxSykgE_J-_W!dn3~v++!JTjz_QUhwaqtCv1RsLGf;U10hu|PQ6F!fx-~;f-a4-BC{3^T(&cZy*!7R+c zbK&dw5#+Z955O%Zmc6cS+233%=2G4>o;Y)Zg$ZrIkk6}Nb2jC~+ zYWOO?ginB+FZdgHC;TqF9^`z%Pr+xcZ=udz&JFw{euMiUff$CN4F7?TK>P@=fde3C z{I7z)#6R!`cs-nh{jd+dMIXNleh+>HUI!;&3T}mc@L~{McoA%SiHc>Tz&H)OxhZ=j z5oN7D!2~k+qGxXMK6(OkcOjB6DEs$&s4-u4`|G)pMo174QSdLHXS5 zZDwvx=;_TAcf{UW&H8XX#|f(aB%@wmt zCqGMZ8wNJS*HI}(uAMWHUyI~3sa#1W94hpyAz!aBxnBX2Uuo%^Uj0d)8>OcG+e-j1 zCH+DMnP=YwJ%%n2CweZW1bFFstFr5h9;z&loDR$KLG~$RBdwAup9zs;qnqkw?EWJx z<^gUaZraFZUma<{u4Xo~Swdnf7jDnYTXq7kbXG{KB0Xeeod)TSU>kMh_|%l! z4;xfN@=KDOgmecyws<0(?eeorSy4t}=_ZRi*~~!3eanwT>@NQxM`dreI%^Xe{U<3Y z_&m=XSoVKprEgwz$9_&&eOHG^|e8n=+I_1@s?dfdB0!eGr?cuf+(x)S~aRly` z$u@7T>aw=k+QhrO(khu>McGpkX>VG=c|T*Z6K@GOqqhu7YbE=c+32&u{;${Ue}g@m zSqJ$cXSZeaxH*W6OMe*miV`idPj?tzX{>ByEjbVRHaj(TsOtV>m%Uf?K(ck0sTuuk z6ZT%B=!aP)YFAc?UeN(iGJ%tgeZaT%BS?EMv0Jr=*^Fp0+${uvyuLa zt~jVSF4FZ!%^aCZzb_5?{hj8Ke6z`jtUA>d)~9`Jlbg`lIKJP6a3Rpcb+nkK0~)RNe{sxtLr`@o6esH*MGFdx4&M 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 + * + */ + +#include +#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; }