dsp_helper.c 136 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779
  1. /*
  2. * MIPS ASE DSP Instruction emulation helpers for QEMU.
  3. *
  4. * Copyright (c) 2012 Jia Liu <proljc@gmail.com>
  5. * Dongxue Zhang <elta.era@gmail.com>
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "cpu.h"
  20. #include "helper.h"
  21. /* As the byte ordering doesn't matter, i.e. all columns are treated
  22. identically, these unions can be used directly. */
  23. typedef union {
  24. uint8_t ub[4];
  25. int8_t sb[4];
  26. uint16_t uh[2];
  27. int16_t sh[2];
  28. uint32_t uw[1];
  29. int32_t sw[1];
  30. } DSP32Value;
  31. typedef union {
  32. uint8_t ub[8];
  33. int8_t sb[8];
  34. uint16_t uh[4];
  35. int16_t sh[4];
  36. uint32_t uw[2];
  37. int32_t sw[2];
  38. uint64_t ul[1];
  39. int64_t sl[1];
  40. } DSP64Value;
  41. /*** MIPS DSP internal functions begin ***/
  42. #define MIPSDSP_ABS(x) (((x) >= 0) ? x : -x)
  43. #define MIPSDSP_OVERFLOW_ADD(a, b, c, d) (~(a ^ b) & (a ^ c) & d)
  44. #define MIPSDSP_OVERFLOW_SUB(a, b, c, d) ((a ^ b) & (a ^ c) & d)
  45. static inline void set_DSPControl_overflow_flag(uint32_t flag, int position,
  46. CPUMIPSState *env)
  47. {
  48. env->active_tc.DSPControl |= (target_ulong)flag << position;
  49. }
  50. static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
  51. {
  52. env->active_tc.DSPControl |= (target_ulong)flag << 13;
  53. }
  54. static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
  55. {
  56. return (env->active_tc.DSPControl >> 13) & 0x01;
  57. }
  58. static inline void set_DSPControl_24(uint32_t flag, int len, CPUMIPSState *env)
  59. {
  60. uint32_t filter;
  61. filter = ((0x01 << len) - 1) << 24;
  62. filter = ~filter;
  63. env->active_tc.DSPControl &= filter;
  64. env->active_tc.DSPControl |= (target_ulong)flag << 24;
  65. }
  66. static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
  67. {
  68. uint32_t filter;
  69. filter = (0x01 << len) - 1;
  70. return (env->active_tc.DSPControl >> 24) & filter;
  71. }
  72. static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
  73. {
  74. target_ulong dspc;
  75. dspc = env->active_tc.DSPControl;
  76. #ifndef TARGET_MIPS64
  77. dspc = dspc & 0xFFFFFFC0;
  78. dspc |= pos;
  79. #else
  80. dspc = dspc & 0xFFFFFF80;
  81. dspc |= pos;
  82. #endif
  83. env->active_tc.DSPControl = dspc;
  84. }
  85. static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
  86. {
  87. target_ulong dspc;
  88. uint32_t pos;
  89. dspc = env->active_tc.DSPControl;
  90. #ifndef TARGET_MIPS64
  91. pos = dspc & 0x3F;
  92. #else
  93. pos = dspc & 0x7F;
  94. #endif
  95. return pos;
  96. }
  97. static inline void set_DSPControl_efi(uint32_t flag, CPUMIPSState *env)
  98. {
  99. env->active_tc.DSPControl &= 0xFFFFBFFF;
  100. env->active_tc.DSPControl |= (target_ulong)flag << 14;
  101. }
  102. #define DO_MIPS_SAT_ABS(size) \
  103. static inline int##size##_t mipsdsp_sat_abs##size(int##size##_t a, \
  104. CPUMIPSState *env) \
  105. { \
  106. if (a == INT##size##_MIN) { \
  107. set_DSPControl_overflow_flag(1, 20, env); \
  108. return INT##size##_MAX; \
  109. } else { \
  110. return MIPSDSP_ABS(a); \
  111. } \
  112. }
  113. DO_MIPS_SAT_ABS(8)
  114. DO_MIPS_SAT_ABS(16)
  115. DO_MIPS_SAT_ABS(32)
  116. #undef DO_MIPS_SAT_ABS
  117. /* get sum value */
  118. static inline int16_t mipsdsp_add_i16(int16_t a, int16_t b, CPUMIPSState *env)
  119. {
  120. int16_t tempI;
  121. tempI = a + b;
  122. if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x8000)) {
  123. set_DSPControl_overflow_flag(1, 20, env);
  124. }
  125. return tempI;
  126. }
  127. static inline int16_t mipsdsp_sat_add_i16(int16_t a, int16_t b,
  128. CPUMIPSState *env)
  129. {
  130. int16_t tempS;
  131. tempS = a + b;
  132. if (MIPSDSP_OVERFLOW_ADD(a, b, tempS, 0x8000)) {
  133. if (a > 0) {
  134. tempS = 0x7FFF;
  135. } else {
  136. tempS = 0x8000;
  137. }
  138. set_DSPControl_overflow_flag(1, 20, env);
  139. }
  140. return tempS;
  141. }
  142. static inline int32_t mipsdsp_sat_add_i32(int32_t a, int32_t b,
  143. CPUMIPSState *env)
  144. {
  145. int32_t tempI;
  146. tempI = a + b;
  147. if (MIPSDSP_OVERFLOW_ADD(a, b, tempI, 0x80000000)) {
  148. if (a > 0) {
  149. tempI = 0x7FFFFFFF;
  150. } else {
  151. tempI = 0x80000000;
  152. }
  153. set_DSPControl_overflow_flag(1, 20, env);
  154. }
  155. return tempI;
  156. }
  157. static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
  158. {
  159. uint16_t temp;
  160. temp = (uint16_t)a + (uint16_t)b;
  161. if (temp & 0x0100) {
  162. set_DSPControl_overflow_flag(1, 20, env);
  163. }
  164. return temp & 0xFF;
  165. }
  166. static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b,
  167. CPUMIPSState *env)
  168. {
  169. uint32_t temp;
  170. temp = (uint32_t)a + (uint32_t)b;
  171. if (temp & 0x00010000) {
  172. set_DSPControl_overflow_flag(1, 20, env);
  173. }
  174. return temp & 0xFFFF;
  175. }
  176. static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b,
  177. CPUMIPSState *env)
  178. {
  179. uint8_t result;
  180. uint16_t temp;
  181. temp = (uint16_t)a + (uint16_t)b;
  182. result = temp & 0xFF;
  183. if (0x0100 & temp) {
  184. result = 0xFF;
  185. set_DSPControl_overflow_flag(1, 20, env);
  186. }
  187. return result;
  188. }
  189. static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b,
  190. CPUMIPSState *env)
  191. {
  192. uint16_t result;
  193. uint32_t temp;
  194. temp = (uint32_t)a + (uint32_t)b;
  195. result = temp & 0xFFFF;
  196. if (0x00010000 & temp) {
  197. result = 0xFFFF;
  198. set_DSPControl_overflow_flag(1, 20, env);
  199. }
  200. return result;
  201. }
  202. static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a,
  203. CPUMIPSState *env)
  204. {
  205. int64_t temp;
  206. int32_t temp32, temp31, result;
  207. int64_t temp_sum;
  208. #ifndef TARGET_MIPS64
  209. temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
  210. (uint64_t)env->active_tc.LO[acc];
  211. #else
  212. temp = (uint64_t)env->active_tc.LO[acc];
  213. #endif
  214. temp_sum = (int64_t)a + temp;
  215. temp32 = (temp_sum >> 32) & 0x01;
  216. temp31 = (temp_sum >> 31) & 0x01;
  217. result = temp_sum & 0xFFFFFFFF;
  218. /* FIXME
  219. This sat function may wrong, because user manual wrote:
  220. temp127..0 ← temp + ( (signA) || a31..0
  221. if ( temp32 ≠ temp31 ) then
  222. if ( temp32 = 0 ) then
  223. temp31..0 ← 0x80000000
  224. else
  225. temp31..0 ← 0x7FFFFFFF
  226. endif
  227. DSPControlouflag:16+acc ← 1
  228. endif
  229. */
  230. if (temp32 != temp31) {
  231. if (temp32 == 0) {
  232. result = 0x7FFFFFFF;
  233. } else {
  234. result = 0x80000000;
  235. }
  236. set_DSPControl_overflow_flag(1, 16 + acc, env);
  237. }
  238. return result;
  239. }
  240. /* a[0] is LO, a[1] is HI. */
  241. static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
  242. int32_t ac,
  243. int64_t *a,
  244. CPUMIPSState *env)
  245. {
  246. bool temp64;
  247. ret[0] = env->active_tc.LO[ac] + a[0];
  248. ret[1] = env->active_tc.HI[ac] + a[1];
  249. if (((uint64_t)ret[0] < (uint64_t)env->active_tc.LO[ac]) &&
  250. ((uint64_t)ret[0] < (uint64_t)a[0])) {
  251. ret[1] += 1;
  252. }
  253. temp64 = ret[1] & 1;
  254. if (temp64 != ((ret[0] >> 63) & 0x01)) {
  255. if (temp64) {
  256. ret[0] = (0x01ull << 63);
  257. ret[1] = ~0ull;
  258. } else {
  259. ret[0] = (0x01ull << 63) - 1;
  260. ret[1] = 0x00;
  261. }
  262. set_DSPControl_overflow_flag(1, 16 + ac, env);
  263. }
  264. }
  265. static inline void mipsdsp_sat64_acc_sub_q63(int64_t *ret,
  266. int32_t ac,
  267. int64_t *a,
  268. CPUMIPSState *env)
  269. {
  270. bool temp64;
  271. ret[0] = env->active_tc.LO[ac] - a[0];
  272. ret[1] = env->active_tc.HI[ac] - a[1];
  273. if ((uint64_t)ret[0] > (uint64_t)env->active_tc.LO[ac]) {
  274. ret[1] -= 1;
  275. }
  276. temp64 = ret[1] & 1;
  277. if (temp64 != ((ret[0] >> 63) & 0x01)) {
  278. if (temp64) {
  279. ret[0] = (0x01ull << 63);
  280. ret[1] = ~0ull;
  281. } else {
  282. ret[0] = (0x01ull << 63) - 1;
  283. ret[1] = 0x00;
  284. }
  285. set_DSPControl_overflow_flag(1, 16 + ac, env);
  286. }
  287. }
  288. static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
  289. CPUMIPSState *env)
  290. {
  291. int32_t temp;
  292. temp = (int32_t)a * (int32_t)b;
  293. if ((temp > (int)0x7FFF) || (temp < (int)0xFFFF8000)) {
  294. set_DSPControl_overflow_flag(1, 21, env);
  295. }
  296. temp &= 0x0000FFFF;
  297. return temp;
  298. }
  299. static inline int32_t mipsdsp_mul_u16_u16(int32_t a, int32_t b)
  300. {
  301. return a * b;
  302. }
  303. static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
  304. {
  305. return a * b;
  306. }
  307. static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
  308. CPUMIPSState *env)
  309. {
  310. int32_t temp;
  311. temp = (int32_t)a * (int32_t)b;
  312. if (temp > (int)0x7FFF) {
  313. temp = 0x00007FFF;
  314. set_DSPControl_overflow_flag(1, 21, env);
  315. } else if (temp < (int)0xffff8000) {
  316. temp = 0xFFFF8000;
  317. set_DSPControl_overflow_flag(1, 21, env);
  318. }
  319. temp &= 0x0000FFFF;
  320. return temp;
  321. }
  322. static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t b,
  323. CPUMIPSState *env)
  324. {
  325. int32_t temp;
  326. if ((a == 0x8000) && (b == 0x8000)) {
  327. temp = 0x7FFFFFFF;
  328. set_DSPControl_overflow_flag(1, 21, env);
  329. } else {
  330. temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
  331. }
  332. return temp;
  333. }
  334. /* right shift */
  335. static inline uint8_t mipsdsp_rshift_u8(uint8_t a, target_ulong mov)
  336. {
  337. return a >> mov;
  338. }
  339. static inline uint16_t mipsdsp_rshift_u16(uint16_t a, target_ulong mov)
  340. {
  341. return a >> mov;
  342. }
  343. static inline int8_t mipsdsp_rashift8(int8_t a, target_ulong mov)
  344. {
  345. return a >> mov;
  346. }
  347. static inline int16_t mipsdsp_rashift16(int16_t a, target_ulong mov)
  348. {
  349. return a >> mov;
  350. }
  351. static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
  352. {
  353. return a >> mov;
  354. }
  355. static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
  356. {
  357. int32_t temp;
  358. temp = (int32_t)a + (int32_t)b;
  359. return (temp >> 1) & 0xFFFF;
  360. }
  361. /* round right shift */
  362. static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
  363. {
  364. int32_t temp;
  365. temp = (int32_t)a + (int32_t)b;
  366. temp += 1;
  367. return (temp >> 1) & 0xFFFF;
  368. }
  369. static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
  370. {
  371. int64_t temp;
  372. temp = (int64_t)a + (int64_t)b;
  373. return (temp >> 1) & 0xFFFFFFFF;
  374. }
  375. static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
  376. {
  377. int64_t temp;
  378. temp = (int64_t)a + (int64_t)b;
  379. temp += 1;
  380. return (temp >> 1) & 0xFFFFFFFF;
  381. }
  382. static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
  383. {
  384. uint16_t temp;
  385. temp = (uint16_t)a + (uint16_t)b;
  386. return (temp >> 1) & 0x00FF;
  387. }
  388. static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
  389. {
  390. uint16_t temp;
  391. temp = (uint16_t)a + (uint16_t)b + 1;
  392. return (temp >> 1) & 0x00FF;
  393. }
  394. static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
  395. {
  396. uint16_t temp;
  397. temp = (uint16_t)a - (uint16_t)b;
  398. return (temp >> 1) & 0x00FF;
  399. }
  400. static inline uint8_t mipsdsp_rrshift1_sub_u8(uint8_t a, uint8_t b)
  401. {
  402. uint16_t temp;
  403. temp = (uint16_t)a - (uint16_t)b + 1;
  404. return (temp >> 1) & 0x00FF;
  405. }
  406. /* 128 bits long. p[0] is LO, p[1] is HI. */
  407. static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
  408. int32_t ac,
  409. int32_t shift,
  410. CPUMIPSState *env)
  411. {
  412. int64_t acc;
  413. acc = ((int64_t)env->active_tc.HI[ac] << 32) |
  414. ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
  415. p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
  416. p[1] = (acc >> 63) & 0x01;
  417. }
  418. /* 128 bits long. p[0] is LO, p[1] is HI */
  419. static inline void mipsdsp_rashift_acc(uint64_t *p,
  420. uint32_t ac,
  421. uint32_t shift,
  422. CPUMIPSState *env)
  423. {
  424. uint64_t tempB, tempA;
  425. tempB = env->active_tc.HI[ac];
  426. tempA = env->active_tc.LO[ac];
  427. shift = shift & 0x1F;
  428. if (shift == 0) {
  429. p[1] = tempB;
  430. p[0] = tempA;
  431. } else {
  432. p[0] = (tempB << (64 - shift)) | (tempA >> shift);
  433. p[1] = (int64_t)tempB >> shift;
  434. }
  435. }
  436. /* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
  437. static inline void mipsdsp_rndrashift_acc(uint64_t *p,
  438. uint32_t ac,
  439. uint32_t shift,
  440. CPUMIPSState *env)
  441. {
  442. int64_t tempB, tempA;
  443. tempB = env->active_tc.HI[ac];
  444. tempA = env->active_tc.LO[ac];
  445. shift = shift & 0x3F;
  446. if (shift == 0) {
  447. p[2] = tempB >> 63;
  448. p[1] = (tempB << 1) | (tempA >> 63);
  449. p[0] = tempA << 1;
  450. } else {
  451. p[0] = (tempB << (65 - shift)) | (tempA >> (shift - 1));
  452. p[1] = (int64_t)tempB >> (shift - 1);
  453. if (tempB >= 0) {
  454. p[2] = 0x0;
  455. } else {
  456. p[2] = ~0ull;
  457. }
  458. }
  459. }
  460. static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
  461. CPUMIPSState *env)
  462. {
  463. int32_t temp;
  464. if ((a == 0x8000) && (b == 0x8000)) {
  465. temp = 0x7FFFFFFF;
  466. set_DSPControl_overflow_flag(1, 16 + ac, env);
  467. } else {
  468. temp = ((uint32_t)a * (uint32_t)b) << 1;
  469. }
  470. return temp;
  471. }
  472. static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b,
  473. CPUMIPSState *env)
  474. {
  475. uint64_t temp;
  476. if ((a == 0x80000000) && (b == 0x80000000)) {
  477. temp = (0x01ull << 63) - 1;
  478. set_DSPControl_overflow_flag(1, 16 + ac, env);
  479. } else {
  480. temp = ((uint64_t)a * (uint64_t)b) << 1;
  481. }
  482. return temp;
  483. }
  484. static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
  485. {
  486. return (uint16_t)a * (uint16_t)b;
  487. }
  488. static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b,
  489. CPUMIPSState *env)
  490. {
  491. uint32_t tempI;
  492. tempI = (uint32_t)a * (uint32_t)b;
  493. if (tempI > 0x0000FFFF) {
  494. tempI = 0x0000FFFF;
  495. set_DSPControl_overflow_flag(1, 21, env);
  496. }
  497. return tempI & 0x0000FFFF;
  498. }
  499. static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
  500. {
  501. return (uint64_t)a * (uint64_t)b;
  502. }
  503. static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
  504. CPUMIPSState *env)
  505. {
  506. uint32_t temp;
  507. if ((a == 0x8000) && (b == 0x8000)) {
  508. temp = 0x7FFF0000;
  509. set_DSPControl_overflow_flag(1, 21, env);
  510. } else {
  511. temp = (a * b) << 1;
  512. temp = temp + 0x00008000;
  513. }
  514. return (temp & 0xFFFF0000) >> 16;
  515. }
  516. static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b,
  517. CPUMIPSState *env)
  518. {
  519. int32_t temp;
  520. if ((a == 0x8000) && (b == 0x8000)) {
  521. temp = 0x7FFF0000;
  522. set_DSPControl_overflow_flag(1, 21, env);
  523. } else {
  524. temp = (int16_t)a * (int16_t)b;
  525. temp = temp << 1;
  526. }
  527. return (temp >> 16) & 0x0000FFFF;
  528. }
  529. static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
  530. CPUMIPSState *env)
  531. {
  532. int64_t temp;
  533. temp = (int32_t)a + 0x00008000;
  534. if (a > (int)0x7fff8000) {
  535. temp = 0x7FFFFFFF;
  536. set_DSPControl_overflow_flag(1, 22, env);
  537. }
  538. return (temp >> 16) & 0xFFFF;
  539. }
  540. static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
  541. CPUMIPSState *env)
  542. {
  543. uint16_t mag;
  544. uint32_t sign;
  545. sign = (a >> 15) & 0x01;
  546. mag = a & 0x7FFF;
  547. if (sign == 0) {
  548. if (mag > 0x7F80) {
  549. set_DSPControl_overflow_flag(1, 22, env);
  550. return 0xFF;
  551. } else {
  552. return (mag >> 7) & 0xFFFF;
  553. }
  554. } else {
  555. set_DSPControl_overflow_flag(1, 22, env);
  556. return 0x00;
  557. }
  558. }
  559. static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
  560. {
  561. uint8_t sign;
  562. uint8_t discard;
  563. if (s == 0) {
  564. return a;
  565. } else {
  566. sign = (a >> 7) & 0x01;
  567. if (sign != 0) {
  568. discard = (((0x01 << (8 - s)) - 1) << s) |
  569. ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
  570. } else {
  571. discard = a >> (6 - (s - 1));
  572. }
  573. if (discard != 0x00) {
  574. set_DSPControl_overflow_flag(1, 22, env);
  575. }
  576. return a << s;
  577. }
  578. }
  579. static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
  580. CPUMIPSState *env)
  581. {
  582. uint8_t sign;
  583. uint16_t discard;
  584. if (s == 0) {
  585. return a;
  586. } else {
  587. sign = (a >> 15) & 0x01;
  588. if (sign != 0) {
  589. discard = (((0x01 << (16 - s)) - 1) << s) |
  590. ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
  591. } else {
  592. discard = a >> (14 - (s - 1));
  593. }
  594. if ((discard != 0x0000) && (discard != 0xFFFF)) {
  595. set_DSPControl_overflow_flag(1, 22, env);
  596. }
  597. return a << s;
  598. }
  599. }
  600. static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
  601. CPUMIPSState *env)
  602. {
  603. uint32_t discard;
  604. if (s == 0) {
  605. return a;
  606. } else {
  607. discard = (int32_t)a >> (31 - (s - 1));
  608. if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
  609. set_DSPControl_overflow_flag(1, 22, env);
  610. }
  611. return a << s;
  612. }
  613. }
  614. static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
  615. CPUMIPSState *env)
  616. {
  617. uint8_t sign;
  618. uint16_t discard;
  619. if (s == 0) {
  620. return a;
  621. } else {
  622. sign = (a >> 15) & 0x01;
  623. if (sign != 0) {
  624. discard = (((0x01 << (16 - s)) - 1) << s) |
  625. ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
  626. } else {
  627. discard = a >> (14 - (s - 1));
  628. }
  629. if ((discard != 0x0000) && (discard != 0xFFFF)) {
  630. set_DSPControl_overflow_flag(1, 22, env);
  631. return (sign == 0) ? 0x7FFF : 0x8000;
  632. } else {
  633. return a << s;
  634. }
  635. }
  636. }
  637. static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s,
  638. CPUMIPSState *env)
  639. {
  640. uint8_t sign;
  641. uint32_t discard;
  642. if (s == 0) {
  643. return a;
  644. } else {
  645. sign = (a >> 31) & 0x01;
  646. if (sign != 0) {
  647. discard = (((0x01 << (32 - s)) - 1) << s) |
  648. ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
  649. } else {
  650. discard = a >> (30 - (s - 1));
  651. }
  652. if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
  653. set_DSPControl_overflow_flag(1, 22, env);
  654. return (sign == 0) ? 0x7FFFFFFF : 0x80000000;
  655. } else {
  656. return a << s;
  657. }
  658. }
  659. }
  660. static inline uint8_t mipsdsp_rnd8_rashift(uint8_t a, uint8_t s)
  661. {
  662. uint32_t temp;
  663. if (s == 0) {
  664. temp = (uint32_t)a << 1;
  665. } else {
  666. temp = (int32_t)(int8_t)a >> (s - 1);
  667. }
  668. return (temp + 1) >> 1;
  669. }
  670. static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
  671. {
  672. uint32_t temp;
  673. if (s == 0) {
  674. temp = (uint32_t)a << 1;
  675. } else {
  676. temp = (int32_t)(int16_t)a >> (s - 1);
  677. }
  678. return (temp + 1) >> 1;
  679. }
  680. static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
  681. {
  682. int64_t temp;
  683. if (s == 0) {
  684. temp = (uint64_t)a << 1;
  685. } else {
  686. temp = (int64_t)(int32_t)a >> (s - 1);
  687. }
  688. temp += 1;
  689. return (temp >> 1) & 0xFFFFFFFFull;
  690. }
  691. static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b, CPUMIPSState *env)
  692. {
  693. int16_t temp;
  694. temp = a - b;
  695. if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
  696. set_DSPControl_overflow_flag(1, 20, env);
  697. }
  698. return temp;
  699. }
  700. static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b,
  701. CPUMIPSState *env)
  702. {
  703. int16_t temp;
  704. temp = a - b;
  705. if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x8000)) {
  706. if (a >= 0) {
  707. temp = 0x7FFF;
  708. } else {
  709. temp = 0x8000;
  710. }
  711. set_DSPControl_overflow_flag(1, 20, env);
  712. }
  713. return temp;
  714. }
  715. static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b,
  716. CPUMIPSState *env)
  717. {
  718. int32_t temp;
  719. temp = a - b;
  720. if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
  721. if (a >= 0) {
  722. temp = 0x7FFFFFFF;
  723. } else {
  724. temp = 0x80000000;
  725. }
  726. set_DSPControl_overflow_flag(1, 20, env);
  727. }
  728. return temp & 0xFFFFFFFFull;
  729. }
  730. static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
  731. {
  732. int32_t temp;
  733. temp = (int32_t)a - (int32_t)b;
  734. return (temp >> 1) & 0x0000FFFF;
  735. }
  736. static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
  737. {
  738. int32_t temp;
  739. temp = (int32_t)a - (int32_t)b;
  740. temp += 1;
  741. return (temp >> 1) & 0x0000FFFF;
  742. }
  743. static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
  744. {
  745. int64_t temp;
  746. temp = (int64_t)a - (int64_t)b;
  747. return (temp >> 1) & 0xFFFFFFFFull;
  748. }
  749. static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
  750. {
  751. int64_t temp;
  752. temp = (int64_t)a - (int64_t)b;
  753. temp += 1;
  754. return (temp >> 1) & 0xFFFFFFFFull;
  755. }
  756. static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b,
  757. CPUMIPSState *env)
  758. {
  759. uint8_t temp16;
  760. uint32_t temp;
  761. temp = (uint32_t)a - (uint32_t)b;
  762. temp16 = (temp >> 16) & 0x01;
  763. if (temp16 == 1) {
  764. set_DSPControl_overflow_flag(1, 20, env);
  765. }
  766. return temp & 0x0000FFFF;
  767. }
  768. static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b,
  769. CPUMIPSState *env)
  770. {
  771. uint8_t temp16;
  772. uint32_t temp;
  773. temp = (uint32_t)a - (uint32_t)b;
  774. temp16 = (temp >> 16) & 0x01;
  775. if (temp16 == 1) {
  776. temp = 0x0000;
  777. set_DSPControl_overflow_flag(1, 20, env);
  778. }
  779. return temp & 0x0000FFFF;
  780. }
  781. static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b, CPUMIPSState *env)
  782. {
  783. uint8_t temp8;
  784. uint16_t temp;
  785. temp = (uint16_t)a - (uint16_t)b;
  786. temp8 = (temp >> 8) & 0x01;
  787. if (temp8 == 1) {
  788. set_DSPControl_overflow_flag(1, 20, env);
  789. }
  790. return temp & 0x00FF;
  791. }
  792. static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b, CPUMIPSState *env)
  793. {
  794. uint8_t temp8;
  795. uint16_t temp;
  796. temp = (uint16_t)a - (uint16_t)b;
  797. temp8 = (temp >> 8) & 0x01;
  798. if (temp8 == 1) {
  799. temp = 0x00;
  800. set_DSPControl_overflow_flag(1, 20, env);
  801. }
  802. return temp & 0x00FF;
  803. }
  804. static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
  805. {
  806. int32_t temp;
  807. temp = a - b;
  808. if (MIPSDSP_OVERFLOW_SUB(a, b, temp, 0x80000000)) {
  809. set_DSPControl_overflow_flag(1, 20, env);
  810. }
  811. return temp;
  812. }
  813. static inline int32_t mipsdsp_add_i32(int32_t a, int32_t b, CPUMIPSState *env)
  814. {
  815. int32_t temp;
  816. temp = a + b;
  817. if (MIPSDSP_OVERFLOW_ADD(a, b, temp, 0x80000000)) {
  818. set_DSPControl_overflow_flag(1, 20, env);
  819. }
  820. return temp;
  821. }
  822. static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
  823. {
  824. return a == b;
  825. }
  826. static inline int32_t mipsdsp_cmp_le(int32_t a, int32_t b)
  827. {
  828. return a <= b;
  829. }
  830. static inline int32_t mipsdsp_cmp_lt(int32_t a, int32_t b)
  831. {
  832. return a < b;
  833. }
  834. static inline int32_t mipsdsp_cmpu_eq(uint32_t a, uint32_t b)
  835. {
  836. return a == b;
  837. }
  838. static inline int32_t mipsdsp_cmpu_le(uint32_t a, uint32_t b)
  839. {
  840. return a <= b;
  841. }
  842. static inline int32_t mipsdsp_cmpu_lt(uint32_t a, uint32_t b)
  843. {
  844. return a < b;
  845. }
  846. /*** MIPS DSP internal functions end ***/
  847. #define MIPSDSP_LHI 0xFFFFFFFF00000000ull
  848. #define MIPSDSP_LLO 0x00000000FFFFFFFFull
  849. #define MIPSDSP_HI 0xFFFF0000
  850. #define MIPSDSP_LO 0x0000FFFF
  851. #define MIPSDSP_Q3 0xFF000000
  852. #define MIPSDSP_Q2 0x00FF0000
  853. #define MIPSDSP_Q1 0x0000FF00
  854. #define MIPSDSP_Q0 0x000000FF
  855. #define MIPSDSP_SPLIT32_8(num, a, b, c, d) \
  856. do { \
  857. a = (num >> 24) & MIPSDSP_Q0; \
  858. b = (num >> 16) & MIPSDSP_Q0; \
  859. c = (num >> 8) & MIPSDSP_Q0; \
  860. d = num & MIPSDSP_Q0; \
  861. } while (0)
  862. #define MIPSDSP_SPLIT32_16(num, a, b) \
  863. do { \
  864. a = (num >> 16) & MIPSDSP_LO; \
  865. b = num & MIPSDSP_LO; \
  866. } while (0)
  867. #define MIPSDSP_RETURN32_8(a, b, c, d) ((target_long)(int32_t) \
  868. (((uint32_t)a << 24) | \
  869. (((uint32_t)b << 16) | \
  870. (((uint32_t)c << 8) | \
  871. ((uint32_t)d & 0xFF)))))
  872. #define MIPSDSP_RETURN32_16(a, b) ((target_long)(int32_t) \
  873. (((uint32_t)a << 16) | \
  874. ((uint32_t)b & 0xFFFF)))
  875. #ifdef TARGET_MIPS64
  876. #define MIPSDSP_SPLIT64_16(num, a, b, c, d) \
  877. do { \
  878. a = (num >> 48) & MIPSDSP_LO; \
  879. b = (num >> 32) & MIPSDSP_LO; \
  880. c = (num >> 16) & MIPSDSP_LO; \
  881. d = num & MIPSDSP_LO; \
  882. } while (0)
  883. #define MIPSDSP_SPLIT64_32(num, a, b) \
  884. do { \
  885. a = (num >> 32) & MIPSDSP_LLO; \
  886. b = num & MIPSDSP_LLO; \
  887. } while (0)
  888. #define MIPSDSP_RETURN64_16(a, b, c, d) (((uint64_t)a << 48) | \
  889. ((uint64_t)b << 32) | \
  890. ((uint64_t)c << 16) | \
  891. (uint64_t)d)
  892. #define MIPSDSP_RETURN64_32(a, b) (((uint64_t)a << 32) | (uint64_t)b)
  893. #endif
  894. /** DSP Arithmetic Sub-class insns **/
  895. #define MIPSDSP32_UNOP_ENV(name, func, element) \
  896. target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
  897. { \
  898. DSP32Value dt; \
  899. unsigned int i, n; \
  900. \
  901. n = sizeof(DSP32Value) / sizeof(dt.element[0]); \
  902. dt.sw[0] = rt; \
  903. \
  904. for (i = 0; i < n; i++) { \
  905. dt.element[i] = mipsdsp_##func(dt.element[i], env); \
  906. } \
  907. \
  908. return (target_long)dt.sw[0]; \
  909. }
  910. MIPSDSP32_UNOP_ENV(absq_s_ph, sat_abs16, sh)
  911. MIPSDSP32_UNOP_ENV(absq_s_qb, sat_abs8, sb)
  912. MIPSDSP32_UNOP_ENV(absq_s_w, sat_abs32, sw)
  913. #undef MIPSDSP32_UNOP_ENV
  914. #if defined(TARGET_MIPS64)
  915. #define MIPSDSP64_UNOP_ENV(name, func, element) \
  916. target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
  917. { \
  918. DSP64Value dt; \
  919. unsigned int i, n; \
  920. \
  921. n = sizeof(DSP64Value) / sizeof(dt.element[0]); \
  922. dt.sl[0] = rt; \
  923. \
  924. for (i = 0; i < n; i++) { \
  925. dt.element[i] = mipsdsp_##func(dt.element[i], env); \
  926. } \
  927. \
  928. return dt.sl[0]; \
  929. }
  930. MIPSDSP64_UNOP_ENV(absq_s_ob, sat_abs8, sb)
  931. MIPSDSP64_UNOP_ENV(absq_s_qh, sat_abs16, sh)
  932. MIPSDSP64_UNOP_ENV(absq_s_pw, sat_abs32, sw)
  933. #undef MIPSDSP64_UNOP_ENV
  934. #endif
  935. #define MIPSDSP32_BINOP(name, func, element) \
  936. target_ulong helper_##name(target_ulong rs, target_ulong rt) \
  937. { \
  938. DSP32Value ds, dt; \
  939. unsigned int i, n; \
  940. \
  941. n = sizeof(DSP32Value) / sizeof(ds.element[0]); \
  942. ds.sw[0] = rs; \
  943. dt.sw[0] = rt; \
  944. \
  945. for (i = 0; i < n; i++) { \
  946. ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
  947. } \
  948. \
  949. return (target_long)ds.sw[0]; \
  950. }
  951. MIPSDSP32_BINOP(addqh_ph, rshift1_add_q16, sh);
  952. MIPSDSP32_BINOP(addqh_r_ph, rrshift1_add_q16, sh);
  953. MIPSDSP32_BINOP(addqh_r_w, rrshift1_add_q32, sw);
  954. MIPSDSP32_BINOP(addqh_w, rshift1_add_q32, sw);
  955. MIPSDSP32_BINOP(adduh_qb, rshift1_add_u8, ub);
  956. MIPSDSP32_BINOP(adduh_r_qb, rrshift1_add_u8, ub);
  957. MIPSDSP32_BINOP(subqh_ph, rshift1_sub_q16, sh);
  958. MIPSDSP32_BINOP(subqh_r_ph, rrshift1_sub_q16, sh);
  959. MIPSDSP32_BINOP(subqh_r_w, rrshift1_sub_q32, sw);
  960. MIPSDSP32_BINOP(subqh_w, rshift1_sub_q32, sw);
  961. #undef MIPSDSP32_BINOP
  962. #define MIPSDSP32_BINOP_ENV(name, func, element) \
  963. target_ulong helper_##name(target_ulong rs, target_ulong rt, \
  964. CPUMIPSState *env) \
  965. { \
  966. DSP32Value ds, dt; \
  967. unsigned int i, n; \
  968. \
  969. n = sizeof(DSP32Value) / sizeof(ds.element[0]); \
  970. ds.sw[0] = rs; \
  971. dt.sw[0] = rt; \
  972. \
  973. for (i = 0 ; i < n ; i++) { \
  974. ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
  975. } \
  976. \
  977. return (target_long)ds.sw[0]; \
  978. }
  979. MIPSDSP32_BINOP_ENV(addq_ph, add_i16, sh)
  980. MIPSDSP32_BINOP_ENV(addq_s_ph, sat_add_i16, sh)
  981. MIPSDSP32_BINOP_ENV(addq_s_w, sat_add_i32, sw);
  982. MIPSDSP32_BINOP_ENV(addu_ph, add_u16, sh)
  983. MIPSDSP32_BINOP_ENV(addu_qb, add_u8, ub);
  984. MIPSDSP32_BINOP_ENV(addu_s_ph, sat_add_u16, sh)
  985. MIPSDSP32_BINOP_ENV(addu_s_qb, sat_add_u8, ub);
  986. MIPSDSP32_BINOP_ENV(subq_ph, sub_i16, sh);
  987. MIPSDSP32_BINOP_ENV(subq_s_ph, sat16_sub, sh);
  988. MIPSDSP32_BINOP_ENV(subq_s_w, sat32_sub, sw);
  989. MIPSDSP32_BINOP_ENV(subu_ph, sub_u16_u16, sh);
  990. MIPSDSP32_BINOP_ENV(subu_qb, sub_u8, ub);
  991. MIPSDSP32_BINOP_ENV(subu_s_ph, satu16_sub_u16_u16, sh);
  992. MIPSDSP32_BINOP_ENV(subu_s_qb, satu8_sub, ub);
  993. #undef MIPSDSP32_BINOP_ENV
  994. #ifdef TARGET_MIPS64
  995. #define MIPSDSP64_BINOP(name, func, element) \
  996. target_ulong helper_##name(target_ulong rs, target_ulong rt) \
  997. { \
  998. DSP64Value ds, dt; \
  999. unsigned int i, n; \
  1000. \
  1001. n = sizeof(DSP64Value) / sizeof(ds.element[0]); \
  1002. ds.sl[0] = rs; \
  1003. dt.sl[0] = rt; \
  1004. \
  1005. for (i = 0 ; i < n ; i++) { \
  1006. ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
  1007. } \
  1008. \
  1009. return ds.sl[0]; \
  1010. }
  1011. MIPSDSP64_BINOP(adduh_ob, rshift1_add_u8, ub);
  1012. MIPSDSP64_BINOP(adduh_r_ob, rrshift1_add_u8, ub);
  1013. MIPSDSP64_BINOP(subuh_ob, rshift1_sub_u8, ub);
  1014. MIPSDSP64_BINOP(subuh_r_ob, rrshift1_sub_u8, ub);
  1015. #undef MIPSDSP64_BINOP
  1016. #define MIPSDSP64_BINOP_ENV(name, func, element) \
  1017. target_ulong helper_##name(target_ulong rs, target_ulong rt, \
  1018. CPUMIPSState *env) \
  1019. { \
  1020. DSP64Value ds, dt; \
  1021. unsigned int i, n; \
  1022. \
  1023. n = sizeof(DSP64Value) / sizeof(ds.element[0]); \
  1024. ds.sl[0] = rs; \
  1025. dt.sl[0] = rt; \
  1026. \
  1027. for (i = 0 ; i < n ; i++) { \
  1028. ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
  1029. } \
  1030. \
  1031. return ds.sl[0]; \
  1032. }
  1033. MIPSDSP64_BINOP_ENV(addq_pw, add_i32, sw);
  1034. MIPSDSP64_BINOP_ENV(addq_qh, add_i16, sh);
  1035. MIPSDSP64_BINOP_ENV(addq_s_pw, sat_add_i32, sw);
  1036. MIPSDSP64_BINOP_ENV(addq_s_qh, sat_add_i16, sh);
  1037. MIPSDSP64_BINOP_ENV(addu_ob, add_u8, uh);
  1038. MIPSDSP64_BINOP_ENV(addu_qh, add_u16, uh);
  1039. MIPSDSP64_BINOP_ENV(addu_s_ob, sat_add_u8, uh);
  1040. MIPSDSP64_BINOP_ENV(addu_s_qh, sat_add_u16, uh);
  1041. MIPSDSP64_BINOP_ENV(subq_pw, sub32, sw);
  1042. MIPSDSP64_BINOP_ENV(subq_qh, sub_i16, sh);
  1043. MIPSDSP64_BINOP_ENV(subq_s_pw, sat32_sub, sw);
  1044. MIPSDSP64_BINOP_ENV(subq_s_qh, sat16_sub, sh);
  1045. MIPSDSP64_BINOP_ENV(subu_ob, sub_u8, uh);
  1046. MIPSDSP64_BINOP_ENV(subu_qh, sub_u16_u16, uh);
  1047. MIPSDSP64_BINOP_ENV(subu_s_ob, satu8_sub, uh);
  1048. MIPSDSP64_BINOP_ENV(subu_s_qh, satu16_sub_u16_u16, uh);
  1049. #undef MIPSDSP64_BINOP_ENV
  1050. #endif
  1051. #define SUBUH_QB(name, var) \
  1052. target_ulong helper_##name##_qb(target_ulong rs, target_ulong rt) \
  1053. { \
  1054. uint8_t rs3, rs2, rs1, rs0; \
  1055. uint8_t rt3, rt2, rt1, rt0; \
  1056. uint8_t tempD, tempC, tempB, tempA; \
  1057. \
  1058. MIPSDSP_SPLIT32_8(rs, rs3, rs2, rs1, rs0); \
  1059. MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
  1060. \
  1061. tempD = ((uint16_t)rs3 - (uint16_t)rt3 + var) >> 1; \
  1062. tempC = ((uint16_t)rs2 - (uint16_t)rt2 + var) >> 1; \
  1063. tempB = ((uint16_t)rs1 - (uint16_t)rt1 + var) >> 1; \
  1064. tempA = ((uint16_t)rs0 - (uint16_t)rt0 + var) >> 1; \
  1065. \
  1066. return ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
  1067. ((uint32_t)tempB << 8) | ((uint32_t)tempA); \
  1068. }
  1069. SUBUH_QB(subuh, 0);
  1070. SUBUH_QB(subuh_r, 1);
  1071. #undef SUBUH_QB
  1072. target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
  1073. {
  1074. uint64_t temp, tempRs, tempRt;
  1075. int32_t flag;
  1076. tempRs = (uint64_t)rs & MIPSDSP_LLO;
  1077. tempRt = (uint64_t)rt & MIPSDSP_LLO;
  1078. temp = tempRs + tempRt;
  1079. flag = (temp & 0x0100000000ull) >> 32;
  1080. set_DSPControl_carryflag(flag, env);
  1081. return (target_long)(int32_t)(temp & MIPSDSP_LLO);
  1082. }
  1083. target_ulong helper_addwc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
  1084. {
  1085. uint32_t rd;
  1086. int32_t temp32, temp31;
  1087. int64_t tempL;
  1088. tempL = (int64_t)(int32_t)rs + (int64_t)(int32_t)rt +
  1089. get_DSPControl_carryflag(env);
  1090. temp31 = (tempL >> 31) & 0x01;
  1091. temp32 = (tempL >> 32) & 0x01;
  1092. if (temp31 != temp32) {
  1093. set_DSPControl_overflow_flag(1, 20, env);
  1094. }
  1095. rd = tempL & MIPSDSP_LLO;
  1096. return (target_long)(int32_t)rd;
  1097. }
  1098. target_ulong helper_modsub(target_ulong rs, target_ulong rt)
  1099. {
  1100. int32_t decr;
  1101. uint16_t lastindex;
  1102. target_ulong rd;
  1103. decr = rt & MIPSDSP_Q0;
  1104. lastindex = (rt >> 8) & MIPSDSP_LO;
  1105. if ((rs & MIPSDSP_LLO) == 0x00000000) {
  1106. rd = (target_ulong)lastindex;
  1107. } else {
  1108. rd = rs - decr;
  1109. }
  1110. return rd;
  1111. }
  1112. target_ulong helper_raddu_w_qb(target_ulong rs)
  1113. {
  1114. target_ulong ret = 0;
  1115. DSP32Value ds;
  1116. unsigned int i;
  1117. ds.uw[0] = rs;
  1118. for (i = 0; i < 4; i++) {
  1119. ret += ds.ub[i];
  1120. }
  1121. return ret;
  1122. }
  1123. #if defined(TARGET_MIPS64)
  1124. target_ulong helper_raddu_l_ob(target_ulong rs)
  1125. {
  1126. target_ulong ret = 0;
  1127. DSP64Value ds;
  1128. unsigned int i;
  1129. ds.ul[0] = rs;
  1130. for (i = 0; i < 8; i++) {
  1131. ret += ds.ub[i];
  1132. }
  1133. return ret;
  1134. }
  1135. #endif
  1136. #define PRECR_QB_PH(name, a, b)\
  1137. target_ulong helper_##name##_qb_ph(target_ulong rs, target_ulong rt) \
  1138. { \
  1139. uint8_t tempD, tempC, tempB, tempA; \
  1140. \
  1141. tempD = (rs >> a) & MIPSDSP_Q0; \
  1142. tempC = (rs >> b) & MIPSDSP_Q0; \
  1143. tempB = (rt >> a) & MIPSDSP_Q0; \
  1144. tempA = (rt >> b) & MIPSDSP_Q0; \
  1145. \
  1146. return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA); \
  1147. }
  1148. PRECR_QB_PH(precr, 16, 0);
  1149. PRECR_QB_PH(precrq, 24, 8);
  1150. #undef PRECR_QB_OH
  1151. target_ulong helper_precr_sra_ph_w(uint32_t sa, target_ulong rs,
  1152. target_ulong rt)
  1153. {
  1154. uint16_t tempB, tempA;
  1155. tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
  1156. tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
  1157. return MIPSDSP_RETURN32_16(tempB, tempA);
  1158. }
  1159. target_ulong helper_precr_sra_r_ph_w(uint32_t sa,
  1160. target_ulong rs, target_ulong rt)
  1161. {
  1162. uint64_t tempB, tempA;
  1163. /* If sa = 0, then (sa - 1) = -1 will case shift error, so we need else. */
  1164. if (sa == 0) {
  1165. tempB = (rt & MIPSDSP_LO) << 1;
  1166. tempA = (rs & MIPSDSP_LO) << 1;
  1167. } else {
  1168. tempB = ((int32_t)rt >> (sa - 1)) + 1;
  1169. tempA = ((int32_t)rs >> (sa - 1)) + 1;
  1170. }
  1171. rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
  1172. return (target_long)(int32_t)rt;
  1173. }
  1174. target_ulong helper_precrq_ph_w(target_ulong rs, target_ulong rt)
  1175. {
  1176. uint16_t tempB, tempA;
  1177. tempB = (rs & MIPSDSP_HI) >> 16;
  1178. tempA = (rt & MIPSDSP_HI) >> 16;
  1179. return MIPSDSP_RETURN32_16(tempB, tempA);
  1180. }
  1181. target_ulong helper_precrq_rs_ph_w(target_ulong rs, target_ulong rt,
  1182. CPUMIPSState *env)
  1183. {
  1184. uint16_t tempB, tempA;
  1185. tempB = mipsdsp_trunc16_sat16_round(rs, env);
  1186. tempA = mipsdsp_trunc16_sat16_round(rt, env);
  1187. return MIPSDSP_RETURN32_16(tempB, tempA);
  1188. }
  1189. #if defined(TARGET_MIPS64)
  1190. target_ulong helper_precr_ob_qh(target_ulong rs, target_ulong rt)
  1191. {
  1192. uint8_t rs6, rs4, rs2, rs0;
  1193. uint8_t rt6, rt4, rt2, rt0;
  1194. uint64_t temp;
  1195. rs6 = (rs >> 48) & MIPSDSP_Q0;
  1196. rs4 = (rs >> 32) & MIPSDSP_Q0;
  1197. rs2 = (rs >> 16) & MIPSDSP_Q0;
  1198. rs0 = rs & MIPSDSP_Q0;
  1199. rt6 = (rt >> 48) & MIPSDSP_Q0;
  1200. rt4 = (rt >> 32) & MIPSDSP_Q0;
  1201. rt2 = (rt >> 16) & MIPSDSP_Q0;
  1202. rt0 = rt & MIPSDSP_Q0;
  1203. temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
  1204. ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
  1205. ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
  1206. ((uint64_t)rt2 << 8) | (uint64_t)rt0;
  1207. return temp;
  1208. }
  1209. #define PRECR_QH_PW(name, var) \
  1210. target_ulong helper_precr_##name##_qh_pw(target_ulong rs, target_ulong rt, \
  1211. uint32_t sa) \
  1212. { \
  1213. uint16_t rs3, rs2, rs1, rs0; \
  1214. uint16_t rt3, rt2, rt1, rt0; \
  1215. uint16_t tempD, tempC, tempB, tempA; \
  1216. \
  1217. MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \
  1218. MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
  1219. \
  1220. /* When sa = 0, we use rt2, rt0, rs2, rs0; \
  1221. * when sa != 0, we use rt3, rt1, rs3, rs1. */ \
  1222. if (sa == 0) { \
  1223. tempD = rt2 << var; \
  1224. tempC = rt0 << var; \
  1225. tempB = rs2 << var; \
  1226. tempA = rs0 << var; \
  1227. } else { \
  1228. tempD = (((int16_t)rt3 >> sa) + var) >> var; \
  1229. tempC = (((int16_t)rt1 >> sa) + var) >> var; \
  1230. tempB = (((int16_t)rs3 >> sa) + var) >> var; \
  1231. tempA = (((int16_t)rs1 >> sa) + var) >> var; \
  1232. } \
  1233. \
  1234. return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
  1235. }
  1236. PRECR_QH_PW(sra, 0);
  1237. PRECR_QH_PW(sra_r, 1);
  1238. #undef PRECR_QH_PW
  1239. target_ulong helper_precrq_ob_qh(target_ulong rs, target_ulong rt)
  1240. {
  1241. uint8_t rs6, rs4, rs2, rs0;
  1242. uint8_t rt6, rt4, rt2, rt0;
  1243. uint64_t temp;
  1244. rs6 = (rs >> 56) & MIPSDSP_Q0;
  1245. rs4 = (rs >> 40) & MIPSDSP_Q0;
  1246. rs2 = (rs >> 24) & MIPSDSP_Q0;
  1247. rs0 = (rs >> 8) & MIPSDSP_Q0;
  1248. rt6 = (rt >> 56) & MIPSDSP_Q0;
  1249. rt4 = (rt >> 40) & MIPSDSP_Q0;
  1250. rt2 = (rt >> 24) & MIPSDSP_Q0;
  1251. rt0 = (rt >> 8) & MIPSDSP_Q0;
  1252. temp = ((uint64_t)rs6 << 56) | ((uint64_t)rs4 << 48) |
  1253. ((uint64_t)rs2 << 40) | ((uint64_t)rs0 << 32) |
  1254. ((uint64_t)rt6 << 24) | ((uint64_t)rt4 << 16) |
  1255. ((uint64_t)rt2 << 8) | (uint64_t)rt0;
  1256. return temp;
  1257. }
  1258. target_ulong helper_precrq_qh_pw(target_ulong rs, target_ulong rt)
  1259. {
  1260. uint16_t tempD, tempC, tempB, tempA;
  1261. tempD = (rs >> 48) & MIPSDSP_LO;
  1262. tempC = (rs >> 16) & MIPSDSP_LO;
  1263. tempB = (rt >> 48) & MIPSDSP_LO;
  1264. tempA = (rt >> 16) & MIPSDSP_LO;
  1265. return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
  1266. }
  1267. target_ulong helper_precrq_rs_qh_pw(target_ulong rs, target_ulong rt,
  1268. CPUMIPSState *env)
  1269. {
  1270. uint32_t rs2, rs0;
  1271. uint32_t rt2, rt0;
  1272. uint16_t tempD, tempC, tempB, tempA;
  1273. rs2 = (rs >> 32) & MIPSDSP_LLO;
  1274. rs0 = rs & MIPSDSP_LLO;
  1275. rt2 = (rt >> 32) & MIPSDSP_LLO;
  1276. rt0 = rt & MIPSDSP_LLO;
  1277. tempD = mipsdsp_trunc16_sat16_round(rs2, env);
  1278. tempC = mipsdsp_trunc16_sat16_round(rs0, env);
  1279. tempB = mipsdsp_trunc16_sat16_round(rt2, env);
  1280. tempA = mipsdsp_trunc16_sat16_round(rt0, env);
  1281. return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA);
  1282. }
  1283. target_ulong helper_precrq_pw_l(target_ulong rs, target_ulong rt)
  1284. {
  1285. uint32_t tempB, tempA;
  1286. tempB = (rs >> 32) & MIPSDSP_LLO;
  1287. tempA = (rt >> 32) & MIPSDSP_LLO;
  1288. return MIPSDSP_RETURN64_32(tempB, tempA);
  1289. }
  1290. #endif
  1291. target_ulong helper_precrqu_s_qb_ph(target_ulong rs, target_ulong rt,
  1292. CPUMIPSState *env)
  1293. {
  1294. uint8_t tempD, tempC, tempB, tempA;
  1295. uint16_t rsh, rsl, rth, rtl;
  1296. rsh = (rs & MIPSDSP_HI) >> 16;
  1297. rsl = rs & MIPSDSP_LO;
  1298. rth = (rt & MIPSDSP_HI) >> 16;
  1299. rtl = rt & MIPSDSP_LO;
  1300. tempD = mipsdsp_sat8_reduce_precision(rsh, env);
  1301. tempC = mipsdsp_sat8_reduce_precision(rsl, env);
  1302. tempB = mipsdsp_sat8_reduce_precision(rth, env);
  1303. tempA = mipsdsp_sat8_reduce_precision(rtl, env);
  1304. return MIPSDSP_RETURN32_8(tempD, tempC, tempB, tempA);
  1305. }
  1306. #if defined(TARGET_MIPS64)
  1307. target_ulong helper_precrqu_s_ob_qh(target_ulong rs, target_ulong rt,
  1308. CPUMIPSState *env)
  1309. {
  1310. int i;
  1311. uint16_t rs3, rs2, rs1, rs0;
  1312. uint16_t rt3, rt2, rt1, rt0;
  1313. uint8_t temp[8];
  1314. uint64_t result;
  1315. result = 0;
  1316. MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
  1317. MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
  1318. temp[7] = mipsdsp_sat8_reduce_precision(rs3, env);
  1319. temp[6] = mipsdsp_sat8_reduce_precision(rs2, env);
  1320. temp[5] = mipsdsp_sat8_reduce_precision(rs1, env);
  1321. temp[4] = mipsdsp_sat8_reduce_precision(rs0, env);
  1322. temp[3] = mipsdsp_sat8_reduce_precision(rt3, env);
  1323. temp[2] = mipsdsp_sat8_reduce_precision(rt2, env);
  1324. temp[1] = mipsdsp_sat8_reduce_precision(rt1, env);
  1325. temp[0] = mipsdsp_sat8_reduce_precision(rt0, env);
  1326. for (i = 0; i < 8; i++) {
  1327. result |= (uint64_t)temp[i] << (8 * i);
  1328. }
  1329. return result;
  1330. }
  1331. #define PRECEQ_PW(name, a, b) \
  1332. target_ulong helper_preceq_pw_##name(target_ulong rt) \
  1333. { \
  1334. uint16_t tempB, tempA; \
  1335. uint32_t tempBI, tempAI; \
  1336. \
  1337. tempB = (rt >> a) & MIPSDSP_LO; \
  1338. tempA = (rt >> b) & MIPSDSP_LO; \
  1339. \
  1340. tempBI = (uint32_t)tempB << 16; \
  1341. tempAI = (uint32_t)tempA << 16; \
  1342. \
  1343. return MIPSDSP_RETURN64_32(tempBI, tempAI); \
  1344. }
  1345. PRECEQ_PW(qhl, 48, 32);
  1346. PRECEQ_PW(qhr, 16, 0);
  1347. PRECEQ_PW(qhla, 48, 16);
  1348. PRECEQ_PW(qhra, 32, 0);
  1349. #undef PRECEQ_PW
  1350. #endif
  1351. #define PRECEQU_PH(name, a, b) \
  1352. target_ulong helper_precequ_ph_##name(target_ulong rt) \
  1353. { \
  1354. uint16_t tempB, tempA; \
  1355. \
  1356. tempB = (rt >> a) & MIPSDSP_Q0; \
  1357. tempA = (rt >> b) & MIPSDSP_Q0; \
  1358. \
  1359. tempB = tempB << 7; \
  1360. tempA = tempA << 7; \
  1361. \
  1362. return MIPSDSP_RETURN32_16(tempB, tempA); \
  1363. }
  1364. PRECEQU_PH(qbl, 24, 16);
  1365. PRECEQU_PH(qbr, 8, 0);
  1366. PRECEQU_PH(qbla, 24, 8);
  1367. PRECEQU_PH(qbra, 16, 0);
  1368. #undef PRECEQU_PH
  1369. #if defined(TARGET_MIPS64)
  1370. #define PRECEQU_QH(name, a, b, c, d) \
  1371. target_ulong helper_precequ_qh_##name(target_ulong rt) \
  1372. { \
  1373. uint16_t tempD, tempC, tempB, tempA; \
  1374. \
  1375. tempD = (rt >> a) & MIPSDSP_Q0; \
  1376. tempC = (rt >> b) & MIPSDSP_Q0; \
  1377. tempB = (rt >> c) & MIPSDSP_Q0; \
  1378. tempA = (rt >> d) & MIPSDSP_Q0; \
  1379. \
  1380. tempD = tempD << 7; \
  1381. tempC = tempC << 7; \
  1382. tempB = tempB << 7; \
  1383. tempA = tempA << 7; \
  1384. \
  1385. return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
  1386. }
  1387. PRECEQU_QH(obl, 56, 48, 40, 32);
  1388. PRECEQU_QH(obr, 24, 16, 8, 0);
  1389. PRECEQU_QH(obla, 56, 40, 24, 8);
  1390. PRECEQU_QH(obra, 48, 32, 16, 0);
  1391. #undef PRECEQU_QH
  1392. #endif
  1393. #define PRECEU_PH(name, a, b) \
  1394. target_ulong helper_preceu_ph_##name(target_ulong rt) \
  1395. { \
  1396. uint16_t tempB, tempA; \
  1397. \
  1398. tempB = (rt >> a) & MIPSDSP_Q0; \
  1399. tempA = (rt >> b) & MIPSDSP_Q0; \
  1400. \
  1401. return MIPSDSP_RETURN32_16(tempB, tempA); \
  1402. }
  1403. PRECEU_PH(qbl, 24, 16);
  1404. PRECEU_PH(qbr, 8, 0);
  1405. PRECEU_PH(qbla, 24, 8);
  1406. PRECEU_PH(qbra, 16, 0);
  1407. #undef PRECEU_PH
  1408. #if defined(TARGET_MIPS64)
  1409. #define PRECEU_QH(name, a, b, c, d) \
  1410. target_ulong helper_preceu_qh_##name(target_ulong rt) \
  1411. { \
  1412. uint16_t tempD, tempC, tempB, tempA; \
  1413. \
  1414. tempD = (rt >> a) & MIPSDSP_Q0; \
  1415. tempC = (rt >> b) & MIPSDSP_Q0; \
  1416. tempB = (rt >> c) & MIPSDSP_Q0; \
  1417. tempA = (rt >> d) & MIPSDSP_Q0; \
  1418. \
  1419. return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
  1420. }
  1421. PRECEU_QH(obl, 56, 48, 40, 32);
  1422. PRECEU_QH(obr, 24, 16, 8, 0);
  1423. PRECEU_QH(obla, 56, 40, 24, 8);
  1424. PRECEU_QH(obra, 48, 32, 16, 0);
  1425. #undef PRECEU_QH
  1426. #endif
  1427. /** DSP GPR-Based Shift Sub-class insns **/
  1428. #define SHIFT_QB(name, func) \
  1429. target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt) \
  1430. { \
  1431. uint8_t rt3, rt2, rt1, rt0; \
  1432. \
  1433. sa = sa & 0x07; \
  1434. \
  1435. MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
  1436. \
  1437. rt3 = mipsdsp_##func(rt3, sa); \
  1438. rt2 = mipsdsp_##func(rt2, sa); \
  1439. rt1 = mipsdsp_##func(rt1, sa); \
  1440. rt0 = mipsdsp_##func(rt0, sa); \
  1441. \
  1442. return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \
  1443. }
  1444. #define SHIFT_QB_ENV(name, func) \
  1445. target_ulong helper_##name##_qb(target_ulong sa, target_ulong rt,\
  1446. CPUMIPSState *env) \
  1447. { \
  1448. uint8_t rt3, rt2, rt1, rt0; \
  1449. \
  1450. sa = sa & 0x07; \
  1451. \
  1452. MIPSDSP_SPLIT32_8(rt, rt3, rt2, rt1, rt0); \
  1453. \
  1454. rt3 = mipsdsp_##func(rt3, sa, env); \
  1455. rt2 = mipsdsp_##func(rt2, sa, env); \
  1456. rt1 = mipsdsp_##func(rt1, sa, env); \
  1457. rt0 = mipsdsp_##func(rt0, sa, env); \
  1458. \
  1459. return MIPSDSP_RETURN32_8(rt3, rt2, rt1, rt0); \
  1460. }
  1461. SHIFT_QB_ENV(shll, lshift8);
  1462. SHIFT_QB(shrl, rshift_u8);
  1463. SHIFT_QB(shra, rashift8);
  1464. SHIFT_QB(shra_r, rnd8_rashift);
  1465. #undef SHIFT_QB
  1466. #undef SHIFT_QB_ENV
  1467. #if defined(TARGET_MIPS64)
  1468. #define SHIFT_OB(name, func) \
  1469. target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa) \
  1470. { \
  1471. int i; \
  1472. uint8_t rt_t[8]; \
  1473. uint64_t temp; \
  1474. \
  1475. sa = sa & 0x07; \
  1476. temp = 0; \
  1477. \
  1478. for (i = 0; i < 8; i++) { \
  1479. rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \
  1480. rt_t[i] = mipsdsp_##func(rt_t[i], sa); \
  1481. temp |= (uint64_t)rt_t[i] << (8 * i); \
  1482. } \
  1483. \
  1484. return temp; \
  1485. }
  1486. #define SHIFT_OB_ENV(name, func) \
  1487. target_ulong helper_##name##_ob(target_ulong rt, target_ulong sa, \
  1488. CPUMIPSState *env) \
  1489. { \
  1490. int i; \
  1491. uint8_t rt_t[8]; \
  1492. uint64_t temp; \
  1493. \
  1494. sa = sa & 0x07; \
  1495. temp = 0; \
  1496. \
  1497. for (i = 0; i < 8; i++) { \
  1498. rt_t[i] = (rt >> (8 * i)) & MIPSDSP_Q0; \
  1499. rt_t[i] = mipsdsp_##func(rt_t[i], sa, env); \
  1500. temp |= (uint64_t)rt_t[i] << (8 * i); \
  1501. } \
  1502. \
  1503. return temp; \
  1504. }
  1505. SHIFT_OB_ENV(shll, lshift8);
  1506. SHIFT_OB(shrl, rshift_u8);
  1507. SHIFT_OB(shra, rashift8);
  1508. SHIFT_OB(shra_r, rnd8_rashift);
  1509. #undef SHIFT_OB
  1510. #undef SHIFT_OB_ENV
  1511. #endif
  1512. #define SHIFT_PH(name, func) \
  1513. target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt, \
  1514. CPUMIPSState *env) \
  1515. { \
  1516. uint16_t rth, rtl; \
  1517. \
  1518. sa = sa & 0x0F; \
  1519. \
  1520. MIPSDSP_SPLIT32_16(rt, rth, rtl); \
  1521. \
  1522. rth = mipsdsp_##func(rth, sa, env); \
  1523. rtl = mipsdsp_##func(rtl, sa, env); \
  1524. \
  1525. return MIPSDSP_RETURN32_16(rth, rtl); \
  1526. }
  1527. SHIFT_PH(shll, lshift16);
  1528. SHIFT_PH(shll_s, sat16_lshift);
  1529. #undef SHIFT_PH
  1530. #if defined(TARGET_MIPS64)
  1531. #define SHIFT_QH(name, func) \
  1532. target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa) \
  1533. { \
  1534. uint16_t rt3, rt2, rt1, rt0; \
  1535. \
  1536. sa = sa & 0x0F; \
  1537. \
  1538. MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
  1539. \
  1540. rt3 = mipsdsp_##func(rt3, sa); \
  1541. rt2 = mipsdsp_##func(rt2, sa); \
  1542. rt1 = mipsdsp_##func(rt1, sa); \
  1543. rt0 = mipsdsp_##func(rt0, sa); \
  1544. \
  1545. return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \
  1546. }
  1547. #define SHIFT_QH_ENV(name, func) \
  1548. target_ulong helper_##name##_qh(target_ulong rt, target_ulong sa, \
  1549. CPUMIPSState *env) \
  1550. { \
  1551. uint16_t rt3, rt2, rt1, rt0; \
  1552. \
  1553. sa = sa & 0x0F; \
  1554. \
  1555. MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
  1556. \
  1557. rt3 = mipsdsp_##func(rt3, sa, env); \
  1558. rt2 = mipsdsp_##func(rt2, sa, env); \
  1559. rt1 = mipsdsp_##func(rt1, sa, env); \
  1560. rt0 = mipsdsp_##func(rt0, sa, env); \
  1561. \
  1562. return MIPSDSP_RETURN64_16(rt3, rt2, rt1, rt0); \
  1563. }
  1564. SHIFT_QH_ENV(shll, lshift16);
  1565. SHIFT_QH_ENV(shll_s, sat16_lshift);
  1566. SHIFT_QH(shrl, rshift_u16);
  1567. SHIFT_QH(shra, rashift16);
  1568. SHIFT_QH(shra_r, rnd16_rashift);
  1569. #undef SHIFT_QH
  1570. #undef SHIFT_QH_ENV
  1571. #endif
  1572. #define SHIFT_W(name, func) \
  1573. target_ulong helper_##name##_w(target_ulong sa, target_ulong rt) \
  1574. { \
  1575. uint32_t temp; \
  1576. \
  1577. sa = sa & 0x1F; \
  1578. temp = mipsdsp_##func(rt, sa); \
  1579. \
  1580. return (target_long)(int32_t)temp; \
  1581. }
  1582. #define SHIFT_W_ENV(name, func) \
  1583. target_ulong helper_##name##_w(target_ulong sa, target_ulong rt, \
  1584. CPUMIPSState *env) \
  1585. { \
  1586. uint32_t temp; \
  1587. \
  1588. sa = sa & 0x1F; \
  1589. temp = mipsdsp_##func(rt, sa, env); \
  1590. \
  1591. return (target_long)(int32_t)temp; \
  1592. }
  1593. SHIFT_W_ENV(shll_s, sat32_lshift);
  1594. SHIFT_W(shra_r, rnd32_rashift);
  1595. #undef SHIFT_W
  1596. #undef SHIFT_W_ENV
  1597. #if defined(TARGET_MIPS64)
  1598. #define SHIFT_PW(name, func) \
  1599. target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa) \
  1600. { \
  1601. uint32_t rt1, rt0; \
  1602. \
  1603. sa = sa & 0x1F; \
  1604. MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
  1605. \
  1606. rt1 = mipsdsp_##func(rt1, sa); \
  1607. rt0 = mipsdsp_##func(rt0, sa); \
  1608. \
  1609. return MIPSDSP_RETURN64_32(rt1, rt0); \
  1610. }
  1611. #define SHIFT_PW_ENV(name, func) \
  1612. target_ulong helper_##name##_pw(target_ulong rt, target_ulong sa, \
  1613. CPUMIPSState *env) \
  1614. { \
  1615. uint32_t rt1, rt0; \
  1616. \
  1617. sa = sa & 0x1F; \
  1618. MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
  1619. \
  1620. rt1 = mipsdsp_##func(rt1, sa, env); \
  1621. rt0 = mipsdsp_##func(rt0, sa, env); \
  1622. \
  1623. return MIPSDSP_RETURN64_32(rt1, rt0); \
  1624. }
  1625. SHIFT_PW_ENV(shll, lshift32);
  1626. SHIFT_PW_ENV(shll_s, sat32_lshift);
  1627. SHIFT_PW(shra, rashift32);
  1628. SHIFT_PW(shra_r, rnd32_rashift);
  1629. #undef SHIFT_PW
  1630. #undef SHIFT_PW_ENV
  1631. #endif
  1632. #define SHIFT_PH(name, func) \
  1633. target_ulong helper_##name##_ph(target_ulong sa, target_ulong rt) \
  1634. { \
  1635. uint16_t rth, rtl; \
  1636. \
  1637. sa = sa & 0x0F; \
  1638. \
  1639. MIPSDSP_SPLIT32_16(rt, rth, rtl); \
  1640. \
  1641. rth = mipsdsp_##func(rth, sa); \
  1642. rtl = mipsdsp_##func(rtl, sa); \
  1643. \
  1644. return MIPSDSP_RETURN32_16(rth, rtl); \
  1645. }
  1646. SHIFT_PH(shrl, rshift_u16);
  1647. SHIFT_PH(shra, rashift16);
  1648. SHIFT_PH(shra_r, rnd16_rashift);
  1649. #undef SHIFT_PH
  1650. /** DSP Multiply Sub-class insns **/
  1651. /* Return value made up by two 16bits value.
  1652. * FIXME give the macro a better name.
  1653. */
  1654. #define MUL_RETURN32_16_PH(name, func, \
  1655. rsmov1, rsmov2, rsfilter, \
  1656. rtmov1, rtmov2, rtfilter) \
  1657. target_ulong helper_##name(target_ulong rs, target_ulong rt, \
  1658. CPUMIPSState *env) \
  1659. { \
  1660. uint16_t rsB, rsA, rtB, rtA; \
  1661. \
  1662. rsB = (rs >> rsmov1) & rsfilter; \
  1663. rsA = (rs >> rsmov2) & rsfilter; \
  1664. rtB = (rt >> rtmov1) & rtfilter; \
  1665. rtA = (rt >> rtmov2) & rtfilter; \
  1666. \
  1667. rsB = mipsdsp_##func(rsB, rtB, env); \
  1668. rsA = mipsdsp_##func(rsA, rtA, env); \
  1669. \
  1670. return MIPSDSP_RETURN32_16(rsB, rsA); \
  1671. }
  1672. MUL_RETURN32_16_PH(muleu_s_ph_qbl, mul_u8_u16, \
  1673. 24, 16, MIPSDSP_Q0, \
  1674. 16, 0, MIPSDSP_LO);
  1675. MUL_RETURN32_16_PH(muleu_s_ph_qbr, mul_u8_u16, \
  1676. 8, 0, MIPSDSP_Q0, \
  1677. 16, 0, MIPSDSP_LO);
  1678. MUL_RETURN32_16_PH(mulq_rs_ph, rndq15_mul_q15_q15, \
  1679. 16, 0, MIPSDSP_LO, \
  1680. 16, 0, MIPSDSP_LO);
  1681. MUL_RETURN32_16_PH(mul_ph, mul_i16_i16, \
  1682. 16, 0, MIPSDSP_LO, \
  1683. 16, 0, MIPSDSP_LO);
  1684. MUL_RETURN32_16_PH(mul_s_ph, sat16_mul_i16_i16, \
  1685. 16, 0, MIPSDSP_LO, \
  1686. 16, 0, MIPSDSP_LO);
  1687. MUL_RETURN32_16_PH(mulq_s_ph, sat16_mul_q15_q15, \
  1688. 16, 0, MIPSDSP_LO, \
  1689. 16, 0, MIPSDSP_LO);
  1690. #undef MUL_RETURN32_16_PH
  1691. #define MUL_RETURN32_32_ph(name, func, movbits) \
  1692. target_ulong helper_##name(target_ulong rs, target_ulong rt, \
  1693. CPUMIPSState *env) \
  1694. { \
  1695. int16_t rsh, rth; \
  1696. int32_t temp; \
  1697. \
  1698. rsh = (rs >> movbits) & MIPSDSP_LO; \
  1699. rth = (rt >> movbits) & MIPSDSP_LO; \
  1700. temp = mipsdsp_##func(rsh, rth, env); \
  1701. \
  1702. return (target_long)(int32_t)temp; \
  1703. }
  1704. MUL_RETURN32_32_ph(muleq_s_w_phl, mul_q15_q15_overflowflag21, 16);
  1705. MUL_RETURN32_32_ph(muleq_s_w_phr, mul_q15_q15_overflowflag21, 0);
  1706. #undef MUL_RETURN32_32_ph
  1707. #define MUL_VOID_PH(name, use_ac_env) \
  1708. void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
  1709. CPUMIPSState *env) \
  1710. { \
  1711. int16_t rsh, rsl, rth, rtl; \
  1712. int32_t tempB, tempA; \
  1713. int64_t acc, dotp; \
  1714. \
  1715. MIPSDSP_SPLIT32_16(rs, rsh, rsl); \
  1716. MIPSDSP_SPLIT32_16(rt, rth, rtl); \
  1717. \
  1718. if (use_ac_env == 1) { \
  1719. tempB = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
  1720. tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl, env); \
  1721. } else { \
  1722. tempB = mipsdsp_mul_u16_u16(rsh, rth); \
  1723. tempA = mipsdsp_mul_u16_u16(rsl, rtl); \
  1724. } \
  1725. \
  1726. dotp = (int64_t)tempB - (int64_t)tempA; \
  1727. acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
  1728. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
  1729. dotp = dotp + acc; \
  1730. env->active_tc.HI[ac] = (target_long)(int32_t) \
  1731. ((dotp & MIPSDSP_LHI) >> 32); \
  1732. env->active_tc.LO[ac] = (target_long)(int32_t)(dotp & MIPSDSP_LLO); \
  1733. }
  1734. MUL_VOID_PH(mulsaq_s_w_ph, 1);
  1735. MUL_VOID_PH(mulsa_w_ph, 0);
  1736. #undef MUL_VOID_PH
  1737. #if defined(TARGET_MIPS64)
  1738. #define MUL_RETURN64_16_QH(name, func, \
  1739. rsmov1, rsmov2, rsmov3, rsmov4, rsfilter, \
  1740. rtmov1, rtmov2, rtmov3, rtmov4, rtfilter) \
  1741. target_ulong helper_##name(target_ulong rs, target_ulong rt, \
  1742. CPUMIPSState *env) \
  1743. { \
  1744. uint16_t rs3, rs2, rs1, rs0; \
  1745. uint16_t rt3, rt2, rt1, rt0; \
  1746. uint16_t tempD, tempC, tempB, tempA; \
  1747. \
  1748. rs3 = (rs >> rsmov1) & rsfilter; \
  1749. rs2 = (rs >> rsmov2) & rsfilter; \
  1750. rs1 = (rs >> rsmov3) & rsfilter; \
  1751. rs0 = (rs >> rsmov4) & rsfilter; \
  1752. rt3 = (rt >> rtmov1) & rtfilter; \
  1753. rt2 = (rt >> rtmov2) & rtfilter; \
  1754. rt1 = (rt >> rtmov3) & rtfilter; \
  1755. rt0 = (rt >> rtmov4) & rtfilter; \
  1756. \
  1757. tempD = mipsdsp_##func(rs3, rt3, env); \
  1758. tempC = mipsdsp_##func(rs2, rt2, env); \
  1759. tempB = mipsdsp_##func(rs1, rt1, env); \
  1760. tempA = mipsdsp_##func(rs0, rt0, env); \
  1761. \
  1762. return MIPSDSP_RETURN64_16(tempD, tempC, tempB, tempA); \
  1763. }
  1764. MUL_RETURN64_16_QH(muleu_s_qh_obl, mul_u8_u16, \
  1765. 56, 48, 40, 32, MIPSDSP_Q0, \
  1766. 48, 32, 16, 0, MIPSDSP_LO);
  1767. MUL_RETURN64_16_QH(muleu_s_qh_obr, mul_u8_u16, \
  1768. 24, 16, 8, 0, MIPSDSP_Q0, \
  1769. 48, 32, 16, 0, MIPSDSP_LO);
  1770. MUL_RETURN64_16_QH(mulq_rs_qh, rndq15_mul_q15_q15, \
  1771. 48, 32, 16, 0, MIPSDSP_LO, \
  1772. 48, 32, 16, 0, MIPSDSP_LO);
  1773. #undef MUL_RETURN64_16_QH
  1774. #define MUL_RETURN64_32_QH(name, \
  1775. rsmov1, rsmov2, \
  1776. rtmov1, rtmov2) \
  1777. target_ulong helper_##name(target_ulong rs, target_ulong rt, \
  1778. CPUMIPSState *env) \
  1779. { \
  1780. uint16_t rsB, rsA; \
  1781. uint16_t rtB, rtA; \
  1782. uint32_t tempB, tempA; \
  1783. \
  1784. rsB = (rs >> rsmov1) & MIPSDSP_LO; \
  1785. rsA = (rs >> rsmov2) & MIPSDSP_LO; \
  1786. rtB = (rt >> rtmov1) & MIPSDSP_LO; \
  1787. rtA = (rt >> rtmov2) & MIPSDSP_LO; \
  1788. \
  1789. tempB = mipsdsp_mul_q15_q15(5, rsB, rtB, env); \
  1790. tempA = mipsdsp_mul_q15_q15(5, rsA, rtA, env); \
  1791. \
  1792. return ((uint64_t)tempB << 32) | (uint64_t)tempA; \
  1793. }
  1794. MUL_RETURN64_32_QH(muleq_s_pw_qhl, 48, 32, 48, 32);
  1795. MUL_RETURN64_32_QH(muleq_s_pw_qhr, 16, 0, 16, 0);
  1796. #undef MUL_RETURN64_32_QH
  1797. void helper_mulsaq_s_w_qh(target_ulong rs, target_ulong rt, uint32_t ac,
  1798. CPUMIPSState *env)
  1799. {
  1800. int16_t rs3, rs2, rs1, rs0;
  1801. int16_t rt3, rt2, rt1, rt0;
  1802. int32_t tempD, tempC, tempB, tempA;
  1803. int64_t acc[2];
  1804. int64_t temp[2];
  1805. int64_t temp_sum;
  1806. MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0);
  1807. MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0);
  1808. tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env);
  1809. tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env);
  1810. tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env);
  1811. tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env);
  1812. temp[0] = ((int32_t)tempD - (int32_t)tempC) +
  1813. ((int32_t)tempB - (int32_t)tempA);
  1814. temp[0] = (int64_t)(temp[0] << 30) >> 30;
  1815. if (((temp[0] >> 33) & 0x01) == 0) {
  1816. temp[1] = 0x00;
  1817. } else {
  1818. temp[1] = ~0ull;
  1819. }
  1820. acc[0] = env->active_tc.LO[ac];
  1821. acc[1] = env->active_tc.HI[ac];
  1822. temp_sum = acc[0] + temp[0];
  1823. if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
  1824. ((uint64_t)temp_sum < (uint64_t)temp[0])) {
  1825. acc[1] += 1;
  1826. }
  1827. acc[0] = temp_sum;
  1828. acc[1] += temp[1];
  1829. env->active_tc.HI[ac] = acc[1];
  1830. env->active_tc.LO[ac] = acc[0];
  1831. }
  1832. #endif
  1833. #define DP_QB(name, func, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
  1834. void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
  1835. CPUMIPSState *env) \
  1836. { \
  1837. uint8_t rs3, rs2; \
  1838. uint8_t rt3, rt2; \
  1839. uint16_t tempB, tempA; \
  1840. uint64_t tempC, dotp; \
  1841. \
  1842. rs3 = (rs >> rsmov1) & MIPSDSP_Q0; \
  1843. rs2 = (rs >> rsmov2) & MIPSDSP_Q0; \
  1844. rt3 = (rt >> rtmov1) & MIPSDSP_Q0; \
  1845. rt2 = (rt >> rtmov2) & MIPSDSP_Q0; \
  1846. tempB = mipsdsp_##func(rs3, rt3); \
  1847. tempA = mipsdsp_##func(rs2, rt2); \
  1848. dotp = (int64_t)tempB + (int64_t)tempA; \
  1849. if (is_add) { \
  1850. tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
  1851. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \
  1852. + dotp; \
  1853. } else { \
  1854. tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
  1855. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) \
  1856. - dotp; \
  1857. } \
  1858. \
  1859. env->active_tc.HI[ac] = (target_long)(int32_t) \
  1860. ((tempC & MIPSDSP_LHI) >> 32); \
  1861. env->active_tc.LO[ac] = (target_long)(int32_t)(tempC & MIPSDSP_LLO); \
  1862. }
  1863. DP_QB(dpau_h_qbl, mul_u8_u8, 1, 24, 16, 24, 16);
  1864. DP_QB(dpau_h_qbr, mul_u8_u8, 1, 8, 0, 8, 0);
  1865. DP_QB(dpsu_h_qbl, mul_u8_u8, 0, 24, 16, 24, 16);
  1866. DP_QB(dpsu_h_qbr, mul_u8_u8, 0, 8, 0, 8, 0);
  1867. #undef DP_QB
  1868. #if defined(TARGET_MIPS64)
  1869. #define DP_OB(name, add_sub, \
  1870. rsmov1, rsmov2, rsmov3, rsmov4, \
  1871. rtmov1, rtmov2, rtmov3, rtmov4) \
  1872. void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
  1873. CPUMIPSState *env) \
  1874. { \
  1875. uint8_t rsD, rsC, rsB, rsA; \
  1876. uint8_t rtD, rtC, rtB, rtA; \
  1877. uint16_t tempD, tempC, tempB, tempA; \
  1878. uint64_t temp[2]; \
  1879. uint64_t acc[2]; \
  1880. uint64_t temp_sum; \
  1881. \
  1882. temp[0] = 0; \
  1883. temp[1] = 0; \
  1884. \
  1885. rsD = (rs >> rsmov1) & MIPSDSP_Q0; \
  1886. rsC = (rs >> rsmov2) & MIPSDSP_Q0; \
  1887. rsB = (rs >> rsmov3) & MIPSDSP_Q0; \
  1888. rsA = (rs >> rsmov4) & MIPSDSP_Q0; \
  1889. rtD = (rt >> rtmov1) & MIPSDSP_Q0; \
  1890. rtC = (rt >> rtmov2) & MIPSDSP_Q0; \
  1891. rtB = (rt >> rtmov3) & MIPSDSP_Q0; \
  1892. rtA = (rt >> rtmov4) & MIPSDSP_Q0; \
  1893. \
  1894. tempD = mipsdsp_mul_u8_u8(rsD, rtD); \
  1895. tempC = mipsdsp_mul_u8_u8(rsC, rtC); \
  1896. tempB = mipsdsp_mul_u8_u8(rsB, rtB); \
  1897. tempA = mipsdsp_mul_u8_u8(rsA, rtA); \
  1898. \
  1899. temp[0] = (uint64_t)tempD + (uint64_t)tempC + \
  1900. (uint64_t)tempB + (uint64_t)tempA; \
  1901. \
  1902. acc[0] = env->active_tc.LO[ac]; \
  1903. acc[1] = env->active_tc.HI[ac]; \
  1904. \
  1905. if (add_sub) { \
  1906. temp_sum = acc[0] + temp[0]; \
  1907. if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
  1908. ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
  1909. acc[1] += 1; \
  1910. } \
  1911. temp[0] = temp_sum; \
  1912. temp[1] = acc[1] + temp[1]; \
  1913. } else { \
  1914. temp_sum = acc[0] - temp[0]; \
  1915. if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
  1916. acc[1] -= 1; \
  1917. } \
  1918. temp[0] = temp_sum; \
  1919. temp[1] = acc[1] - temp[1]; \
  1920. } \
  1921. \
  1922. env->active_tc.HI[ac] = temp[1]; \
  1923. env->active_tc.LO[ac] = temp[0]; \
  1924. }
  1925. DP_OB(dpau_h_obl, 1, 56, 48, 40, 32, 56, 48, 40, 32);
  1926. DP_OB(dpau_h_obr, 1, 24, 16, 8, 0, 24, 16, 8, 0);
  1927. DP_OB(dpsu_h_obl, 0, 56, 48, 40, 32, 56, 48, 40, 32);
  1928. DP_OB(dpsu_h_obr, 0, 24, 16, 8, 0, 24, 16, 8, 0);
  1929. #undef DP_OB
  1930. #endif
  1931. #define DP_NOFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
  1932. void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
  1933. CPUMIPSState *env) \
  1934. { \
  1935. int16_t rsB, rsA, rtB, rtA; \
  1936. int32_t tempA, tempB; \
  1937. int64_t acc; \
  1938. \
  1939. rsB = (rs >> rsmov1) & MIPSDSP_LO; \
  1940. rsA = (rs >> rsmov2) & MIPSDSP_LO; \
  1941. rtB = (rt >> rtmov1) & MIPSDSP_LO; \
  1942. rtA = (rt >> rtmov2) & MIPSDSP_LO; \
  1943. \
  1944. tempB = (int32_t)rsB * (int32_t)rtB; \
  1945. tempA = (int32_t)rsA * (int32_t)rtA; \
  1946. \
  1947. acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
  1948. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
  1949. \
  1950. if (is_add) { \
  1951. acc = acc + ((int64_t)tempB + (int64_t)tempA); \
  1952. } else { \
  1953. acc = acc - ((int64_t)tempB + (int64_t)tempA); \
  1954. } \
  1955. \
  1956. env->active_tc.HI[ac] = (target_long)(int32_t)((acc & MIPSDSP_LHI) >> 32); \
  1957. env->active_tc.LO[ac] = (target_long)(int32_t)(acc & MIPSDSP_LLO); \
  1958. }
  1959. DP_NOFUNC_PH(dpa_w_ph, 1, 16, 0, 16, 0);
  1960. DP_NOFUNC_PH(dpax_w_ph, 1, 16, 0, 0, 16);
  1961. DP_NOFUNC_PH(dps_w_ph, 0, 16, 0, 16, 0);
  1962. DP_NOFUNC_PH(dpsx_w_ph, 0, 16, 0, 0, 16);
  1963. #undef DP_NOFUNC_PH
  1964. #define DP_HASFUNC_PH(name, is_add, rsmov1, rsmov2, rtmov1, rtmov2) \
  1965. void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
  1966. CPUMIPSState *env) \
  1967. { \
  1968. int16_t rsB, rsA, rtB, rtA; \
  1969. int32_t tempB, tempA; \
  1970. int64_t acc, dotp; \
  1971. \
  1972. rsB = (rs >> rsmov1) & MIPSDSP_LO; \
  1973. rsA = (rs >> rsmov2) & MIPSDSP_LO; \
  1974. rtB = (rt >> rtmov1) & MIPSDSP_LO; \
  1975. rtA = (rt >> rtmov2) & MIPSDSP_LO; \
  1976. \
  1977. tempB = mipsdsp_mul_q15_q15(ac, rsB, rtB, env); \
  1978. tempA = mipsdsp_mul_q15_q15(ac, rsA, rtA, env); \
  1979. \
  1980. dotp = (int64_t)tempB + (int64_t)tempA; \
  1981. acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
  1982. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
  1983. \
  1984. if (is_add) { \
  1985. acc = acc + dotp; \
  1986. } else { \
  1987. acc = acc - dotp; \
  1988. } \
  1989. \
  1990. env->active_tc.HI[ac] = (target_long)(int32_t) \
  1991. ((acc & MIPSDSP_LHI) >> 32); \
  1992. env->active_tc.LO[ac] = (target_long)(int32_t) \
  1993. (acc & MIPSDSP_LLO); \
  1994. }
  1995. DP_HASFUNC_PH(dpaq_s_w_ph, 1, 16, 0, 16, 0);
  1996. DP_HASFUNC_PH(dpaqx_s_w_ph, 1, 16, 0, 0, 16);
  1997. DP_HASFUNC_PH(dpsq_s_w_ph, 0, 16, 0, 16, 0);
  1998. DP_HASFUNC_PH(dpsqx_s_w_ph, 0, 16, 0, 0, 16);
  1999. #undef DP_HASFUNC_PH
  2000. #define DP_128OPERATION_PH(name, is_add) \
  2001. void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
  2002. CPUMIPSState *env) \
  2003. { \
  2004. int16_t rsh, rsl, rth, rtl; \
  2005. int32_t tempB, tempA, tempC62_31, tempC63; \
  2006. int64_t acc, dotp, tempC; \
  2007. \
  2008. MIPSDSP_SPLIT32_16(rs, rsh, rsl); \
  2009. MIPSDSP_SPLIT32_16(rt, rth, rtl); \
  2010. \
  2011. tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl, env); \
  2012. tempA = mipsdsp_mul_q15_q15(ac, rsl, rth, env); \
  2013. \
  2014. dotp = (int64_t)tempB + (int64_t)tempA; \
  2015. acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
  2016. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
  2017. if (is_add) { \
  2018. tempC = acc + dotp; \
  2019. } else { \
  2020. tempC = acc - dotp; \
  2021. } \
  2022. tempC63 = (tempC >> 63) & 0x01; \
  2023. tempC62_31 = (tempC >> 31) & 0xFFFFFFFF; \
  2024. \
  2025. if ((tempC63 == 0) && (tempC62_31 != 0x00000000)) { \
  2026. tempC = 0x7FFFFFFF; \
  2027. set_DSPControl_overflow_flag(1, 16 + ac, env); \
  2028. } \
  2029. \
  2030. if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) { \
  2031. tempC = (int64_t)(int32_t)0x80000000; \
  2032. set_DSPControl_overflow_flag(1, 16 + ac, env); \
  2033. } \
  2034. \
  2035. env->active_tc.HI[ac] = (target_long)(int32_t) \
  2036. ((tempC & MIPSDSP_LHI) >> 32); \
  2037. env->active_tc.LO[ac] = (target_long)(int32_t) \
  2038. (tempC & MIPSDSP_LLO); \
  2039. }
  2040. DP_128OPERATION_PH(dpaqx_sa_w_ph, 1);
  2041. DP_128OPERATION_PH(dpsqx_sa_w_ph, 0);
  2042. #undef DP_128OPERATION_HP
  2043. #if defined(TARGET_MIPS64)
  2044. #define DP_QH(name, is_add, use_ac_env) \
  2045. void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
  2046. CPUMIPSState *env) \
  2047. { \
  2048. int32_t rs3, rs2, rs1, rs0; \
  2049. int32_t rt3, rt2, rt1, rt0; \
  2050. int32_t tempD, tempC, tempB, tempA; \
  2051. int64_t acc[2]; \
  2052. int64_t temp[2]; \
  2053. int64_t temp_sum; \
  2054. \
  2055. MIPSDSP_SPLIT64_16(rs, rs3, rs2, rs1, rs0); \
  2056. MIPSDSP_SPLIT64_16(rt, rt3, rt2, rt1, rt0); \
  2057. \
  2058. if (use_ac_env) { \
  2059. tempD = mipsdsp_mul_q15_q15(ac, rs3, rt3, env); \
  2060. tempC = mipsdsp_mul_q15_q15(ac, rs2, rt2, env); \
  2061. tempB = mipsdsp_mul_q15_q15(ac, rs1, rt1, env); \
  2062. tempA = mipsdsp_mul_q15_q15(ac, rs0, rt0, env); \
  2063. } else { \
  2064. tempD = mipsdsp_mul_u16_u16(rs3, rt3); \
  2065. tempC = mipsdsp_mul_u16_u16(rs2, rt2); \
  2066. tempB = mipsdsp_mul_u16_u16(rs1, rt1); \
  2067. tempA = mipsdsp_mul_u16_u16(rs0, rt0); \
  2068. } \
  2069. \
  2070. temp[0] = (int64_t)tempD + (int64_t)tempC + \
  2071. (int64_t)tempB + (int64_t)tempA; \
  2072. \
  2073. if (temp[0] >= 0) { \
  2074. temp[1] = 0; \
  2075. } else { \
  2076. temp[1] = ~0ull; \
  2077. } \
  2078. \
  2079. acc[1] = env->active_tc.HI[ac]; \
  2080. acc[0] = env->active_tc.LO[ac]; \
  2081. \
  2082. if (is_add) { \
  2083. temp_sum = acc[0] + temp[0]; \
  2084. if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
  2085. ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
  2086. acc[1] = acc[1] + 1; \
  2087. } \
  2088. temp[0] = temp_sum; \
  2089. temp[1] = acc[1] + temp[1]; \
  2090. } else { \
  2091. temp_sum = acc[0] - temp[0]; \
  2092. if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
  2093. acc[1] = acc[1] - 1; \
  2094. } \
  2095. temp[0] = temp_sum; \
  2096. temp[1] = acc[1] - temp[1]; \
  2097. } \
  2098. \
  2099. env->active_tc.HI[ac] = temp[1]; \
  2100. env->active_tc.LO[ac] = temp[0]; \
  2101. }
  2102. DP_QH(dpa_w_qh, 1, 0);
  2103. DP_QH(dpaq_s_w_qh, 1, 1);
  2104. DP_QH(dps_w_qh, 0, 0);
  2105. DP_QH(dpsq_s_w_qh, 0, 1);
  2106. #undef DP_QH
  2107. #endif
  2108. #define DP_L_W(name, is_add) \
  2109. void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
  2110. CPUMIPSState *env) \
  2111. { \
  2112. int32_t temp63; \
  2113. int64_t dotp, acc; \
  2114. uint64_t temp; \
  2115. bool overflow; \
  2116. \
  2117. dotp = mipsdsp_mul_q31_q31(ac, rs, rt, env); \
  2118. acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
  2119. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
  2120. if (is_add) { \
  2121. temp = acc + dotp; \
  2122. overflow = MIPSDSP_OVERFLOW_ADD((uint64_t)acc, (uint64_t)dotp, \
  2123. temp, (0x01ull << 63)); \
  2124. } else { \
  2125. temp = acc - dotp; \
  2126. overflow = MIPSDSP_OVERFLOW_SUB((uint64_t)acc, (uint64_t)dotp, \
  2127. temp, (0x01ull << 63)); \
  2128. } \
  2129. \
  2130. if (overflow) { \
  2131. temp63 = (temp >> 63) & 0x01; \
  2132. if (temp63 == 1) { \
  2133. temp = (0x01ull << 63) - 1; \
  2134. } else { \
  2135. temp = 0x01ull << 63; \
  2136. } \
  2137. \
  2138. set_DSPControl_overflow_flag(1, 16 + ac, env); \
  2139. } \
  2140. \
  2141. env->active_tc.HI[ac] = (target_long)(int32_t) \
  2142. ((temp & MIPSDSP_LHI) >> 32); \
  2143. env->active_tc.LO[ac] = (target_long)(int32_t) \
  2144. (temp & MIPSDSP_LLO); \
  2145. }
  2146. DP_L_W(dpaq_sa_l_w, 1);
  2147. DP_L_W(dpsq_sa_l_w, 0);
  2148. #undef DP_L_W
  2149. #if defined(TARGET_MIPS64)
  2150. #define DP_L_PW(name, func) \
  2151. void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
  2152. CPUMIPSState *env) \
  2153. { \
  2154. int32_t rs1, rs0; \
  2155. int32_t rt1, rt0; \
  2156. int64_t tempB[2], tempA[2]; \
  2157. int64_t temp[2]; \
  2158. int64_t acc[2]; \
  2159. int64_t temp_sum; \
  2160. \
  2161. temp[0] = 0; \
  2162. temp[1] = 0; \
  2163. \
  2164. MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
  2165. MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
  2166. \
  2167. tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env); \
  2168. tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env); \
  2169. \
  2170. if (tempB[0] >= 0) { \
  2171. tempB[1] = 0x00; \
  2172. } else { \
  2173. tempB[1] = ~0ull; \
  2174. } \
  2175. \
  2176. if (tempA[0] >= 0) { \
  2177. tempA[1] = 0x00; \
  2178. } else { \
  2179. tempA[1] = ~0ull; \
  2180. } \
  2181. \
  2182. temp_sum = tempB[0] + tempA[0]; \
  2183. if (((uint64_t)temp_sum < (uint64_t)tempB[0]) && \
  2184. ((uint64_t)temp_sum < (uint64_t)tempA[0])) { \
  2185. temp[1] += 1; \
  2186. } \
  2187. temp[0] = temp_sum; \
  2188. temp[1] += tempB[1] + tempA[1]; \
  2189. \
  2190. mipsdsp_##func(acc, ac, temp, env); \
  2191. \
  2192. env->active_tc.HI[ac] = acc[1]; \
  2193. env->active_tc.LO[ac] = acc[0]; \
  2194. }
  2195. DP_L_PW(dpaq_sa_l_pw, sat64_acc_add_q63);
  2196. DP_L_PW(dpsq_sa_l_pw, sat64_acc_sub_q63);
  2197. #undef DP_L_PW
  2198. void helper_mulsaq_s_l_pw(target_ulong rs, target_ulong rt, uint32_t ac,
  2199. CPUMIPSState *env)
  2200. {
  2201. int32_t rs1, rs0;
  2202. int32_t rt1, rt0;
  2203. int64_t tempB[2], tempA[2];
  2204. int64_t temp[2];
  2205. int64_t acc[2];
  2206. int64_t temp_sum;
  2207. rs1 = (rs >> 32) & MIPSDSP_LLO;
  2208. rs0 = rs & MIPSDSP_LLO;
  2209. rt1 = (rt >> 32) & MIPSDSP_LLO;
  2210. rt0 = rt & MIPSDSP_LLO;
  2211. tempB[0] = mipsdsp_mul_q31_q31(ac, rs1, rt1, env);
  2212. tempA[0] = mipsdsp_mul_q31_q31(ac, rs0, rt0, env);
  2213. if (tempB[0] >= 0) {
  2214. tempB[1] = 0x00;
  2215. } else {
  2216. tempB[1] = ~0ull;
  2217. }
  2218. if (tempA[0] >= 0) {
  2219. tempA[1] = 0x00;
  2220. } else {
  2221. tempA[1] = ~0ull;
  2222. }
  2223. acc[0] = env->active_tc.LO[ac];
  2224. acc[1] = env->active_tc.HI[ac];
  2225. temp_sum = tempB[0] - tempA[0];
  2226. if ((uint64_t)temp_sum > (uint64_t)tempB[0]) {
  2227. tempB[1] -= 1;
  2228. }
  2229. temp[0] = temp_sum;
  2230. temp[1] = tempB[1] - tempA[1];
  2231. if ((temp[1] & 0x01) == 0) {
  2232. temp[1] = 0x00;
  2233. } else {
  2234. temp[1] = ~0ull;
  2235. }
  2236. temp_sum = acc[0] + temp[0];
  2237. if (((uint64_t)temp_sum < (uint64_t)acc[0]) &&
  2238. ((uint64_t)temp_sum < (uint64_t)temp[0])) {
  2239. acc[1] += 1;
  2240. }
  2241. acc[0] = temp_sum;
  2242. acc[1] += temp[1];
  2243. env->active_tc.HI[ac] = acc[1];
  2244. env->active_tc.LO[ac] = acc[0];
  2245. }
  2246. #endif
  2247. #define MAQ_S_W(name, mov) \
  2248. void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
  2249. CPUMIPSState *env) \
  2250. { \
  2251. int16_t rsh, rth; \
  2252. int32_t tempA; \
  2253. int64_t tempL, acc; \
  2254. \
  2255. rsh = (rs >> mov) & MIPSDSP_LO; \
  2256. rth = (rt >> mov) & MIPSDSP_LO; \
  2257. tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
  2258. acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
  2259. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO); \
  2260. tempL = (int64_t)tempA + acc; \
  2261. env->active_tc.HI[ac] = (target_long)(int32_t) \
  2262. ((tempL & MIPSDSP_LHI) >> 32); \
  2263. env->active_tc.LO[ac] = (target_long)(int32_t) \
  2264. (tempL & MIPSDSP_LLO); \
  2265. }
  2266. MAQ_S_W(maq_s_w_phl, 16);
  2267. MAQ_S_W(maq_s_w_phr, 0);
  2268. #undef MAQ_S_W
  2269. #define MAQ_SA_W(name, mov) \
  2270. void helper_##name(uint32_t ac, target_ulong rs, target_ulong rt, \
  2271. CPUMIPSState *env) \
  2272. { \
  2273. int16_t rsh, rth; \
  2274. int32_t tempA; \
  2275. \
  2276. rsh = (rs >> mov) & MIPSDSP_LO; \
  2277. rth = (rt >> mov) & MIPSDSP_LO; \
  2278. tempA = mipsdsp_mul_q15_q15(ac, rsh, rth, env); \
  2279. tempA = mipsdsp_sat32_acc_q31(ac, tempA, env); \
  2280. \
  2281. env->active_tc.HI[ac] = (target_long)(int32_t)(((int64_t)tempA & \
  2282. MIPSDSP_LHI) >> 32); \
  2283. env->active_tc.LO[ac] = (target_long)(int32_t)((int64_t)tempA & \
  2284. MIPSDSP_LLO); \
  2285. }
  2286. MAQ_SA_W(maq_sa_w_phl, 16);
  2287. MAQ_SA_W(maq_sa_w_phr, 0);
  2288. #undef MAQ_SA_W
  2289. #define MULQ_W(name, addvar) \
  2290. target_ulong helper_##name(target_ulong rs, target_ulong rt, \
  2291. CPUMIPSState *env) \
  2292. { \
  2293. int32_t rs_t, rt_t; \
  2294. int32_t tempI; \
  2295. int64_t tempL; \
  2296. \
  2297. rs_t = rs & MIPSDSP_LLO; \
  2298. rt_t = rt & MIPSDSP_LLO; \
  2299. \
  2300. if ((rs_t == 0x80000000) && (rt_t == 0x80000000)) { \
  2301. tempL = 0x7FFFFFFF00000000ull; \
  2302. set_DSPControl_overflow_flag(1, 21, env); \
  2303. } else { \
  2304. tempL = ((int64_t)rs_t * (int64_t)rt_t) << 1; \
  2305. tempL += addvar; \
  2306. } \
  2307. tempI = (tempL & MIPSDSP_LHI) >> 32; \
  2308. \
  2309. return (target_long)(int32_t)tempI; \
  2310. }
  2311. MULQ_W(mulq_s_w, 0);
  2312. MULQ_W(mulq_rs_w, 0x80000000ull);
  2313. #undef MULQ_W
  2314. #if defined(TARGET_MIPS64)
  2315. #define MAQ_S_W_QH(name, mov) \
  2316. void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
  2317. CPUMIPSState *env) \
  2318. { \
  2319. int16_t rs_t, rt_t; \
  2320. int32_t temp_mul; \
  2321. int64_t temp[2]; \
  2322. int64_t acc[2]; \
  2323. int64_t temp_sum; \
  2324. \
  2325. temp[0] = 0; \
  2326. temp[1] = 0; \
  2327. \
  2328. rs_t = (rs >> mov) & MIPSDSP_LO; \
  2329. rt_t = (rt >> mov) & MIPSDSP_LO; \
  2330. temp_mul = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \
  2331. \
  2332. temp[0] = (int64_t)temp_mul; \
  2333. if (temp[0] >= 0) { \
  2334. temp[1] = 0x00; \
  2335. } else { \
  2336. temp[1] = ~0ull; \
  2337. } \
  2338. \
  2339. acc[0] = env->active_tc.LO[ac]; \
  2340. acc[1] = env->active_tc.HI[ac]; \
  2341. \
  2342. temp_sum = acc[0] + temp[0]; \
  2343. if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
  2344. ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
  2345. acc[1] += 1; \
  2346. } \
  2347. acc[0] = temp_sum; \
  2348. acc[1] += temp[1]; \
  2349. \
  2350. env->active_tc.HI[ac] = acc[1]; \
  2351. env->active_tc.LO[ac] = acc[0]; \
  2352. }
  2353. MAQ_S_W_QH(maq_s_w_qhll, 48);
  2354. MAQ_S_W_QH(maq_s_w_qhlr, 32);
  2355. MAQ_S_W_QH(maq_s_w_qhrl, 16);
  2356. MAQ_S_W_QH(maq_s_w_qhrr, 0);
  2357. #undef MAQ_S_W_QH
  2358. #define MAQ_SA_W(name, mov) \
  2359. void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
  2360. CPUMIPSState *env) \
  2361. { \
  2362. int16_t rs_t, rt_t; \
  2363. int32_t temp; \
  2364. int64_t acc[2]; \
  2365. \
  2366. rs_t = (rs >> mov) & MIPSDSP_LO; \
  2367. rt_t = (rt >> mov) & MIPSDSP_LO; \
  2368. temp = mipsdsp_mul_q15_q15(ac, rs_t, rt_t, env); \
  2369. temp = mipsdsp_sat32_acc_q31(ac, temp, env); \
  2370. \
  2371. acc[0] = (int64_t)(int32_t)temp; \
  2372. if (acc[0] >= 0) { \
  2373. acc[1] = 0x00; \
  2374. } else { \
  2375. acc[1] = ~0ull; \
  2376. } \
  2377. \
  2378. env->active_tc.HI[ac] = acc[1]; \
  2379. env->active_tc.LO[ac] = acc[0]; \
  2380. }
  2381. MAQ_SA_W(maq_sa_w_qhll, 48);
  2382. MAQ_SA_W(maq_sa_w_qhlr, 32);
  2383. MAQ_SA_W(maq_sa_w_qhrl, 16);
  2384. MAQ_SA_W(maq_sa_w_qhrr, 0);
  2385. #undef MAQ_SA_W
  2386. #define MAQ_S_L_PW(name, mov) \
  2387. void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
  2388. CPUMIPSState *env) \
  2389. { \
  2390. int32_t rs_t, rt_t; \
  2391. int64_t temp[2]; \
  2392. int64_t acc[2]; \
  2393. int64_t temp_sum; \
  2394. \
  2395. temp[0] = 0; \
  2396. temp[1] = 0; \
  2397. \
  2398. rs_t = (rs >> mov) & MIPSDSP_LLO; \
  2399. rt_t = (rt >> mov) & MIPSDSP_LLO; \
  2400. \
  2401. temp[0] = mipsdsp_mul_q31_q31(ac, rs_t, rt_t, env); \
  2402. if (temp[0] >= 0) { \
  2403. temp[1] = 0x00; \
  2404. } else { \
  2405. temp[1] = ~0ull; \
  2406. } \
  2407. \
  2408. acc[0] = env->active_tc.LO[ac]; \
  2409. acc[1] = env->active_tc.HI[ac]; \
  2410. \
  2411. temp_sum = acc[0] + temp[0]; \
  2412. if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
  2413. ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
  2414. acc[1] += 1; \
  2415. } \
  2416. acc[0] = temp_sum; \
  2417. acc[1] += temp[1]; \
  2418. \
  2419. env->active_tc.HI[ac] = acc[1]; \
  2420. env->active_tc.LO[ac] = acc[0]; \
  2421. }
  2422. MAQ_S_L_PW(maq_s_l_pwl, 32);
  2423. MAQ_S_L_PW(maq_s_l_pwr, 0);
  2424. #undef MAQ_S_L_PW
  2425. #define DM_OPERATE(name, func, is_add, sigext) \
  2426. void helper_##name(target_ulong rs, target_ulong rt, uint32_t ac, \
  2427. CPUMIPSState *env) \
  2428. { \
  2429. int32_t rs1, rs0; \
  2430. int32_t rt1, rt0; \
  2431. int64_t tempBL[2], tempAL[2]; \
  2432. int64_t acc[2]; \
  2433. int64_t temp[2]; \
  2434. int64_t temp_sum; \
  2435. \
  2436. temp[0] = 0x00; \
  2437. temp[1] = 0x00; \
  2438. \
  2439. MIPSDSP_SPLIT64_32(rs, rs1, rs0); \
  2440. MIPSDSP_SPLIT64_32(rt, rt1, rt0); \
  2441. \
  2442. if (sigext) { \
  2443. tempBL[0] = (int64_t)mipsdsp_##func(rs1, rt1); \
  2444. tempAL[0] = (int64_t)mipsdsp_##func(rs0, rt0); \
  2445. \
  2446. if (tempBL[0] >= 0) { \
  2447. tempBL[1] = 0x0; \
  2448. } else { \
  2449. tempBL[1] = ~0ull; \
  2450. } \
  2451. \
  2452. if (tempAL[0] >= 0) { \
  2453. tempAL[1] = 0x0; \
  2454. } else { \
  2455. tempAL[1] = ~0ull; \
  2456. } \
  2457. } else { \
  2458. tempBL[0] = mipsdsp_##func(rs1, rt1); \
  2459. tempAL[0] = mipsdsp_##func(rs0, rt0); \
  2460. tempBL[1] = 0; \
  2461. tempAL[1] = 0; \
  2462. } \
  2463. \
  2464. acc[1] = env->active_tc.HI[ac]; \
  2465. acc[0] = env->active_tc.LO[ac]; \
  2466. \
  2467. temp_sum = tempBL[0] + tempAL[0]; \
  2468. if (((uint64_t)temp_sum < (uint64_t)tempBL[0]) && \
  2469. ((uint64_t)temp_sum < (uint64_t)tempAL[0])) { \
  2470. temp[1] += 1; \
  2471. } \
  2472. temp[0] = temp_sum; \
  2473. temp[1] += tempBL[1] + tempAL[1]; \
  2474. \
  2475. if (is_add) { \
  2476. temp_sum = acc[0] + temp[0]; \
  2477. if (((uint64_t)temp_sum < (uint64_t)acc[0]) && \
  2478. ((uint64_t)temp_sum < (uint64_t)temp[0])) { \
  2479. acc[1] += 1; \
  2480. } \
  2481. temp[0] = temp_sum; \
  2482. temp[1] = acc[1] + temp[1]; \
  2483. } else { \
  2484. temp_sum = acc[0] - temp[0]; \
  2485. if ((uint64_t)temp_sum > (uint64_t)acc[0]) { \
  2486. acc[1] -= 1; \
  2487. } \
  2488. temp[0] = temp_sum; \
  2489. temp[1] = acc[1] - temp[1]; \
  2490. } \
  2491. \
  2492. env->active_tc.HI[ac] = temp[1]; \
  2493. env->active_tc.LO[ac] = temp[0]; \
  2494. }
  2495. DM_OPERATE(dmadd, mul_i32_i32, 1, 1);
  2496. DM_OPERATE(dmaddu, mul_u32_u32, 1, 0);
  2497. DM_OPERATE(dmsub, mul_i32_i32, 0, 1);
  2498. DM_OPERATE(dmsubu, mul_u32_u32, 0, 0);
  2499. #undef DM_OPERATE
  2500. #endif
  2501. /** DSP Bit/Manipulation Sub-class insns **/
  2502. target_ulong helper_bitrev(target_ulong rt)
  2503. {
  2504. int32_t temp;
  2505. uint32_t rd;
  2506. int i;
  2507. temp = rt & MIPSDSP_LO;
  2508. rd = 0;
  2509. for (i = 0; i < 16; i++) {
  2510. rd = (rd << 1) | (temp & 1);
  2511. temp = temp >> 1;
  2512. }
  2513. return (target_ulong)rd;
  2514. }
  2515. #define BIT_INSV(name, posfilter, sizefilter, ret_type) \
  2516. target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
  2517. target_ulong rt) \
  2518. { \
  2519. uint32_t pos, size, msb, lsb; \
  2520. target_ulong filter; \
  2521. target_ulong temp, temprs, temprt; \
  2522. target_ulong dspc; \
  2523. \
  2524. dspc = env->active_tc.DSPControl; \
  2525. \
  2526. pos = dspc & posfilter; \
  2527. size = (dspc >> 7) & sizefilter; \
  2528. \
  2529. msb = pos + size - 1; \
  2530. lsb = pos; \
  2531. \
  2532. if (lsb > msb || (msb > TARGET_LONG_BITS)) { \
  2533. return rt; \
  2534. } \
  2535. \
  2536. filter = ((int32_t)0x01 << size) - 1; \
  2537. filter = filter << pos; \
  2538. temprs = (rs << pos) & filter; \
  2539. temprt = rt & ~filter; \
  2540. temp = temprs | temprt; \
  2541. \
  2542. return (target_long)(ret_type)temp; \
  2543. }
  2544. BIT_INSV(insv, 0x1F, 0x1F, int32_t);
  2545. #ifdef TARGET_MIPS64
  2546. BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
  2547. #endif
  2548. #undef BIT_INSV
  2549. /** DSP Compare-Pick Sub-class insns **/
  2550. #define CMP_HAS_RET(name, func, split_num, filter, bit_size) \
  2551. target_ulong helper_##name(target_ulong rs, target_ulong rt) \
  2552. { \
  2553. uint32_t rs_t, rt_t; \
  2554. uint8_t cc; \
  2555. uint32_t temp = 0; \
  2556. int i; \
  2557. \
  2558. for (i = 0; i < split_num; i++) { \
  2559. rs_t = (rs >> (bit_size * i)) & filter; \
  2560. rt_t = (rt >> (bit_size * i)) & filter; \
  2561. cc = mipsdsp_##func(rs_t, rt_t); \
  2562. temp |= cc << i; \
  2563. } \
  2564. \
  2565. return (target_ulong)temp; \
  2566. }
  2567. CMP_HAS_RET(cmpgu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
  2568. CMP_HAS_RET(cmpgu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
  2569. CMP_HAS_RET(cmpgu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
  2570. #ifdef TARGET_MIPS64
  2571. CMP_HAS_RET(cmpgu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
  2572. CMP_HAS_RET(cmpgu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
  2573. CMP_HAS_RET(cmpgu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
  2574. #endif
  2575. #undef CMP_HAS_RET
  2576. #define CMP_NO_RET(name, func, split_num, filter, bit_size) \
  2577. void helper_##name(target_ulong rs, target_ulong rt, \
  2578. CPUMIPSState *env) \
  2579. { \
  2580. int##bit_size##_t rs_t, rt_t; \
  2581. int##bit_size##_t flag = 0; \
  2582. int##bit_size##_t cc; \
  2583. int i; \
  2584. \
  2585. for (i = 0; i < split_num; i++) { \
  2586. rs_t = (rs >> (bit_size * i)) & filter; \
  2587. rt_t = (rt >> (bit_size * i)) & filter; \
  2588. \
  2589. cc = mipsdsp_##func((int32_t)rs_t, (int32_t)rt_t); \
  2590. flag |= cc << i; \
  2591. } \
  2592. \
  2593. set_DSPControl_24(flag, split_num, env); \
  2594. }
  2595. CMP_NO_RET(cmpu_eq_qb, cmpu_eq, 4, MIPSDSP_Q0, 8);
  2596. CMP_NO_RET(cmpu_lt_qb, cmpu_lt, 4, MIPSDSP_Q0, 8);
  2597. CMP_NO_RET(cmpu_le_qb, cmpu_le, 4, MIPSDSP_Q0, 8);
  2598. CMP_NO_RET(cmp_eq_ph, cmp_eq, 2, MIPSDSP_LO, 16);
  2599. CMP_NO_RET(cmp_lt_ph, cmp_lt, 2, MIPSDSP_LO, 16);
  2600. CMP_NO_RET(cmp_le_ph, cmp_le, 2, MIPSDSP_LO, 16);
  2601. #ifdef TARGET_MIPS64
  2602. CMP_NO_RET(cmpu_eq_ob, cmpu_eq, 8, MIPSDSP_Q0, 8);
  2603. CMP_NO_RET(cmpu_lt_ob, cmpu_lt, 8, MIPSDSP_Q0, 8);
  2604. CMP_NO_RET(cmpu_le_ob, cmpu_le, 8, MIPSDSP_Q0, 8);
  2605. CMP_NO_RET(cmp_eq_qh, cmp_eq, 4, MIPSDSP_LO, 16);
  2606. CMP_NO_RET(cmp_lt_qh, cmp_lt, 4, MIPSDSP_LO, 16);
  2607. CMP_NO_RET(cmp_le_qh, cmp_le, 4, MIPSDSP_LO, 16);
  2608. CMP_NO_RET(cmp_eq_pw, cmp_eq, 2, MIPSDSP_LLO, 32);
  2609. CMP_NO_RET(cmp_lt_pw, cmp_lt, 2, MIPSDSP_LLO, 32);
  2610. CMP_NO_RET(cmp_le_pw, cmp_le, 2, MIPSDSP_LLO, 32);
  2611. #endif
  2612. #undef CMP_NO_RET
  2613. #if defined(TARGET_MIPS64)
  2614. #define CMPGDU_OB(name) \
  2615. target_ulong helper_cmpgdu_##name##_ob(target_ulong rs, target_ulong rt, \
  2616. CPUMIPSState *env) \
  2617. { \
  2618. int i; \
  2619. uint8_t rs_t, rt_t; \
  2620. uint32_t cond; \
  2621. \
  2622. cond = 0; \
  2623. \
  2624. for (i = 0; i < 8; i++) { \
  2625. rs_t = (rs >> (8 * i)) & MIPSDSP_Q0; \
  2626. rt_t = (rt >> (8 * i)) & MIPSDSP_Q0; \
  2627. \
  2628. if (mipsdsp_cmpu_##name(rs_t, rt_t)) { \
  2629. cond |= 0x01 << i; \
  2630. } \
  2631. } \
  2632. \
  2633. set_DSPControl_24(cond, 8, env); \
  2634. \
  2635. return (uint64_t)cond; \
  2636. }
  2637. CMPGDU_OB(eq)
  2638. CMPGDU_OB(lt)
  2639. CMPGDU_OB(le)
  2640. #undef CMPGDU_OB
  2641. #endif
  2642. #define PICK_INSN(name, split_num, filter, bit_size, ret32bit) \
  2643. target_ulong helper_##name(target_ulong rs, target_ulong rt, \
  2644. CPUMIPSState *env) \
  2645. { \
  2646. uint32_t rs_t, rt_t; \
  2647. uint32_t cc; \
  2648. target_ulong dsp; \
  2649. int i; \
  2650. target_ulong result = 0; \
  2651. \
  2652. dsp = env->active_tc.DSPControl; \
  2653. for (i = 0; i < split_num; i++) { \
  2654. rs_t = (rs >> (bit_size * i)) & filter; \
  2655. rt_t = (rt >> (bit_size * i)) & filter; \
  2656. cc = (dsp >> (24 + i)) & 0x01; \
  2657. cc = cc == 1 ? rs_t : rt_t; \
  2658. \
  2659. result |= (target_ulong)cc << (bit_size * i); \
  2660. } \
  2661. \
  2662. if (ret32bit) { \
  2663. result = (target_long)(int32_t)(result & MIPSDSP_LLO); \
  2664. } \
  2665. \
  2666. return result; \
  2667. }
  2668. PICK_INSN(pick_qb, 4, MIPSDSP_Q0, 8, 1);
  2669. PICK_INSN(pick_ph, 2, MIPSDSP_LO, 16, 1);
  2670. #ifdef TARGET_MIPS64
  2671. PICK_INSN(pick_ob, 8, MIPSDSP_Q0, 8, 0);
  2672. PICK_INSN(pick_qh, 4, MIPSDSP_LO, 16, 0);
  2673. PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
  2674. #endif
  2675. #undef PICK_INSN
  2676. target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
  2677. {
  2678. uint32_t rsl, rth;
  2679. rsl = rs & MIPSDSP_LO;
  2680. rth = (rt & MIPSDSP_HI) >> 16;
  2681. return (target_long)(int32_t)((rsl << 16) | rth);
  2682. }
  2683. #if defined(TARGET_MIPS64)
  2684. target_ulong helper_packrl_pw(target_ulong rs, target_ulong rt)
  2685. {
  2686. uint32_t rs0, rt1;
  2687. rs0 = rs & MIPSDSP_LLO;
  2688. rt1 = (rt >> 32) & MIPSDSP_LLO;
  2689. return ((uint64_t)rs0 << 32) | (uint64_t)rt1;
  2690. }
  2691. #endif
  2692. /** DSP Accumulator and DSPControl Access Sub-class insns **/
  2693. target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
  2694. CPUMIPSState *env)
  2695. {
  2696. int32_t tempI;
  2697. int64_t tempDL[2];
  2698. shift = shift & 0x1F;
  2699. mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
  2700. if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
  2701. (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
  2702. set_DSPControl_overflow_flag(1, 23, env);
  2703. }
  2704. tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
  2705. tempDL[0] += 1;
  2706. if (tempDL[0] == 0) {
  2707. tempDL[1] += 1;
  2708. }
  2709. if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
  2710. ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
  2711. set_DSPControl_overflow_flag(1, 23, env);
  2712. }
  2713. return (target_long)tempI;
  2714. }
  2715. target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
  2716. CPUMIPSState *env)
  2717. {
  2718. int64_t tempDL[2];
  2719. shift = shift & 0x1F;
  2720. mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
  2721. if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
  2722. (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
  2723. set_DSPControl_overflow_flag(1, 23, env);
  2724. }
  2725. tempDL[0] += 1;
  2726. if (tempDL[0] == 0) {
  2727. tempDL[1] += 1;
  2728. }
  2729. if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
  2730. ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
  2731. set_DSPControl_overflow_flag(1, 23, env);
  2732. }
  2733. return (target_long)(int32_t)(tempDL[0] >> 1);
  2734. }
  2735. target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
  2736. CPUMIPSState *env)
  2737. {
  2738. int32_t tempI, temp64;
  2739. int64_t tempDL[2];
  2740. shift = shift & 0x1F;
  2741. mipsdsp_rndrashift_short_acc(tempDL, ac, shift, env);
  2742. if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
  2743. (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
  2744. set_DSPControl_overflow_flag(1, 23, env);
  2745. }
  2746. tempDL[0] += 1;
  2747. if (tempDL[0] == 0) {
  2748. tempDL[1] += 1;
  2749. }
  2750. tempI = tempDL[0] >> 1;
  2751. if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
  2752. ((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
  2753. temp64 = tempDL[1] & 0x01;
  2754. if (temp64 == 0) {
  2755. tempI = 0x7FFFFFFF;
  2756. } else {
  2757. tempI = 0x80000000;
  2758. }
  2759. set_DSPControl_overflow_flag(1, 23, env);
  2760. }
  2761. return (target_long)tempI;
  2762. }
  2763. #if defined(TARGET_MIPS64)
  2764. target_ulong helper_dextr_w(target_ulong ac, target_ulong shift,
  2765. CPUMIPSState *env)
  2766. {
  2767. uint64_t temp[3];
  2768. shift = shift & 0x3F;
  2769. mipsdsp_rndrashift_acc(temp, ac, shift, env);
  2770. return (int64_t)(int32_t)(temp[0] >> 1);
  2771. }
  2772. target_ulong helper_dextr_r_w(target_ulong ac, target_ulong shift,
  2773. CPUMIPSState *env)
  2774. {
  2775. uint64_t temp[3];
  2776. uint32_t temp128;
  2777. shift = shift & 0x3F;
  2778. mipsdsp_rndrashift_acc(temp, ac, shift, env);
  2779. temp[0] += 1;
  2780. if (temp[0] == 0) {
  2781. temp[1] += 1;
  2782. if (temp[1] == 0) {
  2783. temp[2] += 1;
  2784. }
  2785. }
  2786. temp128 = temp[2] & 0x01;
  2787. if ((temp128 != 0 || temp[1] != 0) &&
  2788. (temp128 != 1 || temp[1] != ~0ull)) {
  2789. set_DSPControl_overflow_flag(1, 23, env);
  2790. }
  2791. return (int64_t)(int32_t)(temp[0] >> 1);
  2792. }
  2793. target_ulong helper_dextr_rs_w(target_ulong ac, target_ulong shift,
  2794. CPUMIPSState *env)
  2795. {
  2796. uint64_t temp[3];
  2797. uint32_t temp128;
  2798. shift = shift & 0x3F;
  2799. mipsdsp_rndrashift_acc(temp, ac, shift, env);
  2800. temp[0] += 1;
  2801. if (temp[0] == 0) {
  2802. temp[1] += 1;
  2803. if (temp[1] == 0) {
  2804. temp[2] += 1;
  2805. }
  2806. }
  2807. temp128 = temp[2] & 0x01;
  2808. if ((temp128 != 0 || temp[1] != 0) &&
  2809. (temp128 != 1 || temp[1] != ~0ull)) {
  2810. if (temp128 == 0) {
  2811. temp[0] = 0x0FFFFFFFF;
  2812. } else {
  2813. temp[0] = 0x0100000000ULL;
  2814. }
  2815. set_DSPControl_overflow_flag(1, 23, env);
  2816. }
  2817. return (int64_t)(int32_t)(temp[0] >> 1);
  2818. }
  2819. target_ulong helper_dextr_l(target_ulong ac, target_ulong shift,
  2820. CPUMIPSState *env)
  2821. {
  2822. uint64_t temp[3];
  2823. target_ulong result;
  2824. shift = shift & 0x3F;
  2825. mipsdsp_rndrashift_acc(temp, ac, shift, env);
  2826. result = (temp[1] << 63) | (temp[0] >> 1);
  2827. return result;
  2828. }
  2829. target_ulong helper_dextr_r_l(target_ulong ac, target_ulong shift,
  2830. CPUMIPSState *env)
  2831. {
  2832. uint64_t temp[3];
  2833. uint32_t temp128;
  2834. target_ulong result;
  2835. shift = shift & 0x3F;
  2836. mipsdsp_rndrashift_acc(temp, ac, shift, env);
  2837. temp[0] += 1;
  2838. if (temp[0] == 0) {
  2839. temp[1] += 1;
  2840. if (temp[1] == 0) {
  2841. temp[2] += 1;
  2842. }
  2843. }
  2844. temp128 = temp[2] & 0x01;
  2845. if ((temp128 != 0 || temp[1] != 0) &&
  2846. (temp128 != 1 || temp[1] != ~0ull)) {
  2847. set_DSPControl_overflow_flag(1, 23, env);
  2848. }
  2849. result = (temp[1] << 63) | (temp[0] >> 1);
  2850. return result;
  2851. }
  2852. target_ulong helper_dextr_rs_l(target_ulong ac, target_ulong shift,
  2853. CPUMIPSState *env)
  2854. {
  2855. uint64_t temp[3];
  2856. uint32_t temp128;
  2857. target_ulong result;
  2858. shift = shift & 0x3F;
  2859. mipsdsp_rndrashift_acc(temp, ac, shift, env);
  2860. temp[0] += 1;
  2861. if (temp[0] == 0) {
  2862. temp[1] += 1;
  2863. if (temp[1] == 0) {
  2864. temp[2] += 1;
  2865. }
  2866. }
  2867. temp128 = temp[2] & 0x01;
  2868. if ((temp128 != 0 || temp[1] != 0) &&
  2869. (temp128 != 1 || temp[1] != ~0ull)) {
  2870. if (temp128 == 0) {
  2871. temp[1] &= ~0x00ull - 1;
  2872. temp[0] |= ~0x00ull - 1;
  2873. } else {
  2874. temp[1] |= 0x01;
  2875. temp[0] &= 0x01;
  2876. }
  2877. set_DSPControl_overflow_flag(1, 23, env);
  2878. }
  2879. result = (temp[1] << 63) | (temp[0] >> 1);
  2880. return result;
  2881. }
  2882. #endif
  2883. target_ulong helper_extr_s_h(target_ulong ac, target_ulong shift,
  2884. CPUMIPSState *env)
  2885. {
  2886. int64_t temp, acc;
  2887. shift = shift & 0x1F;
  2888. acc = ((int64_t)env->active_tc.HI[ac] << 32) |
  2889. ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
  2890. temp = acc >> shift;
  2891. if (temp > (int64_t)0x7FFF) {
  2892. temp = 0x00007FFF;
  2893. set_DSPControl_overflow_flag(1, 23, env);
  2894. } else if (temp < (int64_t)0xFFFFFFFFFFFF8000ULL) {
  2895. temp = 0xFFFF8000;
  2896. set_DSPControl_overflow_flag(1, 23, env);
  2897. }
  2898. return (target_long)(int32_t)(temp & 0xFFFFFFFF);
  2899. }
  2900. #if defined(TARGET_MIPS64)
  2901. target_ulong helper_dextr_s_h(target_ulong ac, target_ulong shift,
  2902. CPUMIPSState *env)
  2903. {
  2904. int64_t temp[2];
  2905. uint32_t temp127;
  2906. shift = shift & 0x1F;
  2907. mipsdsp_rashift_acc((uint64_t *)temp, ac, shift, env);
  2908. temp127 = (temp[1] >> 63) & 0x01;
  2909. if ((temp127 == 0) && (temp[1] > 0 || temp[0] > 32767)) {
  2910. temp[0] &= 0xFFFF0000;
  2911. temp[0] |= 0x00007FFF;
  2912. set_DSPControl_overflow_flag(1, 23, env);
  2913. } else if ((temp127 == 1) &&
  2914. (temp[1] < 0xFFFFFFFFFFFFFFFFll
  2915. || temp[0] < 0xFFFFFFFFFFFF1000ll)) {
  2916. temp[0] &= 0xFFFF0000;
  2917. temp[0] |= 0x00008000;
  2918. set_DSPControl_overflow_flag(1, 23, env);
  2919. }
  2920. return (int64_t)(int16_t)(temp[0] & MIPSDSP_LO);
  2921. }
  2922. #endif
  2923. target_ulong helper_extp(target_ulong ac, target_ulong size, CPUMIPSState *env)
  2924. {
  2925. int32_t start_pos;
  2926. int sub;
  2927. uint32_t temp;
  2928. uint64_t acc;
  2929. size = size & 0x1F;
  2930. temp = 0;
  2931. start_pos = get_DSPControl_pos(env);
  2932. sub = start_pos - (size + 1);
  2933. if (sub >= -1) {
  2934. acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
  2935. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
  2936. temp = (acc >> (start_pos - size)) &
  2937. (((uint32_t)0x01 << (size + 1)) - 1);
  2938. set_DSPControl_efi(0, env);
  2939. } else {
  2940. set_DSPControl_efi(1, env);
  2941. }
  2942. return (target_ulong)temp;
  2943. }
  2944. target_ulong helper_extpdp(target_ulong ac, target_ulong size,
  2945. CPUMIPSState *env)
  2946. {
  2947. int32_t start_pos;
  2948. int sub;
  2949. uint32_t temp;
  2950. uint64_t acc;
  2951. size = size & 0x1F;
  2952. temp = 0;
  2953. start_pos = get_DSPControl_pos(env);
  2954. sub = start_pos - (size + 1);
  2955. if (sub >= -1) {
  2956. acc = ((uint64_t)env->active_tc.HI[ac] << 32) |
  2957. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
  2958. temp = (acc >> (start_pos - size)) &
  2959. (((uint32_t)0x01 << (size + 1)) - 1);
  2960. set_DSPControl_pos(start_pos - (size + 1), env);
  2961. set_DSPControl_efi(0, env);
  2962. } else {
  2963. set_DSPControl_efi(1, env);
  2964. }
  2965. return (target_ulong)temp;
  2966. }
  2967. #if defined(TARGET_MIPS64)
  2968. target_ulong helper_dextp(target_ulong ac, target_ulong size, CPUMIPSState *env)
  2969. {
  2970. int start_pos;
  2971. int len;
  2972. int sub;
  2973. uint64_t tempB, tempA;
  2974. uint64_t temp;
  2975. temp = 0;
  2976. size = size & 0x3F;
  2977. start_pos = get_DSPControl_pos(env);
  2978. len = start_pos - size;
  2979. tempB = env->active_tc.HI[ac];
  2980. tempA = env->active_tc.LO[ac];
  2981. sub = start_pos - (size + 1);
  2982. if (sub >= -1) {
  2983. temp = (tempB << (64 - len)) | (tempA >> len);
  2984. temp = temp & ((0x01 << (size + 1)) - 1);
  2985. set_DSPControl_efi(0, env);
  2986. } else {
  2987. set_DSPControl_efi(1, env);
  2988. }
  2989. return temp;
  2990. }
  2991. target_ulong helper_dextpdp(target_ulong ac, target_ulong size,
  2992. CPUMIPSState *env)
  2993. {
  2994. int start_pos;
  2995. int len;
  2996. int sub;
  2997. uint64_t tempB, tempA;
  2998. uint64_t temp;
  2999. temp = 0;
  3000. size = size & 0x3F;
  3001. start_pos = get_DSPControl_pos(env);
  3002. len = start_pos - size;
  3003. tempB = env->active_tc.HI[ac];
  3004. tempA = env->active_tc.LO[ac];
  3005. sub = start_pos - (size + 1);
  3006. if (sub >= -1) {
  3007. temp = (tempB << (64 - len)) | (tempA >> len);
  3008. temp = temp & ((0x01 << (size + 1)) - 1);
  3009. set_DSPControl_pos(sub, env);
  3010. set_DSPControl_efi(0, env);
  3011. } else {
  3012. set_DSPControl_efi(1, env);
  3013. }
  3014. return temp;
  3015. }
  3016. #endif
  3017. void helper_shilo(target_ulong ac, target_ulong rs, CPUMIPSState *env)
  3018. {
  3019. int8_t rs5_0;
  3020. uint64_t temp, acc;
  3021. rs5_0 = rs & 0x3F;
  3022. rs5_0 = (int8_t)(rs5_0 << 2) >> 2;
  3023. if (unlikely(rs5_0 == 0)) {
  3024. return;
  3025. }
  3026. acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) |
  3027. ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
  3028. if (rs5_0 > 0) {
  3029. temp = acc >> rs5_0;
  3030. } else {
  3031. temp = acc << -rs5_0;
  3032. }
  3033. env->active_tc.HI[ac] = (target_ulong)(int32_t)((temp & MIPSDSP_LHI) >> 32);
  3034. env->active_tc.LO[ac] = (target_ulong)(int32_t)(temp & MIPSDSP_LLO);
  3035. }
  3036. #if defined(TARGET_MIPS64)
  3037. void helper_dshilo(target_ulong shift, target_ulong ac, CPUMIPSState *env)
  3038. {
  3039. int8_t shift_t;
  3040. uint64_t tempB, tempA;
  3041. shift_t = (int8_t)(shift << 1) >> 1;
  3042. tempB = env->active_tc.HI[ac];
  3043. tempA = env->active_tc.LO[ac];
  3044. if (shift_t != 0) {
  3045. if (shift_t >= 0) {
  3046. tempA = (tempB << (64 - shift_t)) | (tempA >> shift_t);
  3047. tempB = tempB >> shift_t;
  3048. } else {
  3049. shift_t = -shift_t;
  3050. tempB = (tempB << shift_t) | (tempA >> (64 - shift_t));
  3051. tempA = tempA << shift_t;
  3052. }
  3053. }
  3054. env->active_tc.HI[ac] = tempB;
  3055. env->active_tc.LO[ac] = tempA;
  3056. }
  3057. #endif
  3058. void helper_mthlip(target_ulong ac, target_ulong rs, CPUMIPSState *env)
  3059. {
  3060. int32_t tempA, tempB, pos;
  3061. tempA = rs;
  3062. tempB = env->active_tc.LO[ac];
  3063. env->active_tc.HI[ac] = (target_long)tempB;
  3064. env->active_tc.LO[ac] = (target_long)tempA;
  3065. pos = get_DSPControl_pos(env);
  3066. if (pos > 32) {
  3067. return;
  3068. } else {
  3069. set_DSPControl_pos(pos + 32, env);
  3070. }
  3071. }
  3072. #if defined(TARGET_MIPS64)
  3073. void helper_dmthlip(target_ulong rs, target_ulong ac, CPUMIPSState *env)
  3074. {
  3075. uint8_t ac_t;
  3076. uint8_t pos;
  3077. uint64_t tempB, tempA;
  3078. ac_t = ac & 0x3;
  3079. tempA = rs;
  3080. tempB = env->active_tc.LO[ac_t];
  3081. env->active_tc.HI[ac_t] = tempB;
  3082. env->active_tc.LO[ac_t] = tempA;
  3083. pos = get_DSPControl_pos(env);
  3084. if (pos <= 64) {
  3085. pos = pos + 64;
  3086. set_DSPControl_pos(pos, env);
  3087. }
  3088. }
  3089. #endif
  3090. void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
  3091. {
  3092. uint8_t mask[6];
  3093. uint8_t i;
  3094. uint32_t newbits, overwrite;
  3095. target_ulong dsp;
  3096. newbits = 0x00;
  3097. overwrite = 0xFFFFFFFF;
  3098. dsp = env->active_tc.DSPControl;
  3099. for (i = 0; i < 6; i++) {
  3100. mask[i] = (mask_num >> i) & 0x01;
  3101. }
  3102. if (mask[0] == 1) {
  3103. #if defined(TARGET_MIPS64)
  3104. overwrite &= 0xFFFFFF80;
  3105. newbits &= 0xFFFFFF80;
  3106. newbits |= 0x0000007F & rs;
  3107. #else
  3108. overwrite &= 0xFFFFFFC0;
  3109. newbits &= 0xFFFFFFC0;
  3110. newbits |= 0x0000003F & rs;
  3111. #endif
  3112. }
  3113. if (mask[1] == 1) {
  3114. overwrite &= 0xFFFFE07F;
  3115. newbits &= 0xFFFFE07F;
  3116. newbits |= 0x00001F80 & rs;
  3117. }
  3118. if (mask[2] == 1) {
  3119. overwrite &= 0xFFFFDFFF;
  3120. newbits &= 0xFFFFDFFF;
  3121. newbits |= 0x00002000 & rs;
  3122. }
  3123. if (mask[3] == 1) {
  3124. overwrite &= 0xFF00FFFF;
  3125. newbits &= 0xFF00FFFF;
  3126. newbits |= 0x00FF0000 & rs;
  3127. }
  3128. if (mask[4] == 1) {
  3129. overwrite &= 0x00FFFFFF;
  3130. newbits &= 0x00FFFFFF;
  3131. #if defined(TARGET_MIPS64)
  3132. newbits |= 0xFF000000 & rs;
  3133. #else
  3134. newbits |= 0x0F000000 & rs;
  3135. #endif
  3136. }
  3137. if (mask[5] == 1) {
  3138. overwrite &= 0xFFFFBFFF;
  3139. newbits &= 0xFFFFBFFF;
  3140. newbits |= 0x00004000 & rs;
  3141. }
  3142. dsp = dsp & overwrite;
  3143. dsp = dsp | newbits;
  3144. env->active_tc.DSPControl = dsp;
  3145. }
  3146. target_ulong helper_rddsp(target_ulong masknum, CPUMIPSState *env)
  3147. {
  3148. uint8_t mask[6];
  3149. uint32_t ruler, i;
  3150. target_ulong temp;
  3151. target_ulong dsp;
  3152. ruler = 0x01;
  3153. for (i = 0; i < 6; i++) {
  3154. mask[i] = (masknum & ruler) >> i ;
  3155. ruler = ruler << 1;
  3156. }
  3157. temp = 0x00;
  3158. dsp = env->active_tc.DSPControl;
  3159. if (mask[0] == 1) {
  3160. #if defined(TARGET_MIPS64)
  3161. temp |= dsp & 0x7F;
  3162. #else
  3163. temp |= dsp & 0x3F;
  3164. #endif
  3165. }
  3166. if (mask[1] == 1) {
  3167. temp |= dsp & 0x1F80;
  3168. }
  3169. if (mask[2] == 1) {
  3170. temp |= dsp & 0x2000;
  3171. }
  3172. if (mask[3] == 1) {
  3173. temp |= dsp & 0x00FF0000;
  3174. }
  3175. if (mask[4] == 1) {
  3176. #if defined(TARGET_MIPS64)
  3177. temp |= dsp & 0xFF000000;
  3178. #else
  3179. temp |= dsp & 0x0F000000;
  3180. #endif
  3181. }
  3182. if (mask[5] == 1) {
  3183. temp |= dsp & 0x4000;
  3184. }
  3185. return temp;
  3186. }
  3187. #undef MIPSDSP_LHI
  3188. #undef MIPSDSP_LLO
  3189. #undef MIPSDSP_HI
  3190. #undef MIPSDSP_LO
  3191. #undef MIPSDSP_Q3
  3192. #undef MIPSDSP_Q2
  3193. #undef MIPSDSP_Q1
  3194. #undef MIPSDSP_Q0
  3195. #undef MIPSDSP_SPLIT32_8
  3196. #undef MIPSDSP_SPLIT32_16
  3197. #undef MIPSDSP_RETURN32_8
  3198. #undef MIPSDSP_RETURN32_16
  3199. #ifdef TARGET_MIPS64
  3200. #undef MIPSDSP_SPLIT64_16
  3201. #undef MIPSDSP_SPLIT64_32
  3202. #undef MIPSDSP_RETURN64_16
  3203. #undef MIPSDSP_RETURN64_32
  3204. #endif