op_helper.c 88 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161
  1. #include "exec.h"
  2. #include "host-utils.h"
  3. #include "helper.h"
  4. #if !defined(CONFIG_USER_ONLY)
  5. #include "softmmu_exec.h"
  6. #endif /* !defined(CONFIG_USER_ONLY) */
  7. //#define DEBUG_MMU
  8. //#define DEBUG_MXCC
  9. //#define DEBUG_UNALIGNED
  10. //#define DEBUG_UNASSIGNED
  11. //#define DEBUG_ASI
  12. //#define DEBUG_PCALL
  13. #ifdef DEBUG_MMU
  14. #define DPRINTF_MMU(fmt, args...) \
  15. do { printf("MMU: " fmt , ##args); } while (0)
  16. #else
  17. #define DPRINTF_MMU(fmt, args...) do {} while (0)
  18. #endif
  19. #ifdef DEBUG_MXCC
  20. #define DPRINTF_MXCC(fmt, args...) \
  21. do { printf("MXCC: " fmt , ##args); } while (0)
  22. #else
  23. #define DPRINTF_MXCC(fmt, args...) do {} while (0)
  24. #endif
  25. #ifdef DEBUG_ASI
  26. #define DPRINTF_ASI(fmt, args...) \
  27. do { printf("ASI: " fmt , ##args); } while (0)
  28. #else
  29. #define DPRINTF_ASI(fmt, args...) do {} while (0)
  30. #endif
  31. #ifdef TARGET_SPARC64
  32. #ifndef TARGET_ABI32
  33. #define AM_CHECK(env1) ((env1)->pstate & PS_AM)
  34. #else
  35. #define AM_CHECK(env1) (1)
  36. #endif
  37. #endif
  38. static inline void address_mask(CPUState *env1, target_ulong *addr)
  39. {
  40. #ifdef TARGET_SPARC64
  41. if (AM_CHECK(env1))
  42. *addr &= 0xffffffffULL;
  43. #endif
  44. }
  45. static void raise_exception(int tt)
  46. {
  47. env->exception_index = tt;
  48. cpu_loop_exit();
  49. }
  50. void HELPER(raise_exception)(int tt)
  51. {
  52. raise_exception(tt);
  53. }
  54. static inline void set_cwp(int new_cwp)
  55. {
  56. cpu_set_cwp(env, new_cwp);
  57. }
  58. void helper_check_align(target_ulong addr, uint32_t align)
  59. {
  60. if (addr & align) {
  61. #ifdef DEBUG_UNALIGNED
  62. printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
  63. "\n", addr, env->pc);
  64. #endif
  65. raise_exception(TT_UNALIGNED);
  66. }
  67. }
  68. #define F_HELPER(name, p) void helper_f##name##p(void)
  69. #define F_BINOP(name) \
  70. float32 helper_f ## name ## s (float32 src1, float32 src2) \
  71. { \
  72. return float32_ ## name (src1, src2, &env->fp_status); \
  73. } \
  74. F_HELPER(name, d) \
  75. { \
  76. DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
  77. } \
  78. F_HELPER(name, q) \
  79. { \
  80. QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
  81. }
  82. F_BINOP(add);
  83. F_BINOP(sub);
  84. F_BINOP(mul);
  85. F_BINOP(div);
  86. #undef F_BINOP
  87. void helper_fsmuld(float32 src1, float32 src2)
  88. {
  89. DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
  90. float32_to_float64(src2, &env->fp_status),
  91. &env->fp_status);
  92. }
  93. void helper_fdmulq(void)
  94. {
  95. QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
  96. float64_to_float128(DT1, &env->fp_status),
  97. &env->fp_status);
  98. }
  99. float32 helper_fnegs(float32 src)
  100. {
  101. return float32_chs(src);
  102. }
  103. #ifdef TARGET_SPARC64
  104. F_HELPER(neg, d)
  105. {
  106. DT0 = float64_chs(DT1);
  107. }
  108. F_HELPER(neg, q)
  109. {
  110. QT0 = float128_chs(QT1);
  111. }
  112. #endif
  113. /* Integer to float conversion. */
  114. float32 helper_fitos(int32_t src)
  115. {
  116. return int32_to_float32(src, &env->fp_status);
  117. }
  118. void helper_fitod(int32_t src)
  119. {
  120. DT0 = int32_to_float64(src, &env->fp_status);
  121. }
  122. void helper_fitoq(int32_t src)
  123. {
  124. QT0 = int32_to_float128(src, &env->fp_status);
  125. }
  126. #ifdef TARGET_SPARC64
  127. float32 helper_fxtos(void)
  128. {
  129. return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
  130. }
  131. F_HELPER(xto, d)
  132. {
  133. DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
  134. }
  135. F_HELPER(xto, q)
  136. {
  137. QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
  138. }
  139. #endif
  140. #undef F_HELPER
  141. /* floating point conversion */
  142. float32 helper_fdtos(void)
  143. {
  144. return float64_to_float32(DT1, &env->fp_status);
  145. }
  146. void helper_fstod(float32 src)
  147. {
  148. DT0 = float32_to_float64(src, &env->fp_status);
  149. }
  150. float32 helper_fqtos(void)
  151. {
  152. return float128_to_float32(QT1, &env->fp_status);
  153. }
  154. void helper_fstoq(float32 src)
  155. {
  156. QT0 = float32_to_float128(src, &env->fp_status);
  157. }
  158. void helper_fqtod(void)
  159. {
  160. DT0 = float128_to_float64(QT1, &env->fp_status);
  161. }
  162. void helper_fdtoq(void)
  163. {
  164. QT0 = float64_to_float128(DT1, &env->fp_status);
  165. }
  166. /* Float to integer conversion. */
  167. int32_t helper_fstoi(float32 src)
  168. {
  169. return float32_to_int32_round_to_zero(src, &env->fp_status);
  170. }
  171. int32_t helper_fdtoi(void)
  172. {
  173. return float64_to_int32_round_to_zero(DT1, &env->fp_status);
  174. }
  175. int32_t helper_fqtoi(void)
  176. {
  177. return float128_to_int32_round_to_zero(QT1, &env->fp_status);
  178. }
  179. #ifdef TARGET_SPARC64
  180. void helper_fstox(float32 src)
  181. {
  182. *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
  183. }
  184. void helper_fdtox(void)
  185. {
  186. *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
  187. }
  188. void helper_fqtox(void)
  189. {
  190. *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
  191. }
  192. void helper_faligndata(void)
  193. {
  194. uint64_t tmp;
  195. tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
  196. /* on many architectures a shift of 64 does nothing */
  197. if ((env->gsr & 7) != 0) {
  198. tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
  199. }
  200. *((uint64_t *)&DT0) = tmp;
  201. }
  202. #ifdef WORDS_BIGENDIAN
  203. #define VIS_B64(n) b[7 - (n)]
  204. #define VIS_W64(n) w[3 - (n)]
  205. #define VIS_SW64(n) sw[3 - (n)]
  206. #define VIS_L64(n) l[1 - (n)]
  207. #define VIS_B32(n) b[3 - (n)]
  208. #define VIS_W32(n) w[1 - (n)]
  209. #else
  210. #define VIS_B64(n) b[n]
  211. #define VIS_W64(n) w[n]
  212. #define VIS_SW64(n) sw[n]
  213. #define VIS_L64(n) l[n]
  214. #define VIS_B32(n) b[n]
  215. #define VIS_W32(n) w[n]
  216. #endif
  217. typedef union {
  218. uint8_t b[8];
  219. uint16_t w[4];
  220. int16_t sw[4];
  221. uint32_t l[2];
  222. float64 d;
  223. } vis64;
  224. typedef union {
  225. uint8_t b[4];
  226. uint16_t w[2];
  227. uint32_t l;
  228. float32 f;
  229. } vis32;
  230. void helper_fpmerge(void)
  231. {
  232. vis64 s, d;
  233. s.d = DT0;
  234. d.d = DT1;
  235. // Reverse calculation order to handle overlap
  236. d.VIS_B64(7) = s.VIS_B64(3);
  237. d.VIS_B64(6) = d.VIS_B64(3);
  238. d.VIS_B64(5) = s.VIS_B64(2);
  239. d.VIS_B64(4) = d.VIS_B64(2);
  240. d.VIS_B64(3) = s.VIS_B64(1);
  241. d.VIS_B64(2) = d.VIS_B64(1);
  242. d.VIS_B64(1) = s.VIS_B64(0);
  243. //d.VIS_B64(0) = d.VIS_B64(0);
  244. DT0 = d.d;
  245. }
  246. void helper_fmul8x16(void)
  247. {
  248. vis64 s, d;
  249. uint32_t tmp;
  250. s.d = DT0;
  251. d.d = DT1;
  252. #define PMUL(r) \
  253. tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
  254. if ((tmp & 0xff) > 0x7f) \
  255. tmp += 0x100; \
  256. d.VIS_W64(r) = tmp >> 8;
  257. PMUL(0);
  258. PMUL(1);
  259. PMUL(2);
  260. PMUL(3);
  261. #undef PMUL
  262. DT0 = d.d;
  263. }
  264. void helper_fmul8x16al(void)
  265. {
  266. vis64 s, d;
  267. uint32_t tmp;
  268. s.d = DT0;
  269. d.d = DT1;
  270. #define PMUL(r) \
  271. tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
  272. if ((tmp & 0xff) > 0x7f) \
  273. tmp += 0x100; \
  274. d.VIS_W64(r) = tmp >> 8;
  275. PMUL(0);
  276. PMUL(1);
  277. PMUL(2);
  278. PMUL(3);
  279. #undef PMUL
  280. DT0 = d.d;
  281. }
  282. void helper_fmul8x16au(void)
  283. {
  284. vis64 s, d;
  285. uint32_t tmp;
  286. s.d = DT0;
  287. d.d = DT1;
  288. #define PMUL(r) \
  289. tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
  290. if ((tmp & 0xff) > 0x7f) \
  291. tmp += 0x100; \
  292. d.VIS_W64(r) = tmp >> 8;
  293. PMUL(0);
  294. PMUL(1);
  295. PMUL(2);
  296. PMUL(3);
  297. #undef PMUL
  298. DT0 = d.d;
  299. }
  300. void helper_fmul8sux16(void)
  301. {
  302. vis64 s, d;
  303. uint32_t tmp;
  304. s.d = DT0;
  305. d.d = DT1;
  306. #define PMUL(r) \
  307. tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
  308. if ((tmp & 0xff) > 0x7f) \
  309. tmp += 0x100; \
  310. d.VIS_W64(r) = tmp >> 8;
  311. PMUL(0);
  312. PMUL(1);
  313. PMUL(2);
  314. PMUL(3);
  315. #undef PMUL
  316. DT0 = d.d;
  317. }
  318. void helper_fmul8ulx16(void)
  319. {
  320. vis64 s, d;
  321. uint32_t tmp;
  322. s.d = DT0;
  323. d.d = DT1;
  324. #define PMUL(r) \
  325. tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
  326. if ((tmp & 0xff) > 0x7f) \
  327. tmp += 0x100; \
  328. d.VIS_W64(r) = tmp >> 8;
  329. PMUL(0);
  330. PMUL(1);
  331. PMUL(2);
  332. PMUL(3);
  333. #undef PMUL
  334. DT0 = d.d;
  335. }
  336. void helper_fmuld8sux16(void)
  337. {
  338. vis64 s, d;
  339. uint32_t tmp;
  340. s.d = DT0;
  341. d.d = DT1;
  342. #define PMUL(r) \
  343. tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
  344. if ((tmp & 0xff) > 0x7f) \
  345. tmp += 0x100; \
  346. d.VIS_L64(r) = tmp;
  347. // Reverse calculation order to handle overlap
  348. PMUL(1);
  349. PMUL(0);
  350. #undef PMUL
  351. DT0 = d.d;
  352. }
  353. void helper_fmuld8ulx16(void)
  354. {
  355. vis64 s, d;
  356. uint32_t tmp;
  357. s.d = DT0;
  358. d.d = DT1;
  359. #define PMUL(r) \
  360. tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
  361. if ((tmp & 0xff) > 0x7f) \
  362. tmp += 0x100; \
  363. d.VIS_L64(r) = tmp;
  364. // Reverse calculation order to handle overlap
  365. PMUL(1);
  366. PMUL(0);
  367. #undef PMUL
  368. DT0 = d.d;
  369. }
  370. void helper_fexpand(void)
  371. {
  372. vis32 s;
  373. vis64 d;
  374. s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
  375. d.d = DT1;
  376. d.VIS_W64(0) = s.VIS_B32(0) << 4;
  377. d.VIS_W64(1) = s.VIS_B32(1) << 4;
  378. d.VIS_W64(2) = s.VIS_B32(2) << 4;
  379. d.VIS_W64(3) = s.VIS_B32(3) << 4;
  380. DT0 = d.d;
  381. }
  382. #define VIS_HELPER(name, F) \
  383. void name##16(void) \
  384. { \
  385. vis64 s, d; \
  386. \
  387. s.d = DT0; \
  388. d.d = DT1; \
  389. \
  390. d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
  391. d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
  392. d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
  393. d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
  394. \
  395. DT0 = d.d; \
  396. } \
  397. \
  398. uint32_t name##16s(uint32_t src1, uint32_t src2) \
  399. { \
  400. vis32 s, d; \
  401. \
  402. s.l = src1; \
  403. d.l = src2; \
  404. \
  405. d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
  406. d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
  407. \
  408. return d.l; \
  409. } \
  410. \
  411. void name##32(void) \
  412. { \
  413. vis64 s, d; \
  414. \
  415. s.d = DT0; \
  416. d.d = DT1; \
  417. \
  418. d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
  419. d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
  420. \
  421. DT0 = d.d; \
  422. } \
  423. \
  424. uint32_t name##32s(uint32_t src1, uint32_t src2) \
  425. { \
  426. vis32 s, d; \
  427. \
  428. s.l = src1; \
  429. d.l = src2; \
  430. \
  431. d.l = F(d.l, s.l); \
  432. \
  433. return d.l; \
  434. }
  435. #define FADD(a, b) ((a) + (b))
  436. #define FSUB(a, b) ((a) - (b))
  437. VIS_HELPER(helper_fpadd, FADD)
  438. VIS_HELPER(helper_fpsub, FSUB)
  439. #define VIS_CMPHELPER(name, F) \
  440. void name##16(void) \
  441. { \
  442. vis64 s, d; \
  443. \
  444. s.d = DT0; \
  445. d.d = DT1; \
  446. \
  447. d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \
  448. d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \
  449. d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \
  450. d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \
  451. \
  452. DT0 = d.d; \
  453. } \
  454. \
  455. void name##32(void) \
  456. { \
  457. vis64 s, d; \
  458. \
  459. s.d = DT0; \
  460. d.d = DT1; \
  461. \
  462. d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \
  463. d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \
  464. \
  465. DT0 = d.d; \
  466. }
  467. #define FCMPGT(a, b) ((a) > (b))
  468. #define FCMPEQ(a, b) ((a) == (b))
  469. #define FCMPLE(a, b) ((a) <= (b))
  470. #define FCMPNE(a, b) ((a) != (b))
  471. VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
  472. VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
  473. VIS_CMPHELPER(helper_fcmple, FCMPLE)
  474. VIS_CMPHELPER(helper_fcmpne, FCMPNE)
  475. #endif
  476. void helper_check_ieee_exceptions(void)
  477. {
  478. target_ulong status;
  479. status = get_float_exception_flags(&env->fp_status);
  480. if (status) {
  481. /* Copy IEEE 754 flags into FSR */
  482. if (status & float_flag_invalid)
  483. env->fsr |= FSR_NVC;
  484. if (status & float_flag_overflow)
  485. env->fsr |= FSR_OFC;
  486. if (status & float_flag_underflow)
  487. env->fsr |= FSR_UFC;
  488. if (status & float_flag_divbyzero)
  489. env->fsr |= FSR_DZC;
  490. if (status & float_flag_inexact)
  491. env->fsr |= FSR_NXC;
  492. if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
  493. /* Unmasked exception, generate a trap */
  494. env->fsr |= FSR_FTT_IEEE_EXCP;
  495. raise_exception(TT_FP_EXCP);
  496. } else {
  497. /* Accumulate exceptions */
  498. env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
  499. }
  500. }
  501. }
  502. void helper_clear_float_exceptions(void)
  503. {
  504. set_float_exception_flags(0, &env->fp_status);
  505. }
  506. float32 helper_fabss(float32 src)
  507. {
  508. return float32_abs(src);
  509. }
  510. #ifdef TARGET_SPARC64
  511. void helper_fabsd(void)
  512. {
  513. DT0 = float64_abs(DT1);
  514. }
  515. void helper_fabsq(void)
  516. {
  517. QT0 = float128_abs(QT1);
  518. }
  519. #endif
  520. float32 helper_fsqrts(float32 src)
  521. {
  522. return float32_sqrt(src, &env->fp_status);
  523. }
  524. void helper_fsqrtd(void)
  525. {
  526. DT0 = float64_sqrt(DT1, &env->fp_status);
  527. }
  528. void helper_fsqrtq(void)
  529. {
  530. QT0 = float128_sqrt(QT1, &env->fp_status);
  531. }
  532. #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
  533. void glue(helper_, name) (void) \
  534. { \
  535. target_ulong new_fsr; \
  536. \
  537. env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
  538. switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
  539. case float_relation_unordered: \
  540. new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
  541. if ((env->fsr & FSR_NVM) || TRAP) { \
  542. env->fsr |= new_fsr; \
  543. env->fsr |= FSR_NVC; \
  544. env->fsr |= FSR_FTT_IEEE_EXCP; \
  545. raise_exception(TT_FP_EXCP); \
  546. } else { \
  547. env->fsr |= FSR_NVA; \
  548. } \
  549. break; \
  550. case float_relation_less: \
  551. new_fsr = FSR_FCC0 << FS; \
  552. break; \
  553. case float_relation_greater: \
  554. new_fsr = FSR_FCC1 << FS; \
  555. break; \
  556. default: \
  557. new_fsr = 0; \
  558. break; \
  559. } \
  560. env->fsr |= new_fsr; \
  561. }
  562. #define GEN_FCMPS(name, size, FS, TRAP) \
  563. void glue(helper_, name)(float32 src1, float32 src2) \
  564. { \
  565. target_ulong new_fsr; \
  566. \
  567. env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
  568. switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
  569. case float_relation_unordered: \
  570. new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
  571. if ((env->fsr & FSR_NVM) || TRAP) { \
  572. env->fsr |= new_fsr; \
  573. env->fsr |= FSR_NVC; \
  574. env->fsr |= FSR_FTT_IEEE_EXCP; \
  575. raise_exception(TT_FP_EXCP); \
  576. } else { \
  577. env->fsr |= FSR_NVA; \
  578. } \
  579. break; \
  580. case float_relation_less: \
  581. new_fsr = FSR_FCC0 << FS; \
  582. break; \
  583. case float_relation_greater: \
  584. new_fsr = FSR_FCC1 << FS; \
  585. break; \
  586. default: \
  587. new_fsr = 0; \
  588. break; \
  589. } \
  590. env->fsr |= new_fsr; \
  591. }
  592. GEN_FCMPS(fcmps, float32, 0, 0);
  593. GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
  594. GEN_FCMPS(fcmpes, float32, 0, 1);
  595. GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
  596. GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
  597. GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
  598. #ifdef TARGET_SPARC64
  599. GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
  600. GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
  601. GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
  602. GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
  603. GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
  604. GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
  605. GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
  606. GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
  607. GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
  608. GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
  609. GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
  610. GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
  611. GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
  612. GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
  613. GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
  614. GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
  615. GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
  616. GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
  617. #endif
  618. #undef GEN_FCMPS
  619. #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
  620. defined(DEBUG_MXCC)
  621. static void dump_mxcc(CPUState *env)
  622. {
  623. printf("mxccdata: %016llx %016llx %016llx %016llx\n",
  624. env->mxccdata[0], env->mxccdata[1],
  625. env->mxccdata[2], env->mxccdata[3]);
  626. printf("mxccregs: %016llx %016llx %016llx %016llx\n"
  627. " %016llx %016llx %016llx %016llx\n",
  628. env->mxccregs[0], env->mxccregs[1],
  629. env->mxccregs[2], env->mxccregs[3],
  630. env->mxccregs[4], env->mxccregs[5],
  631. env->mxccregs[6], env->mxccregs[7]);
  632. }
  633. #endif
  634. #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
  635. && defined(DEBUG_ASI)
  636. static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
  637. uint64_t r1)
  638. {
  639. switch (size)
  640. {
  641. case 1:
  642. DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
  643. addr, asi, r1 & 0xff);
  644. break;
  645. case 2:
  646. DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
  647. addr, asi, r1 & 0xffff);
  648. break;
  649. case 4:
  650. DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
  651. addr, asi, r1 & 0xffffffff);
  652. break;
  653. case 8:
  654. DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
  655. addr, asi, r1);
  656. break;
  657. }
  658. }
  659. #endif
  660. #ifndef TARGET_SPARC64
  661. #ifndef CONFIG_USER_ONLY
  662. uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
  663. {
  664. uint64_t ret = 0;
  665. #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
  666. uint32_t last_addr = addr;
  667. #endif
  668. helper_check_align(addr, size - 1);
  669. switch (asi) {
  670. case 2: /* SuperSparc MXCC registers */
  671. switch (addr) {
  672. case 0x01c00a00: /* MXCC control register */
  673. if (size == 8)
  674. ret = env->mxccregs[3];
  675. else
  676. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  677. size);
  678. break;
  679. case 0x01c00a04: /* MXCC control register */
  680. if (size == 4)
  681. ret = env->mxccregs[3];
  682. else
  683. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  684. size);
  685. break;
  686. case 0x01c00c00: /* Module reset register */
  687. if (size == 8) {
  688. ret = env->mxccregs[5];
  689. // should we do something here?
  690. } else
  691. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  692. size);
  693. break;
  694. case 0x01c00f00: /* MBus port address register */
  695. if (size == 8)
  696. ret = env->mxccregs[7];
  697. else
  698. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  699. size);
  700. break;
  701. default:
  702. DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
  703. size);
  704. break;
  705. }
  706. DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
  707. "addr = %08x -> ret = %" PRIx64 ","
  708. "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
  709. #ifdef DEBUG_MXCC
  710. dump_mxcc(env);
  711. #endif
  712. break;
  713. case 3: /* MMU probe */
  714. {
  715. int mmulev;
  716. mmulev = (addr >> 8) & 15;
  717. if (mmulev > 4)
  718. ret = 0;
  719. else
  720. ret = mmu_probe(env, addr, mmulev);
  721. DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
  722. addr, mmulev, ret);
  723. }
  724. break;
  725. case 4: /* read MMU regs */
  726. {
  727. int reg = (addr >> 8) & 0x1f;
  728. ret = env->mmuregs[reg];
  729. if (reg == 3) /* Fault status cleared on read */
  730. env->mmuregs[3] = 0;
  731. else if (reg == 0x13) /* Fault status read */
  732. ret = env->mmuregs[3];
  733. else if (reg == 0x14) /* Fault address read */
  734. ret = env->mmuregs[4];
  735. DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
  736. }
  737. break;
  738. case 5: // Turbosparc ITLB Diagnostic
  739. case 6: // Turbosparc DTLB Diagnostic
  740. case 7: // Turbosparc IOTLB Diagnostic
  741. break;
  742. case 9: /* Supervisor code access */
  743. switch(size) {
  744. case 1:
  745. ret = ldub_code(addr);
  746. break;
  747. case 2:
  748. ret = lduw_code(addr);
  749. break;
  750. default:
  751. case 4:
  752. ret = ldl_code(addr);
  753. break;
  754. case 8:
  755. ret = ldq_code(addr);
  756. break;
  757. }
  758. break;
  759. case 0xa: /* User data access */
  760. switch(size) {
  761. case 1:
  762. ret = ldub_user(addr);
  763. break;
  764. case 2:
  765. ret = lduw_user(addr);
  766. break;
  767. default:
  768. case 4:
  769. ret = ldl_user(addr);
  770. break;
  771. case 8:
  772. ret = ldq_user(addr);
  773. break;
  774. }
  775. break;
  776. case 0xb: /* Supervisor data access */
  777. switch(size) {
  778. case 1:
  779. ret = ldub_kernel(addr);
  780. break;
  781. case 2:
  782. ret = lduw_kernel(addr);
  783. break;
  784. default:
  785. case 4:
  786. ret = ldl_kernel(addr);
  787. break;
  788. case 8:
  789. ret = ldq_kernel(addr);
  790. break;
  791. }
  792. break;
  793. case 0xc: /* I-cache tag */
  794. case 0xd: /* I-cache data */
  795. case 0xe: /* D-cache tag */
  796. case 0xf: /* D-cache data */
  797. break;
  798. case 0x20: /* MMU passthrough */
  799. switch(size) {
  800. case 1:
  801. ret = ldub_phys(addr);
  802. break;
  803. case 2:
  804. ret = lduw_phys(addr);
  805. break;
  806. default:
  807. case 4:
  808. ret = ldl_phys(addr);
  809. break;
  810. case 8:
  811. ret = ldq_phys(addr);
  812. break;
  813. }
  814. break;
  815. case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
  816. switch(size) {
  817. case 1:
  818. ret = ldub_phys((target_phys_addr_t)addr
  819. | ((target_phys_addr_t)(asi & 0xf) << 32));
  820. break;
  821. case 2:
  822. ret = lduw_phys((target_phys_addr_t)addr
  823. | ((target_phys_addr_t)(asi & 0xf) << 32));
  824. break;
  825. default:
  826. case 4:
  827. ret = ldl_phys((target_phys_addr_t)addr
  828. | ((target_phys_addr_t)(asi & 0xf) << 32));
  829. break;
  830. case 8:
  831. ret = ldq_phys((target_phys_addr_t)addr
  832. | ((target_phys_addr_t)(asi & 0xf) << 32));
  833. break;
  834. }
  835. break;
  836. case 0x30: // Turbosparc secondary cache diagnostic
  837. case 0x31: // Turbosparc RAM snoop
  838. case 0x32: // Turbosparc page table descriptor diagnostic
  839. case 0x39: /* data cache diagnostic register */
  840. ret = 0;
  841. break;
  842. case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
  843. {
  844. int reg = (addr >> 8) & 3;
  845. switch(reg) {
  846. case 0: /* Breakpoint Value (Addr) */
  847. ret = env->mmubpregs[reg];
  848. break;
  849. case 1: /* Breakpoint Mask */
  850. ret = env->mmubpregs[reg];
  851. break;
  852. case 2: /* Breakpoint Control */
  853. ret = env->mmubpregs[reg];
  854. break;
  855. case 3: /* Breakpoint Status */
  856. ret = env->mmubpregs[reg];
  857. env->mmubpregs[reg] = 0ULL;
  858. break;
  859. }
  860. DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret);
  861. }
  862. break;
  863. case 8: /* User code access, XXX */
  864. default:
  865. do_unassigned_access(addr, 0, 0, asi, size);
  866. ret = 0;
  867. break;
  868. }
  869. if (sign) {
  870. switch(size) {
  871. case 1:
  872. ret = (int8_t) ret;
  873. break;
  874. case 2:
  875. ret = (int16_t) ret;
  876. break;
  877. case 4:
  878. ret = (int32_t) ret;
  879. break;
  880. default:
  881. break;
  882. }
  883. }
  884. #ifdef DEBUG_ASI
  885. dump_asi("read ", last_addr, asi, size, ret);
  886. #endif
  887. return ret;
  888. }
  889. void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
  890. {
  891. helper_check_align(addr, size - 1);
  892. switch(asi) {
  893. case 2: /* SuperSparc MXCC registers */
  894. switch (addr) {
  895. case 0x01c00000: /* MXCC stream data register 0 */
  896. if (size == 8)
  897. env->mxccdata[0] = val;
  898. else
  899. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  900. size);
  901. break;
  902. case 0x01c00008: /* MXCC stream data register 1 */
  903. if (size == 8)
  904. env->mxccdata[1] = val;
  905. else
  906. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  907. size);
  908. break;
  909. case 0x01c00010: /* MXCC stream data register 2 */
  910. if (size == 8)
  911. env->mxccdata[2] = val;
  912. else
  913. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  914. size);
  915. break;
  916. case 0x01c00018: /* MXCC stream data register 3 */
  917. if (size == 8)
  918. env->mxccdata[3] = val;
  919. else
  920. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  921. size);
  922. break;
  923. case 0x01c00100: /* MXCC stream source */
  924. if (size == 8)
  925. env->mxccregs[0] = val;
  926. else
  927. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  928. size);
  929. env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
  930. 0);
  931. env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
  932. 8);
  933. env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
  934. 16);
  935. env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
  936. 24);
  937. break;
  938. case 0x01c00200: /* MXCC stream destination */
  939. if (size == 8)
  940. env->mxccregs[1] = val;
  941. else
  942. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  943. size);
  944. stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0,
  945. env->mxccdata[0]);
  946. stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8,
  947. env->mxccdata[1]);
  948. stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
  949. env->mxccdata[2]);
  950. stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
  951. env->mxccdata[3]);
  952. break;
  953. case 0x01c00a00: /* MXCC control register */
  954. if (size == 8)
  955. env->mxccregs[3] = val;
  956. else
  957. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  958. size);
  959. break;
  960. case 0x01c00a04: /* MXCC control register */
  961. if (size == 4)
  962. env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
  963. | val;
  964. else
  965. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  966. size);
  967. break;
  968. case 0x01c00e00: /* MXCC error register */
  969. // writing a 1 bit clears the error
  970. if (size == 8)
  971. env->mxccregs[6] &= ~val;
  972. else
  973. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  974. size);
  975. break;
  976. case 0x01c00f00: /* MBus port address register */
  977. if (size == 8)
  978. env->mxccregs[7] = val;
  979. else
  980. DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
  981. size);
  982. break;
  983. default:
  984. DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
  985. size);
  986. break;
  987. }
  988. DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
  989. asi, size, addr, val);
  990. #ifdef DEBUG_MXCC
  991. dump_mxcc(env);
  992. #endif
  993. break;
  994. case 3: /* MMU flush */
  995. {
  996. int mmulev;
  997. mmulev = (addr >> 8) & 15;
  998. DPRINTF_MMU("mmu flush level %d\n", mmulev);
  999. switch (mmulev) {
  1000. case 0: // flush page
  1001. tlb_flush_page(env, addr & 0xfffff000);
  1002. break;
  1003. case 1: // flush segment (256k)
  1004. case 2: // flush region (16M)
  1005. case 3: // flush context (4G)
  1006. case 4: // flush entire
  1007. tlb_flush(env, 1);
  1008. break;
  1009. default:
  1010. break;
  1011. }
  1012. #ifdef DEBUG_MMU
  1013. dump_mmu(env);
  1014. #endif
  1015. }
  1016. break;
  1017. case 4: /* write MMU regs */
  1018. {
  1019. int reg = (addr >> 8) & 0x1f;
  1020. uint32_t oldreg;
  1021. oldreg = env->mmuregs[reg];
  1022. switch(reg) {
  1023. case 0: // Control Register
  1024. env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
  1025. (val & 0x00ffffff);
  1026. // Mappings generated during no-fault mode or MMU
  1027. // disabled mode are invalid in normal mode
  1028. if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
  1029. (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
  1030. tlb_flush(env, 1);
  1031. break;
  1032. case 1: // Context Table Pointer Register
  1033. env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
  1034. break;
  1035. case 2: // Context Register
  1036. env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
  1037. if (oldreg != env->mmuregs[reg]) {
  1038. /* we flush when the MMU context changes because
  1039. QEMU has no MMU context support */
  1040. tlb_flush(env, 1);
  1041. }
  1042. break;
  1043. case 3: // Synchronous Fault Status Register with Clear
  1044. case 4: // Synchronous Fault Address Register
  1045. break;
  1046. case 0x10: // TLB Replacement Control Register
  1047. env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
  1048. break;
  1049. case 0x13: // Synchronous Fault Status Register with Read and Clear
  1050. env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
  1051. break;
  1052. case 0x14: // Synchronous Fault Address Register
  1053. env->mmuregs[4] = val;
  1054. break;
  1055. default:
  1056. env->mmuregs[reg] = val;
  1057. break;
  1058. }
  1059. if (oldreg != env->mmuregs[reg]) {
  1060. DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
  1061. reg, oldreg, env->mmuregs[reg]);
  1062. }
  1063. #ifdef DEBUG_MMU
  1064. dump_mmu(env);
  1065. #endif
  1066. }
  1067. break;
  1068. case 5: // Turbosparc ITLB Diagnostic
  1069. case 6: // Turbosparc DTLB Diagnostic
  1070. case 7: // Turbosparc IOTLB Diagnostic
  1071. break;
  1072. case 0xa: /* User data access */
  1073. switch(size) {
  1074. case 1:
  1075. stb_user(addr, val);
  1076. break;
  1077. case 2:
  1078. stw_user(addr, val);
  1079. break;
  1080. default:
  1081. case 4:
  1082. stl_user(addr, val);
  1083. break;
  1084. case 8:
  1085. stq_user(addr, val);
  1086. break;
  1087. }
  1088. break;
  1089. case 0xb: /* Supervisor data access */
  1090. switch(size) {
  1091. case 1:
  1092. stb_kernel(addr, val);
  1093. break;
  1094. case 2:
  1095. stw_kernel(addr, val);
  1096. break;
  1097. default:
  1098. case 4:
  1099. stl_kernel(addr, val);
  1100. break;
  1101. case 8:
  1102. stq_kernel(addr, val);
  1103. break;
  1104. }
  1105. break;
  1106. case 0xc: /* I-cache tag */
  1107. case 0xd: /* I-cache data */
  1108. case 0xe: /* D-cache tag */
  1109. case 0xf: /* D-cache data */
  1110. case 0x10: /* I/D-cache flush page */
  1111. case 0x11: /* I/D-cache flush segment */
  1112. case 0x12: /* I/D-cache flush region */
  1113. case 0x13: /* I/D-cache flush context */
  1114. case 0x14: /* I/D-cache flush user */
  1115. break;
  1116. case 0x17: /* Block copy, sta access */
  1117. {
  1118. // val = src
  1119. // addr = dst
  1120. // copy 32 bytes
  1121. unsigned int i;
  1122. uint32_t src = val & ~3, dst = addr & ~3, temp;
  1123. for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
  1124. temp = ldl_kernel(src);
  1125. stl_kernel(dst, temp);
  1126. }
  1127. }
  1128. break;
  1129. case 0x1f: /* Block fill, stda access */
  1130. {
  1131. // addr = dst
  1132. // fill 32 bytes with val
  1133. unsigned int i;
  1134. uint32_t dst = addr & 7;
  1135. for (i = 0; i < 32; i += 8, dst += 8)
  1136. stq_kernel(dst, val);
  1137. }
  1138. break;
  1139. case 0x20: /* MMU passthrough */
  1140. {
  1141. switch(size) {
  1142. case 1:
  1143. stb_phys(addr, val);
  1144. break;
  1145. case 2:
  1146. stw_phys(addr, val);
  1147. break;
  1148. case 4:
  1149. default:
  1150. stl_phys(addr, val);
  1151. break;
  1152. case 8:
  1153. stq_phys(addr, val);
  1154. break;
  1155. }
  1156. }
  1157. break;
  1158. case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
  1159. {
  1160. switch(size) {
  1161. case 1:
  1162. stb_phys((target_phys_addr_t)addr
  1163. | ((target_phys_addr_t)(asi & 0xf) << 32), val);
  1164. break;
  1165. case 2:
  1166. stw_phys((target_phys_addr_t)addr
  1167. | ((target_phys_addr_t)(asi & 0xf) << 32), val);
  1168. break;
  1169. case 4:
  1170. default:
  1171. stl_phys((target_phys_addr_t)addr
  1172. | ((target_phys_addr_t)(asi & 0xf) << 32), val);
  1173. break;
  1174. case 8:
  1175. stq_phys((target_phys_addr_t)addr
  1176. | ((target_phys_addr_t)(asi & 0xf) << 32), val);
  1177. break;
  1178. }
  1179. }
  1180. break;
  1181. case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
  1182. case 0x31: // store buffer data, Ross RT620 I-cache flush or
  1183. // Turbosparc snoop RAM
  1184. case 0x32: // store buffer control or Turbosparc page table
  1185. // descriptor diagnostic
  1186. case 0x36: /* I-cache flash clear */
  1187. case 0x37: /* D-cache flash clear */
  1188. case 0x4c: /* breakpoint action */
  1189. break;
  1190. case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
  1191. {
  1192. int reg = (addr >> 8) & 3;
  1193. switch(reg) {
  1194. case 0: /* Breakpoint Value (Addr) */
  1195. env->mmubpregs[reg] = (val & 0xfffffffffULL);
  1196. break;
  1197. case 1: /* Breakpoint Mask */
  1198. env->mmubpregs[reg] = (val & 0xfffffffffULL);
  1199. break;
  1200. case 2: /* Breakpoint Control */
  1201. env->mmubpregs[reg] = (val & 0x7fULL);
  1202. break;
  1203. case 3: /* Breakpoint Status */
  1204. env->mmubpregs[reg] = (val & 0xfULL);
  1205. break;
  1206. }
  1207. DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg,
  1208. env->mmuregs[reg]);
  1209. }
  1210. break;
  1211. case 8: /* User code access, XXX */
  1212. case 9: /* Supervisor code access, XXX */
  1213. default:
  1214. do_unassigned_access(addr, 1, 0, asi, size);
  1215. break;
  1216. }
  1217. #ifdef DEBUG_ASI
  1218. dump_asi("write", addr, asi, size, val);
  1219. #endif
  1220. }
  1221. #endif /* CONFIG_USER_ONLY */
  1222. #else /* TARGET_SPARC64 */
  1223. #ifdef CONFIG_USER_ONLY
  1224. uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
  1225. {
  1226. uint64_t ret = 0;
  1227. #if defined(DEBUG_ASI)
  1228. target_ulong last_addr = addr;
  1229. #endif
  1230. if (asi < 0x80)
  1231. raise_exception(TT_PRIV_ACT);
  1232. helper_check_align(addr, size - 1);
  1233. address_mask(env, &addr);
  1234. switch (asi) {
  1235. case 0x82: // Primary no-fault
  1236. case 0x8a: // Primary no-fault LE
  1237. if (page_check_range(addr, size, PAGE_READ) == -1) {
  1238. #ifdef DEBUG_ASI
  1239. dump_asi("read ", last_addr, asi, size, ret);
  1240. #endif
  1241. return 0;
  1242. }
  1243. // Fall through
  1244. case 0x80: // Primary
  1245. case 0x88: // Primary LE
  1246. {
  1247. switch(size) {
  1248. case 1:
  1249. ret = ldub_raw(addr);
  1250. break;
  1251. case 2:
  1252. ret = lduw_raw(addr);
  1253. break;
  1254. case 4:
  1255. ret = ldl_raw(addr);
  1256. break;
  1257. default:
  1258. case 8:
  1259. ret = ldq_raw(addr);
  1260. break;
  1261. }
  1262. }
  1263. break;
  1264. case 0x83: // Secondary no-fault
  1265. case 0x8b: // Secondary no-fault LE
  1266. if (page_check_range(addr, size, PAGE_READ) == -1) {
  1267. #ifdef DEBUG_ASI
  1268. dump_asi("read ", last_addr, asi, size, ret);
  1269. #endif
  1270. return 0;
  1271. }
  1272. // Fall through
  1273. case 0x81: // Secondary
  1274. case 0x89: // Secondary LE
  1275. // XXX
  1276. break;
  1277. default:
  1278. break;
  1279. }
  1280. /* Convert from little endian */
  1281. switch (asi) {
  1282. case 0x88: // Primary LE
  1283. case 0x89: // Secondary LE
  1284. case 0x8a: // Primary no-fault LE
  1285. case 0x8b: // Secondary no-fault LE
  1286. switch(size) {
  1287. case 2:
  1288. ret = bswap16(ret);
  1289. break;
  1290. case 4:
  1291. ret = bswap32(ret);
  1292. break;
  1293. case 8:
  1294. ret = bswap64(ret);
  1295. break;
  1296. default:
  1297. break;
  1298. }
  1299. default:
  1300. break;
  1301. }
  1302. /* Convert to signed number */
  1303. if (sign) {
  1304. switch(size) {
  1305. case 1:
  1306. ret = (int8_t) ret;
  1307. break;
  1308. case 2:
  1309. ret = (int16_t) ret;
  1310. break;
  1311. case 4:
  1312. ret = (int32_t) ret;
  1313. break;
  1314. default:
  1315. break;
  1316. }
  1317. }
  1318. #ifdef DEBUG_ASI
  1319. dump_asi("read ", last_addr, asi, size, ret);
  1320. #endif
  1321. return ret;
  1322. }
  1323. void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
  1324. {
  1325. #ifdef DEBUG_ASI
  1326. dump_asi("write", addr, asi, size, val);
  1327. #endif
  1328. if (asi < 0x80)
  1329. raise_exception(TT_PRIV_ACT);
  1330. helper_check_align(addr, size - 1);
  1331. address_mask(env, &addr);
  1332. /* Convert to little endian */
  1333. switch (asi) {
  1334. case 0x88: // Primary LE
  1335. case 0x89: // Secondary LE
  1336. switch(size) {
  1337. case 2:
  1338. addr = bswap16(addr);
  1339. break;
  1340. case 4:
  1341. addr = bswap32(addr);
  1342. break;
  1343. case 8:
  1344. addr = bswap64(addr);
  1345. break;
  1346. default:
  1347. break;
  1348. }
  1349. default:
  1350. break;
  1351. }
  1352. switch(asi) {
  1353. case 0x80: // Primary
  1354. case 0x88: // Primary LE
  1355. {
  1356. switch(size) {
  1357. case 1:
  1358. stb_raw(addr, val);
  1359. break;
  1360. case 2:
  1361. stw_raw(addr, val);
  1362. break;
  1363. case 4:
  1364. stl_raw(addr, val);
  1365. break;
  1366. case 8:
  1367. default:
  1368. stq_raw(addr, val);
  1369. break;
  1370. }
  1371. }
  1372. break;
  1373. case 0x81: // Secondary
  1374. case 0x89: // Secondary LE
  1375. // XXX
  1376. return;
  1377. case 0x82: // Primary no-fault, RO
  1378. case 0x83: // Secondary no-fault, RO
  1379. case 0x8a: // Primary no-fault LE, RO
  1380. case 0x8b: // Secondary no-fault LE, RO
  1381. default:
  1382. do_unassigned_access(addr, 1, 0, 1, size);
  1383. return;
  1384. }
  1385. }
  1386. #else /* CONFIG_USER_ONLY */
  1387. uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
  1388. {
  1389. uint64_t ret = 0;
  1390. #if defined(DEBUG_ASI)
  1391. target_ulong last_addr = addr;
  1392. #endif
  1393. if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
  1394. || ((env->def->features & CPU_FEATURE_HYPV)
  1395. && asi >= 0x30 && asi < 0x80
  1396. && !(env->hpstate & HS_PRIV)))
  1397. raise_exception(TT_PRIV_ACT);
  1398. helper_check_align(addr, size - 1);
  1399. switch (asi) {
  1400. case 0x82: // Primary no-fault
  1401. case 0x8a: // Primary no-fault LE
  1402. if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
  1403. #ifdef DEBUG_ASI
  1404. dump_asi("read ", last_addr, asi, size, ret);
  1405. #endif
  1406. return 0;
  1407. }
  1408. // Fall through
  1409. case 0x10: // As if user primary
  1410. case 0x18: // As if user primary LE
  1411. case 0x80: // Primary
  1412. case 0x88: // Primary LE
  1413. case 0xe2: // UA2007 Primary block init
  1414. case 0xe3: // UA2007 Secondary block init
  1415. if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
  1416. if ((env->def->features & CPU_FEATURE_HYPV)
  1417. && env->hpstate & HS_PRIV) {
  1418. switch(size) {
  1419. case 1:
  1420. ret = ldub_hypv(addr);
  1421. break;
  1422. case 2:
  1423. ret = lduw_hypv(addr);
  1424. break;
  1425. case 4:
  1426. ret = ldl_hypv(addr);
  1427. break;
  1428. default:
  1429. case 8:
  1430. ret = ldq_hypv(addr);
  1431. break;
  1432. }
  1433. } else {
  1434. switch(size) {
  1435. case 1:
  1436. ret = ldub_kernel(addr);
  1437. break;
  1438. case 2:
  1439. ret = lduw_kernel(addr);
  1440. break;
  1441. case 4:
  1442. ret = ldl_kernel(addr);
  1443. break;
  1444. default:
  1445. case 8:
  1446. ret = ldq_kernel(addr);
  1447. break;
  1448. }
  1449. }
  1450. } else {
  1451. switch(size) {
  1452. case 1:
  1453. ret = ldub_user(addr);
  1454. break;
  1455. case 2:
  1456. ret = lduw_user(addr);
  1457. break;
  1458. case 4:
  1459. ret = ldl_user(addr);
  1460. break;
  1461. default:
  1462. case 8:
  1463. ret = ldq_user(addr);
  1464. break;
  1465. }
  1466. }
  1467. break;
  1468. case 0x14: // Bypass
  1469. case 0x15: // Bypass, non-cacheable
  1470. case 0x1c: // Bypass LE
  1471. case 0x1d: // Bypass, non-cacheable LE
  1472. {
  1473. switch(size) {
  1474. case 1:
  1475. ret = ldub_phys(addr);
  1476. break;
  1477. case 2:
  1478. ret = lduw_phys(addr);
  1479. break;
  1480. case 4:
  1481. ret = ldl_phys(addr);
  1482. break;
  1483. default:
  1484. case 8:
  1485. ret = ldq_phys(addr);
  1486. break;
  1487. }
  1488. break;
  1489. }
  1490. case 0x24: // Nucleus quad LDD 128 bit atomic
  1491. case 0x2c: // Nucleus quad LDD 128 bit atomic LE
  1492. // Only ldda allowed
  1493. raise_exception(TT_ILL_INSN);
  1494. return 0;
  1495. case 0x83: // Secondary no-fault
  1496. case 0x8b: // Secondary no-fault LE
  1497. if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
  1498. #ifdef DEBUG_ASI
  1499. dump_asi("read ", last_addr, asi, size, ret);
  1500. #endif
  1501. return 0;
  1502. }
  1503. // Fall through
  1504. case 0x04: // Nucleus
  1505. case 0x0c: // Nucleus Little Endian (LE)
  1506. case 0x11: // As if user secondary
  1507. case 0x19: // As if user secondary LE
  1508. case 0x4a: // UPA config
  1509. case 0x81: // Secondary
  1510. case 0x89: // Secondary LE
  1511. // XXX
  1512. break;
  1513. case 0x45: // LSU
  1514. ret = env->lsu;
  1515. break;
  1516. case 0x50: // I-MMU regs
  1517. {
  1518. int reg = (addr >> 3) & 0xf;
  1519. ret = env->immuregs[reg];
  1520. break;
  1521. }
  1522. case 0x51: // I-MMU 8k TSB pointer
  1523. case 0x52: // I-MMU 64k TSB pointer
  1524. // XXX
  1525. break;
  1526. case 0x55: // I-MMU data access
  1527. {
  1528. int reg = (addr >> 3) & 0x3f;
  1529. ret = env->itlb_tte[reg];
  1530. break;
  1531. }
  1532. case 0x56: // I-MMU tag read
  1533. {
  1534. int reg = (addr >> 3) & 0x3f;
  1535. ret = env->itlb_tag[reg];
  1536. break;
  1537. }
  1538. case 0x58: // D-MMU regs
  1539. {
  1540. int reg = (addr >> 3) & 0xf;
  1541. ret = env->dmmuregs[reg];
  1542. break;
  1543. }
  1544. case 0x5d: // D-MMU data access
  1545. {
  1546. int reg = (addr >> 3) & 0x3f;
  1547. ret = env->dtlb_tte[reg];
  1548. break;
  1549. }
  1550. case 0x5e: // D-MMU tag read
  1551. {
  1552. int reg = (addr >> 3) & 0x3f;
  1553. ret = env->dtlb_tag[reg];
  1554. break;
  1555. }
  1556. case 0x46: // D-cache data
  1557. case 0x47: // D-cache tag access
  1558. case 0x4b: // E-cache error enable
  1559. case 0x4c: // E-cache asynchronous fault status
  1560. case 0x4d: // E-cache asynchronous fault address
  1561. case 0x4e: // E-cache tag data
  1562. case 0x66: // I-cache instruction access
  1563. case 0x67: // I-cache tag access
  1564. case 0x6e: // I-cache predecode
  1565. case 0x6f: // I-cache LRU etc.
  1566. case 0x76: // E-cache tag
  1567. case 0x7e: // E-cache tag
  1568. break;
  1569. case 0x59: // D-MMU 8k TSB pointer
  1570. case 0x5a: // D-MMU 64k TSB pointer
  1571. case 0x5b: // D-MMU data pointer
  1572. case 0x48: // Interrupt dispatch, RO
  1573. case 0x49: // Interrupt data receive
  1574. case 0x7f: // Incoming interrupt vector, RO
  1575. // XXX
  1576. break;
  1577. case 0x54: // I-MMU data in, WO
  1578. case 0x57: // I-MMU demap, WO
  1579. case 0x5c: // D-MMU data in, WO
  1580. case 0x5f: // D-MMU demap, WO
  1581. case 0x77: // Interrupt vector, WO
  1582. default:
  1583. do_unassigned_access(addr, 0, 0, 1, size);
  1584. ret = 0;
  1585. break;
  1586. }
  1587. /* Convert from little endian */
  1588. switch (asi) {
  1589. case 0x0c: // Nucleus Little Endian (LE)
  1590. case 0x18: // As if user primary LE
  1591. case 0x19: // As if user secondary LE
  1592. case 0x1c: // Bypass LE
  1593. case 0x1d: // Bypass, non-cacheable LE
  1594. case 0x88: // Primary LE
  1595. case 0x89: // Secondary LE
  1596. case 0x8a: // Primary no-fault LE
  1597. case 0x8b: // Secondary no-fault LE
  1598. switch(size) {
  1599. case 2:
  1600. ret = bswap16(ret);
  1601. break;
  1602. case 4:
  1603. ret = bswap32(ret);
  1604. break;
  1605. case 8:
  1606. ret = bswap64(ret);
  1607. break;
  1608. default:
  1609. break;
  1610. }
  1611. default:
  1612. break;
  1613. }
  1614. /* Convert to signed number */
  1615. if (sign) {
  1616. switch(size) {
  1617. case 1:
  1618. ret = (int8_t) ret;
  1619. break;
  1620. case 2:
  1621. ret = (int16_t) ret;
  1622. break;
  1623. case 4:
  1624. ret = (int32_t) ret;
  1625. break;
  1626. default:
  1627. break;
  1628. }
  1629. }
  1630. #ifdef DEBUG_ASI
  1631. dump_asi("read ", last_addr, asi, size, ret);
  1632. #endif
  1633. return ret;
  1634. }
  1635. void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
  1636. {
  1637. #ifdef DEBUG_ASI
  1638. dump_asi("write", addr, asi, size, val);
  1639. #endif
  1640. if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
  1641. || ((env->def->features & CPU_FEATURE_HYPV)
  1642. && asi >= 0x30 && asi < 0x80
  1643. && !(env->hpstate & HS_PRIV)))
  1644. raise_exception(TT_PRIV_ACT);
  1645. helper_check_align(addr, size - 1);
  1646. /* Convert to little endian */
  1647. switch (asi) {
  1648. case 0x0c: // Nucleus Little Endian (LE)
  1649. case 0x18: // As if user primary LE
  1650. case 0x19: // As if user secondary LE
  1651. case 0x1c: // Bypass LE
  1652. case 0x1d: // Bypass, non-cacheable LE
  1653. case 0x88: // Primary LE
  1654. case 0x89: // Secondary LE
  1655. switch(size) {
  1656. case 2:
  1657. addr = bswap16(addr);
  1658. break;
  1659. case 4:
  1660. addr = bswap32(addr);
  1661. break;
  1662. case 8:
  1663. addr = bswap64(addr);
  1664. break;
  1665. default:
  1666. break;
  1667. }
  1668. default:
  1669. break;
  1670. }
  1671. switch(asi) {
  1672. case 0x10: // As if user primary
  1673. case 0x18: // As if user primary LE
  1674. case 0x80: // Primary
  1675. case 0x88: // Primary LE
  1676. case 0xe2: // UA2007 Primary block init
  1677. case 0xe3: // UA2007 Secondary block init
  1678. if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
  1679. if ((env->def->features & CPU_FEATURE_HYPV)
  1680. && env->hpstate & HS_PRIV) {
  1681. switch(size) {
  1682. case 1:
  1683. stb_hypv(addr, val);
  1684. break;
  1685. case 2:
  1686. stw_hypv(addr, val);
  1687. break;
  1688. case 4:
  1689. stl_hypv(addr, val);
  1690. break;
  1691. case 8:
  1692. default:
  1693. stq_hypv(addr, val);
  1694. break;
  1695. }
  1696. } else {
  1697. switch(size) {
  1698. case 1:
  1699. stb_kernel(addr, val);
  1700. break;
  1701. case 2:
  1702. stw_kernel(addr, val);
  1703. break;
  1704. case 4:
  1705. stl_kernel(addr, val);
  1706. break;
  1707. case 8:
  1708. default:
  1709. stq_kernel(addr, val);
  1710. break;
  1711. }
  1712. }
  1713. } else {
  1714. switch(size) {
  1715. case 1:
  1716. stb_user(addr, val);
  1717. break;
  1718. case 2:
  1719. stw_user(addr, val);
  1720. break;
  1721. case 4:
  1722. stl_user(addr, val);
  1723. break;
  1724. case 8:
  1725. default:
  1726. stq_user(addr, val);
  1727. break;
  1728. }
  1729. }
  1730. break;
  1731. case 0x14: // Bypass
  1732. case 0x15: // Bypass, non-cacheable
  1733. case 0x1c: // Bypass LE
  1734. case 0x1d: // Bypass, non-cacheable LE
  1735. {
  1736. switch(size) {
  1737. case 1:
  1738. stb_phys(addr, val);
  1739. break;
  1740. case 2:
  1741. stw_phys(addr, val);
  1742. break;
  1743. case 4:
  1744. stl_phys(addr, val);
  1745. break;
  1746. case 8:
  1747. default:
  1748. stq_phys(addr, val);
  1749. break;
  1750. }
  1751. }
  1752. return;
  1753. case 0x24: // Nucleus quad LDD 128 bit atomic
  1754. case 0x2c: // Nucleus quad LDD 128 bit atomic LE
  1755. // Only ldda allowed
  1756. raise_exception(TT_ILL_INSN);
  1757. return;
  1758. case 0x04: // Nucleus
  1759. case 0x0c: // Nucleus Little Endian (LE)
  1760. case 0x11: // As if user secondary
  1761. case 0x19: // As if user secondary LE
  1762. case 0x4a: // UPA config
  1763. case 0x81: // Secondary
  1764. case 0x89: // Secondary LE
  1765. // XXX
  1766. return;
  1767. case 0x45: // LSU
  1768. {
  1769. uint64_t oldreg;
  1770. oldreg = env->lsu;
  1771. env->lsu = val & (DMMU_E | IMMU_E);
  1772. // Mappings generated during D/I MMU disabled mode are
  1773. // invalid in normal mode
  1774. if (oldreg != env->lsu) {
  1775. DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
  1776. oldreg, env->lsu);
  1777. #ifdef DEBUG_MMU
  1778. dump_mmu(env);
  1779. #endif
  1780. tlb_flush(env, 1);
  1781. }
  1782. return;
  1783. }
  1784. case 0x50: // I-MMU regs
  1785. {
  1786. int reg = (addr >> 3) & 0xf;
  1787. uint64_t oldreg;
  1788. oldreg = env->immuregs[reg];
  1789. switch(reg) {
  1790. case 0: // RO
  1791. case 4:
  1792. return;
  1793. case 1: // Not in I-MMU
  1794. case 2:
  1795. case 7:
  1796. case 8:
  1797. return;
  1798. case 3: // SFSR
  1799. if ((val & 1) == 0)
  1800. val = 0; // Clear SFSR
  1801. break;
  1802. case 5: // TSB access
  1803. case 6: // Tag access
  1804. default:
  1805. break;
  1806. }
  1807. env->immuregs[reg] = val;
  1808. if (oldreg != env->immuregs[reg]) {
  1809. DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
  1810. PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
  1811. }
  1812. #ifdef DEBUG_MMU
  1813. dump_mmu(env);
  1814. #endif
  1815. return;
  1816. }
  1817. case 0x54: // I-MMU data in
  1818. {
  1819. unsigned int i;
  1820. // Try finding an invalid entry
  1821. for (i = 0; i < 64; i++) {
  1822. if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
  1823. env->itlb_tag[i] = env->immuregs[6];
  1824. env->itlb_tte[i] = val;
  1825. return;
  1826. }
  1827. }
  1828. // Try finding an unlocked entry
  1829. for (i = 0; i < 64; i++) {
  1830. if ((env->itlb_tte[i] & 0x40) == 0) {
  1831. env->itlb_tag[i] = env->immuregs[6];
  1832. env->itlb_tte[i] = val;
  1833. return;
  1834. }
  1835. }
  1836. // error state?
  1837. return;
  1838. }
  1839. case 0x55: // I-MMU data access
  1840. {
  1841. // TODO: auto demap
  1842. unsigned int i = (addr >> 3) & 0x3f;
  1843. env->itlb_tag[i] = env->immuregs[6];
  1844. env->itlb_tte[i] = val;
  1845. return;
  1846. }
  1847. case 0x57: // I-MMU demap
  1848. {
  1849. unsigned int i;
  1850. for (i = 0; i < 64; i++) {
  1851. if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
  1852. target_ulong mask = 0xffffffffffffe000ULL;
  1853. mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
  1854. if ((val & mask) == (env->itlb_tag[i] & mask)) {
  1855. env->itlb_tag[i] = 0;
  1856. env->itlb_tte[i] = 0;
  1857. }
  1858. return;
  1859. }
  1860. }
  1861. }
  1862. return;
  1863. case 0x58: // D-MMU regs
  1864. {
  1865. int reg = (addr >> 3) & 0xf;
  1866. uint64_t oldreg;
  1867. oldreg = env->dmmuregs[reg];
  1868. switch(reg) {
  1869. case 0: // RO
  1870. case 4:
  1871. return;
  1872. case 3: // SFSR
  1873. if ((val & 1) == 0) {
  1874. val = 0; // Clear SFSR, Fault address
  1875. env->dmmuregs[4] = 0;
  1876. }
  1877. env->dmmuregs[reg] = val;
  1878. break;
  1879. case 1: // Primary context
  1880. case 2: // Secondary context
  1881. case 5: // TSB access
  1882. case 6: // Tag access
  1883. case 7: // Virtual Watchpoint
  1884. case 8: // Physical Watchpoint
  1885. default:
  1886. break;
  1887. }
  1888. env->dmmuregs[reg] = val;
  1889. if (oldreg != env->dmmuregs[reg]) {
  1890. DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
  1891. PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
  1892. }
  1893. #ifdef DEBUG_MMU
  1894. dump_mmu(env);
  1895. #endif
  1896. return;
  1897. }
  1898. case 0x5c: // D-MMU data in
  1899. {
  1900. unsigned int i;
  1901. // Try finding an invalid entry
  1902. for (i = 0; i < 64; i++) {
  1903. if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
  1904. env->dtlb_tag[i] = env->dmmuregs[6];
  1905. env->dtlb_tte[i] = val;
  1906. return;
  1907. }
  1908. }
  1909. // Try finding an unlocked entry
  1910. for (i = 0; i < 64; i++) {
  1911. if ((env->dtlb_tte[i] & 0x40) == 0) {
  1912. env->dtlb_tag[i] = env->dmmuregs[6];
  1913. env->dtlb_tte[i] = val;
  1914. return;
  1915. }
  1916. }
  1917. // error state?
  1918. return;
  1919. }
  1920. case 0x5d: // D-MMU data access
  1921. {
  1922. unsigned int i = (addr >> 3) & 0x3f;
  1923. env->dtlb_tag[i] = env->dmmuregs[6];
  1924. env->dtlb_tte[i] = val;
  1925. return;
  1926. }
  1927. case 0x5f: // D-MMU demap
  1928. {
  1929. unsigned int i;
  1930. for (i = 0; i < 64; i++) {
  1931. if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
  1932. target_ulong mask = 0xffffffffffffe000ULL;
  1933. mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
  1934. if ((val & mask) == (env->dtlb_tag[i] & mask)) {
  1935. env->dtlb_tag[i] = 0;
  1936. env->dtlb_tte[i] = 0;
  1937. }
  1938. return;
  1939. }
  1940. }
  1941. }
  1942. return;
  1943. case 0x49: // Interrupt data receive
  1944. // XXX
  1945. return;
  1946. case 0x46: // D-cache data
  1947. case 0x47: // D-cache tag access
  1948. case 0x4b: // E-cache error enable
  1949. case 0x4c: // E-cache asynchronous fault status
  1950. case 0x4d: // E-cache asynchronous fault address
  1951. case 0x4e: // E-cache tag data
  1952. case 0x66: // I-cache instruction access
  1953. case 0x67: // I-cache tag access
  1954. case 0x6e: // I-cache predecode
  1955. case 0x6f: // I-cache LRU etc.
  1956. case 0x76: // E-cache tag
  1957. case 0x7e: // E-cache tag
  1958. return;
  1959. case 0x51: // I-MMU 8k TSB pointer, RO
  1960. case 0x52: // I-MMU 64k TSB pointer, RO
  1961. case 0x56: // I-MMU tag read, RO
  1962. case 0x59: // D-MMU 8k TSB pointer, RO
  1963. case 0x5a: // D-MMU 64k TSB pointer, RO
  1964. case 0x5b: // D-MMU data pointer, RO
  1965. case 0x5e: // D-MMU tag read, RO
  1966. case 0x48: // Interrupt dispatch, RO
  1967. case 0x7f: // Incoming interrupt vector, RO
  1968. case 0x82: // Primary no-fault, RO
  1969. case 0x83: // Secondary no-fault, RO
  1970. case 0x8a: // Primary no-fault LE, RO
  1971. case 0x8b: // Secondary no-fault LE, RO
  1972. default:
  1973. do_unassigned_access(addr, 1, 0, 1, size);
  1974. return;
  1975. }
  1976. }
  1977. #endif /* CONFIG_USER_ONLY */
  1978. void helper_ldda_asi(target_ulong addr, int asi, int rd)
  1979. {
  1980. if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
  1981. || ((env->def->features & CPU_FEATURE_HYPV)
  1982. && asi >= 0x30 && asi < 0x80
  1983. && !(env->hpstate & HS_PRIV)))
  1984. raise_exception(TT_PRIV_ACT);
  1985. switch (asi) {
  1986. case 0x24: // Nucleus quad LDD 128 bit atomic
  1987. case 0x2c: // Nucleus quad LDD 128 bit atomic LE
  1988. helper_check_align(addr, 0xf);
  1989. if (rd == 0) {
  1990. env->gregs[1] = ldq_kernel(addr + 8);
  1991. if (asi == 0x2c)
  1992. bswap64s(&env->gregs[1]);
  1993. } else if (rd < 8) {
  1994. env->gregs[rd] = ldq_kernel(addr);
  1995. env->gregs[rd + 1] = ldq_kernel(addr + 8);
  1996. if (asi == 0x2c) {
  1997. bswap64s(&env->gregs[rd]);
  1998. bswap64s(&env->gregs[rd + 1]);
  1999. }
  2000. } else {
  2001. env->regwptr[rd] = ldq_kernel(addr);
  2002. env->regwptr[rd + 1] = ldq_kernel(addr + 8);
  2003. if (asi == 0x2c) {
  2004. bswap64s(&env->regwptr[rd]);
  2005. bswap64s(&env->regwptr[rd + 1]);
  2006. }
  2007. }
  2008. break;
  2009. default:
  2010. helper_check_align(addr, 0x3);
  2011. if (rd == 0)
  2012. env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
  2013. else if (rd < 8) {
  2014. env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
  2015. env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
  2016. } else {
  2017. env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
  2018. env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
  2019. }
  2020. break;
  2021. }
  2022. }
  2023. void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
  2024. {
  2025. unsigned int i;
  2026. target_ulong val;
  2027. helper_check_align(addr, 3);
  2028. switch (asi) {
  2029. case 0xf0: // Block load primary
  2030. case 0xf1: // Block load secondary
  2031. case 0xf8: // Block load primary LE
  2032. case 0xf9: // Block load secondary LE
  2033. if (rd & 7) {
  2034. raise_exception(TT_ILL_INSN);
  2035. return;
  2036. }
  2037. helper_check_align(addr, 0x3f);
  2038. for (i = 0; i < 16; i++) {
  2039. *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
  2040. 0);
  2041. addr += 4;
  2042. }
  2043. return;
  2044. default:
  2045. break;
  2046. }
  2047. val = helper_ld_asi(addr, asi, size, 0);
  2048. switch(size) {
  2049. default:
  2050. case 4:
  2051. *((uint32_t *)&env->fpr[rd]) = val;
  2052. break;
  2053. case 8:
  2054. *((int64_t *)&DT0) = val;
  2055. break;
  2056. case 16:
  2057. // XXX
  2058. break;
  2059. }
  2060. }
  2061. void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
  2062. {
  2063. unsigned int i;
  2064. target_ulong val = 0;
  2065. helper_check_align(addr, 3);
  2066. switch (asi) {
  2067. case 0xe0: // UA2007 Block commit store primary (cache flush)
  2068. case 0xe1: // UA2007 Block commit store secondary (cache flush)
  2069. case 0xf0: // Block store primary
  2070. case 0xf1: // Block store secondary
  2071. case 0xf8: // Block store primary LE
  2072. case 0xf9: // Block store secondary LE
  2073. if (rd & 7) {
  2074. raise_exception(TT_ILL_INSN);
  2075. return;
  2076. }
  2077. helper_check_align(addr, 0x3f);
  2078. for (i = 0; i < 16; i++) {
  2079. val = *(uint32_t *)&env->fpr[rd++];
  2080. helper_st_asi(addr, val, asi & 0x8f, 4);
  2081. addr += 4;
  2082. }
  2083. return;
  2084. default:
  2085. break;
  2086. }
  2087. switch(size) {
  2088. default:
  2089. case 4:
  2090. val = *((uint32_t *)&env->fpr[rd]);
  2091. break;
  2092. case 8:
  2093. val = *((int64_t *)&DT0);
  2094. break;
  2095. case 16:
  2096. // XXX
  2097. break;
  2098. }
  2099. helper_st_asi(addr, val, asi, size);
  2100. }
  2101. target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
  2102. target_ulong val2, uint32_t asi)
  2103. {
  2104. target_ulong ret;
  2105. val2 &= 0xffffffffUL;
  2106. ret = helper_ld_asi(addr, asi, 4, 0);
  2107. ret &= 0xffffffffUL;
  2108. if (val2 == ret)
  2109. helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
  2110. return ret;
  2111. }
  2112. target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
  2113. target_ulong val2, uint32_t asi)
  2114. {
  2115. target_ulong ret;
  2116. ret = helper_ld_asi(addr, asi, 8, 0);
  2117. if (val2 == ret)
  2118. helper_st_asi(addr, val1, asi, 8);
  2119. return ret;
  2120. }
  2121. #endif /* TARGET_SPARC64 */
  2122. #ifndef TARGET_SPARC64
  2123. void helper_rett(void)
  2124. {
  2125. unsigned int cwp;
  2126. if (env->psret == 1)
  2127. raise_exception(TT_ILL_INSN);
  2128. env->psret = 1;
  2129. cwp = cpu_cwp_inc(env, env->cwp + 1) ;
  2130. if (env->wim & (1 << cwp)) {
  2131. raise_exception(TT_WIN_UNF);
  2132. }
  2133. set_cwp(cwp);
  2134. env->psrs = env->psrps;
  2135. }
  2136. #endif
  2137. target_ulong helper_udiv(target_ulong a, target_ulong b)
  2138. {
  2139. uint64_t x0;
  2140. uint32_t x1;
  2141. x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
  2142. x1 = b;
  2143. if (x1 == 0) {
  2144. raise_exception(TT_DIV_ZERO);
  2145. }
  2146. x0 = x0 / x1;
  2147. if (x0 > 0xffffffff) {
  2148. env->cc_src2 = 1;
  2149. return 0xffffffff;
  2150. } else {
  2151. env->cc_src2 = 0;
  2152. return x0;
  2153. }
  2154. }
  2155. target_ulong helper_sdiv(target_ulong a, target_ulong b)
  2156. {
  2157. int64_t x0;
  2158. int32_t x1;
  2159. x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
  2160. x1 = b;
  2161. if (x1 == 0) {
  2162. raise_exception(TT_DIV_ZERO);
  2163. }
  2164. x0 = x0 / x1;
  2165. if ((int32_t) x0 != x0) {
  2166. env->cc_src2 = 1;
  2167. return x0 < 0? 0x80000000: 0x7fffffff;
  2168. } else {
  2169. env->cc_src2 = 0;
  2170. return x0;
  2171. }
  2172. }
  2173. void helper_stdf(target_ulong addr, int mem_idx)
  2174. {
  2175. helper_check_align(addr, 7);
  2176. #if !defined(CONFIG_USER_ONLY)
  2177. switch (mem_idx) {
  2178. case 0:
  2179. stfq_user(addr, DT0);
  2180. break;
  2181. case 1:
  2182. stfq_kernel(addr, DT0);
  2183. break;
  2184. #ifdef TARGET_SPARC64
  2185. case 2:
  2186. stfq_hypv(addr, DT0);
  2187. break;
  2188. #endif
  2189. default:
  2190. break;
  2191. }
  2192. #else
  2193. address_mask(env, &addr);
  2194. stfq_raw(addr, DT0);
  2195. #endif
  2196. }
  2197. void helper_lddf(target_ulong addr, int mem_idx)
  2198. {
  2199. helper_check_align(addr, 7);
  2200. #if !defined(CONFIG_USER_ONLY)
  2201. switch (mem_idx) {
  2202. case 0:
  2203. DT0 = ldfq_user(addr);
  2204. break;
  2205. case 1:
  2206. DT0 = ldfq_kernel(addr);
  2207. break;
  2208. #ifdef TARGET_SPARC64
  2209. case 2:
  2210. DT0 = ldfq_hypv(addr);
  2211. break;
  2212. #endif
  2213. default:
  2214. break;
  2215. }
  2216. #else
  2217. address_mask(env, &addr);
  2218. DT0 = ldfq_raw(addr);
  2219. #endif
  2220. }
  2221. void helper_ldqf(target_ulong addr, int mem_idx)
  2222. {
  2223. // XXX add 128 bit load
  2224. CPU_QuadU u;
  2225. helper_check_align(addr, 7);
  2226. #if !defined(CONFIG_USER_ONLY)
  2227. switch (mem_idx) {
  2228. case 0:
  2229. u.ll.upper = ldq_user(addr);
  2230. u.ll.lower = ldq_user(addr + 8);
  2231. QT0 = u.q;
  2232. break;
  2233. case 1:
  2234. u.ll.upper = ldq_kernel(addr);
  2235. u.ll.lower = ldq_kernel(addr + 8);
  2236. QT0 = u.q;
  2237. break;
  2238. #ifdef TARGET_SPARC64
  2239. case 2:
  2240. u.ll.upper = ldq_hypv(addr);
  2241. u.ll.lower = ldq_hypv(addr + 8);
  2242. QT0 = u.q;
  2243. break;
  2244. #endif
  2245. default:
  2246. break;
  2247. }
  2248. #else
  2249. address_mask(env, &addr);
  2250. u.ll.upper = ldq_raw(addr);
  2251. u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
  2252. QT0 = u.q;
  2253. #endif
  2254. }
  2255. void helper_stqf(target_ulong addr, int mem_idx)
  2256. {
  2257. // XXX add 128 bit store
  2258. CPU_QuadU u;
  2259. helper_check_align(addr, 7);
  2260. #if !defined(CONFIG_USER_ONLY)
  2261. switch (mem_idx) {
  2262. case 0:
  2263. u.q = QT0;
  2264. stq_user(addr, u.ll.upper);
  2265. stq_user(addr + 8, u.ll.lower);
  2266. break;
  2267. case 1:
  2268. u.q = QT0;
  2269. stq_kernel(addr, u.ll.upper);
  2270. stq_kernel(addr + 8, u.ll.lower);
  2271. break;
  2272. #ifdef TARGET_SPARC64
  2273. case 2:
  2274. u.q = QT0;
  2275. stq_hypv(addr, u.ll.upper);
  2276. stq_hypv(addr + 8, u.ll.lower);
  2277. break;
  2278. #endif
  2279. default:
  2280. break;
  2281. }
  2282. #else
  2283. u.q = QT0;
  2284. address_mask(env, &addr);
  2285. stq_raw(addr, u.ll.upper);
  2286. stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
  2287. #endif
  2288. }
  2289. static inline void set_fsr(void)
  2290. {
  2291. int rnd_mode;
  2292. switch (env->fsr & FSR_RD_MASK) {
  2293. case FSR_RD_NEAREST:
  2294. rnd_mode = float_round_nearest_even;
  2295. break;
  2296. default:
  2297. case FSR_RD_ZERO:
  2298. rnd_mode = float_round_to_zero;
  2299. break;
  2300. case FSR_RD_POS:
  2301. rnd_mode = float_round_up;
  2302. break;
  2303. case FSR_RD_NEG:
  2304. rnd_mode = float_round_down;
  2305. break;
  2306. }
  2307. set_float_rounding_mode(rnd_mode, &env->fp_status);
  2308. }
  2309. void helper_ldfsr(uint32_t new_fsr)
  2310. {
  2311. env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
  2312. set_fsr();
  2313. }
  2314. #ifdef TARGET_SPARC64
  2315. void helper_ldxfsr(uint64_t new_fsr)
  2316. {
  2317. env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
  2318. set_fsr();
  2319. }
  2320. #endif
  2321. void helper_debug(void)
  2322. {
  2323. env->exception_index = EXCP_DEBUG;
  2324. cpu_loop_exit();
  2325. }
  2326. #ifndef TARGET_SPARC64
  2327. /* XXX: use another pointer for %iN registers to avoid slow wrapping
  2328. handling ? */
  2329. void helper_save(void)
  2330. {
  2331. uint32_t cwp;
  2332. cwp = cpu_cwp_dec(env, env->cwp - 1);
  2333. if (env->wim & (1 << cwp)) {
  2334. raise_exception(TT_WIN_OVF);
  2335. }
  2336. set_cwp(cwp);
  2337. }
  2338. void helper_restore(void)
  2339. {
  2340. uint32_t cwp;
  2341. cwp = cpu_cwp_inc(env, env->cwp + 1);
  2342. if (env->wim & (1 << cwp)) {
  2343. raise_exception(TT_WIN_UNF);
  2344. }
  2345. set_cwp(cwp);
  2346. }
  2347. void helper_wrpsr(target_ulong new_psr)
  2348. {
  2349. if ((new_psr & PSR_CWP) >= env->nwindows)
  2350. raise_exception(TT_ILL_INSN);
  2351. else
  2352. PUT_PSR(env, new_psr);
  2353. }
  2354. target_ulong helper_rdpsr(void)
  2355. {
  2356. return GET_PSR(env);
  2357. }
  2358. #else
  2359. /* XXX: use another pointer for %iN registers to avoid slow wrapping
  2360. handling ? */
  2361. void helper_save(void)
  2362. {
  2363. uint32_t cwp;
  2364. cwp = cpu_cwp_dec(env, env->cwp - 1);
  2365. if (env->cansave == 0) {
  2366. raise_exception(TT_SPILL | (env->otherwin != 0 ?
  2367. (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
  2368. ((env->wstate & 0x7) << 2)));
  2369. } else {
  2370. if (env->cleanwin - env->canrestore == 0) {
  2371. // XXX Clean windows without trap
  2372. raise_exception(TT_CLRWIN);
  2373. } else {
  2374. env->cansave--;
  2375. env->canrestore++;
  2376. set_cwp(cwp);
  2377. }
  2378. }
  2379. }
  2380. void helper_restore(void)
  2381. {
  2382. uint32_t cwp;
  2383. cwp = cpu_cwp_inc(env, env->cwp + 1);
  2384. if (env->canrestore == 0) {
  2385. raise_exception(TT_FILL | (env->otherwin != 0 ?
  2386. (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
  2387. ((env->wstate & 0x7) << 2)));
  2388. } else {
  2389. env->cansave++;
  2390. env->canrestore--;
  2391. set_cwp(cwp);
  2392. }
  2393. }
  2394. void helper_flushw(void)
  2395. {
  2396. if (env->cansave != env->nwindows - 2) {
  2397. raise_exception(TT_SPILL | (env->otherwin != 0 ?
  2398. (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
  2399. ((env->wstate & 0x7) << 2)));
  2400. }
  2401. }
  2402. void helper_saved(void)
  2403. {
  2404. env->cansave++;
  2405. if (env->otherwin == 0)
  2406. env->canrestore--;
  2407. else
  2408. env->otherwin--;
  2409. }
  2410. void helper_restored(void)
  2411. {
  2412. env->canrestore++;
  2413. if (env->cleanwin < env->nwindows - 1)
  2414. env->cleanwin++;
  2415. if (env->otherwin == 0)
  2416. env->cansave--;
  2417. else
  2418. env->otherwin--;
  2419. }
  2420. target_ulong helper_rdccr(void)
  2421. {
  2422. return GET_CCR(env);
  2423. }
  2424. void helper_wrccr(target_ulong new_ccr)
  2425. {
  2426. PUT_CCR(env, new_ccr);
  2427. }
  2428. // CWP handling is reversed in V9, but we still use the V8 register
  2429. // order.
  2430. target_ulong helper_rdcwp(void)
  2431. {
  2432. return GET_CWP64(env);
  2433. }
  2434. void helper_wrcwp(target_ulong new_cwp)
  2435. {
  2436. PUT_CWP64(env, new_cwp);
  2437. }
  2438. // This function uses non-native bit order
  2439. #define GET_FIELD(X, FROM, TO) \
  2440. ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
  2441. // This function uses the order in the manuals, i.e. bit 0 is 2^0
  2442. #define GET_FIELD_SP(X, FROM, TO) \
  2443. GET_FIELD(X, 63 - (TO), 63 - (FROM))
  2444. target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
  2445. {
  2446. return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
  2447. (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
  2448. (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
  2449. (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
  2450. (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
  2451. (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
  2452. (((pixel_addr >> 55) & 1) << 4) |
  2453. (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
  2454. GET_FIELD_SP(pixel_addr, 11, 12);
  2455. }
  2456. target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
  2457. {
  2458. uint64_t tmp;
  2459. tmp = addr + offset;
  2460. env->gsr &= ~7ULL;
  2461. env->gsr |= tmp & 7ULL;
  2462. return tmp & ~7ULL;
  2463. }
  2464. target_ulong helper_popc(target_ulong val)
  2465. {
  2466. return ctpop64(val);
  2467. }
  2468. static inline uint64_t *get_gregset(uint64_t pstate)
  2469. {
  2470. switch (pstate) {
  2471. default:
  2472. case 0:
  2473. return env->bgregs;
  2474. case PS_AG:
  2475. return env->agregs;
  2476. case PS_MG:
  2477. return env->mgregs;
  2478. case PS_IG:
  2479. return env->igregs;
  2480. }
  2481. }
  2482. static inline void change_pstate(uint64_t new_pstate)
  2483. {
  2484. uint64_t pstate_regs, new_pstate_regs;
  2485. uint64_t *src, *dst;
  2486. pstate_regs = env->pstate & 0xc01;
  2487. new_pstate_regs = new_pstate & 0xc01;
  2488. if (new_pstate_regs != pstate_regs) {
  2489. // Switch global register bank
  2490. src = get_gregset(new_pstate_regs);
  2491. dst = get_gregset(pstate_regs);
  2492. memcpy32(dst, env->gregs);
  2493. memcpy32(env->gregs, src);
  2494. }
  2495. env->pstate = new_pstate;
  2496. }
  2497. void helper_wrpstate(target_ulong new_state)
  2498. {
  2499. if (!(env->def->features & CPU_FEATURE_GL))
  2500. change_pstate(new_state & 0xf3f);
  2501. }
  2502. void helper_done(void)
  2503. {
  2504. env->pc = env->tsptr->tpc;
  2505. env->npc = env->tsptr->tnpc + 4;
  2506. PUT_CCR(env, env->tsptr->tstate >> 32);
  2507. env->asi = (env->tsptr->tstate >> 24) & 0xff;
  2508. change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
  2509. PUT_CWP64(env, env->tsptr->tstate & 0xff);
  2510. env->tl--;
  2511. env->tsptr = &env->ts[env->tl & MAXTL_MASK];
  2512. }
  2513. void helper_retry(void)
  2514. {
  2515. env->pc = env->tsptr->tpc;
  2516. env->npc = env->tsptr->tnpc;
  2517. PUT_CCR(env, env->tsptr->tstate >> 32);
  2518. env->asi = (env->tsptr->tstate >> 24) & 0xff;
  2519. change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
  2520. PUT_CWP64(env, env->tsptr->tstate & 0xff);
  2521. env->tl--;
  2522. env->tsptr = &env->ts[env->tl & MAXTL_MASK];
  2523. }
  2524. void helper_set_softint(uint64_t value)
  2525. {
  2526. env->softint |= (uint32_t)value;
  2527. }
  2528. void helper_clear_softint(uint64_t value)
  2529. {
  2530. env->softint &= (uint32_t)~value;
  2531. }
  2532. void helper_write_softint(uint64_t value)
  2533. {
  2534. env->softint = (uint32_t)value;
  2535. }
  2536. #endif
  2537. void helper_flush(target_ulong addr)
  2538. {
  2539. addr &= ~7;
  2540. tb_invalidate_page_range(addr, addr + 8);
  2541. }
  2542. #ifdef TARGET_SPARC64
  2543. #ifdef DEBUG_PCALL
  2544. static const char * const excp_names[0x80] = {
  2545. [TT_TFAULT] = "Instruction Access Fault",
  2546. [TT_TMISS] = "Instruction Access MMU Miss",
  2547. [TT_CODE_ACCESS] = "Instruction Access Error",
  2548. [TT_ILL_INSN] = "Illegal Instruction",
  2549. [TT_PRIV_INSN] = "Privileged Instruction",
  2550. [TT_NFPU_INSN] = "FPU Disabled",
  2551. [TT_FP_EXCP] = "FPU Exception",
  2552. [TT_TOVF] = "Tag Overflow",
  2553. [TT_CLRWIN] = "Clean Windows",
  2554. [TT_DIV_ZERO] = "Division By Zero",
  2555. [TT_DFAULT] = "Data Access Fault",
  2556. [TT_DMISS] = "Data Access MMU Miss",
  2557. [TT_DATA_ACCESS] = "Data Access Error",
  2558. [TT_DPROT] = "Data Protection Error",
  2559. [TT_UNALIGNED] = "Unaligned Memory Access",
  2560. [TT_PRIV_ACT] = "Privileged Action",
  2561. [TT_EXTINT | 0x1] = "External Interrupt 1",
  2562. [TT_EXTINT | 0x2] = "External Interrupt 2",
  2563. [TT_EXTINT | 0x3] = "External Interrupt 3",
  2564. [TT_EXTINT | 0x4] = "External Interrupt 4",
  2565. [TT_EXTINT | 0x5] = "External Interrupt 5",
  2566. [TT_EXTINT | 0x6] = "External Interrupt 6",
  2567. [TT_EXTINT | 0x7] = "External Interrupt 7",
  2568. [TT_EXTINT | 0x8] = "External Interrupt 8",
  2569. [TT_EXTINT | 0x9] = "External Interrupt 9",
  2570. [TT_EXTINT | 0xa] = "External Interrupt 10",
  2571. [TT_EXTINT | 0xb] = "External Interrupt 11",
  2572. [TT_EXTINT | 0xc] = "External Interrupt 12",
  2573. [TT_EXTINT | 0xd] = "External Interrupt 13",
  2574. [TT_EXTINT | 0xe] = "External Interrupt 14",
  2575. [TT_EXTINT | 0xf] = "External Interrupt 15",
  2576. };
  2577. #endif
  2578. void do_interrupt(CPUState *env)
  2579. {
  2580. int intno = env->exception_index;
  2581. #ifdef DEBUG_PCALL
  2582. if (qemu_loglevel_mask(CPU_LOG_INT)) {
  2583. static int count;
  2584. const char *name;
  2585. if (intno < 0 || intno >= 0x180)
  2586. name = "Unknown";
  2587. else if (intno >= 0x100)
  2588. name = "Trap Instruction";
  2589. else if (intno >= 0xc0)
  2590. name = "Window Fill";
  2591. else if (intno >= 0x80)
  2592. name = "Window Spill";
  2593. else {
  2594. name = excp_names[intno];
  2595. if (!name)
  2596. name = "Unknown";
  2597. }
  2598. qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
  2599. " SP=%016" PRIx64 "\n",
  2600. count, name, intno,
  2601. env->pc,
  2602. env->npc, env->regwptr[6]);
  2603. log_cpu_state(env, 0);
  2604. #if 0
  2605. {
  2606. int i;
  2607. uint8_t *ptr;
  2608. qemu_log(" code=");
  2609. ptr = (uint8_t *)env->pc;
  2610. for(i = 0; i < 16; i++) {
  2611. qemu_log(" %02x", ldub(ptr + i));
  2612. }
  2613. qemu_log("\n");
  2614. }
  2615. #endif
  2616. count++;
  2617. }
  2618. #endif
  2619. #if !defined(CONFIG_USER_ONLY)
  2620. if (env->tl >= env->maxtl) {
  2621. cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
  2622. " Error state", env->exception_index, env->tl, env->maxtl);
  2623. return;
  2624. }
  2625. #endif
  2626. if (env->tl < env->maxtl - 1) {
  2627. env->tl++;
  2628. } else {
  2629. env->pstate |= PS_RED;
  2630. if (env->tl < env->maxtl)
  2631. env->tl++;
  2632. }
  2633. env->tsptr = &env->ts[env->tl & MAXTL_MASK];
  2634. env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
  2635. ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
  2636. GET_CWP64(env);
  2637. env->tsptr->tpc = env->pc;
  2638. env->tsptr->tnpc = env->npc;
  2639. env->tsptr->tt = intno;
  2640. if (!(env->def->features & CPU_FEATURE_GL)) {
  2641. switch (intno) {
  2642. case TT_IVEC:
  2643. change_pstate(PS_PEF | PS_PRIV | PS_IG);
  2644. break;
  2645. case TT_TFAULT:
  2646. case TT_TMISS:
  2647. case TT_DFAULT:
  2648. case TT_DMISS:
  2649. case TT_DPROT:
  2650. change_pstate(PS_PEF | PS_PRIV | PS_MG);
  2651. break;
  2652. default:
  2653. change_pstate(PS_PEF | PS_PRIV | PS_AG);
  2654. break;
  2655. }
  2656. }
  2657. if (intno == TT_CLRWIN)
  2658. cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
  2659. else if ((intno & 0x1c0) == TT_SPILL)
  2660. cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
  2661. else if ((intno & 0x1c0) == TT_FILL)
  2662. cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
  2663. env->tbr &= ~0x7fffULL;
  2664. env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
  2665. env->pc = env->tbr;
  2666. env->npc = env->pc + 4;
  2667. env->exception_index = 0;
  2668. }
  2669. #else
  2670. #ifdef DEBUG_PCALL
  2671. static const char * const excp_names[0x80] = {
  2672. [TT_TFAULT] = "Instruction Access Fault",
  2673. [TT_ILL_INSN] = "Illegal Instruction",
  2674. [TT_PRIV_INSN] = "Privileged Instruction",
  2675. [TT_NFPU_INSN] = "FPU Disabled",
  2676. [TT_WIN_OVF] = "Window Overflow",
  2677. [TT_WIN_UNF] = "Window Underflow",
  2678. [TT_UNALIGNED] = "Unaligned Memory Access",
  2679. [TT_FP_EXCP] = "FPU Exception",
  2680. [TT_DFAULT] = "Data Access Fault",
  2681. [TT_TOVF] = "Tag Overflow",
  2682. [TT_EXTINT | 0x1] = "External Interrupt 1",
  2683. [TT_EXTINT | 0x2] = "External Interrupt 2",
  2684. [TT_EXTINT | 0x3] = "External Interrupt 3",
  2685. [TT_EXTINT | 0x4] = "External Interrupt 4",
  2686. [TT_EXTINT | 0x5] = "External Interrupt 5",
  2687. [TT_EXTINT | 0x6] = "External Interrupt 6",
  2688. [TT_EXTINT | 0x7] = "External Interrupt 7",
  2689. [TT_EXTINT | 0x8] = "External Interrupt 8",
  2690. [TT_EXTINT | 0x9] = "External Interrupt 9",
  2691. [TT_EXTINT | 0xa] = "External Interrupt 10",
  2692. [TT_EXTINT | 0xb] = "External Interrupt 11",
  2693. [TT_EXTINT | 0xc] = "External Interrupt 12",
  2694. [TT_EXTINT | 0xd] = "External Interrupt 13",
  2695. [TT_EXTINT | 0xe] = "External Interrupt 14",
  2696. [TT_EXTINT | 0xf] = "External Interrupt 15",
  2697. [TT_TOVF] = "Tag Overflow",
  2698. [TT_CODE_ACCESS] = "Instruction Access Error",
  2699. [TT_DATA_ACCESS] = "Data Access Error",
  2700. [TT_DIV_ZERO] = "Division By Zero",
  2701. [TT_NCP_INSN] = "Coprocessor Disabled",
  2702. };
  2703. #endif
  2704. void do_interrupt(CPUState *env)
  2705. {
  2706. int cwp, intno = env->exception_index;
  2707. #ifdef DEBUG_PCALL
  2708. if (qemu_loglevel_mask(CPU_LOG_INT)) {
  2709. static int count;
  2710. const char *name;
  2711. if (intno < 0 || intno >= 0x100)
  2712. name = "Unknown";
  2713. else if (intno >= 0x80)
  2714. name = "Trap Instruction";
  2715. else {
  2716. name = excp_names[intno];
  2717. if (!name)
  2718. name = "Unknown";
  2719. }
  2720. qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
  2721. count, name, intno,
  2722. env->pc,
  2723. env->npc, env->regwptr[6]);
  2724. log_cpu_state(env, 0);
  2725. #if 0
  2726. {
  2727. int i;
  2728. uint8_t *ptr;
  2729. qemu_log(" code=");
  2730. ptr = (uint8_t *)env->pc;
  2731. for(i = 0; i < 16; i++) {
  2732. qemu_log(" %02x", ldub(ptr + i));
  2733. }
  2734. qemu_log("\n");
  2735. }
  2736. #endif
  2737. count++;
  2738. }
  2739. #endif
  2740. #if !defined(CONFIG_USER_ONLY)
  2741. if (env->psret == 0) {
  2742. cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
  2743. env->exception_index);
  2744. return;
  2745. }
  2746. #endif
  2747. env->psret = 0;
  2748. cwp = cpu_cwp_dec(env, env->cwp - 1);
  2749. cpu_set_cwp(env, cwp);
  2750. env->regwptr[9] = env->pc;
  2751. env->regwptr[10] = env->npc;
  2752. env->psrps = env->psrs;
  2753. env->psrs = 1;
  2754. env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
  2755. env->pc = env->tbr;
  2756. env->npc = env->pc + 4;
  2757. env->exception_index = 0;
  2758. }
  2759. #endif
  2760. #if !defined(CONFIG_USER_ONLY)
  2761. static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
  2762. void *retaddr);
  2763. #define MMUSUFFIX _mmu
  2764. #define ALIGNED_ONLY
  2765. #define SHIFT 0
  2766. #include "softmmu_template.h"
  2767. #define SHIFT 1
  2768. #include "softmmu_template.h"
  2769. #define SHIFT 2
  2770. #include "softmmu_template.h"
  2771. #define SHIFT 3
  2772. #include "softmmu_template.h"
  2773. /* XXX: make it generic ? */
  2774. static void cpu_restore_state2(void *retaddr)
  2775. {
  2776. TranslationBlock *tb;
  2777. unsigned long pc;
  2778. if (retaddr) {
  2779. /* now we have a real cpu fault */
  2780. pc = (unsigned long)retaddr;
  2781. tb = tb_find_pc(pc);
  2782. if (tb) {
  2783. /* the PC is inside the translated code. It means that we have
  2784. a virtual CPU fault */
  2785. cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
  2786. }
  2787. }
  2788. }
  2789. static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
  2790. void *retaddr)
  2791. {
  2792. #ifdef DEBUG_UNALIGNED
  2793. printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
  2794. "\n", addr, env->pc);
  2795. #endif
  2796. cpu_restore_state2(retaddr);
  2797. raise_exception(TT_UNALIGNED);
  2798. }
  2799. /* try to fill the TLB and return an exception if error. If retaddr is
  2800. NULL, it means that the function was called in C code (i.e. not
  2801. from generated code or from helper.c) */
  2802. /* XXX: fix it to restore all registers */
  2803. void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
  2804. {
  2805. int ret;
  2806. CPUState *saved_env;
  2807. /* XXX: hack to restore env in all cases, even if not called from
  2808. generated code */
  2809. saved_env = env;
  2810. env = cpu_single_env;
  2811. ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
  2812. if (ret) {
  2813. cpu_restore_state2(retaddr);
  2814. cpu_loop_exit();
  2815. }
  2816. env = saved_env;
  2817. }
  2818. #endif
  2819. #ifndef TARGET_SPARC64
  2820. void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
  2821. int is_asi, int size)
  2822. {
  2823. CPUState *saved_env;
  2824. /* XXX: hack to restore env in all cases, even if not called from
  2825. generated code */
  2826. saved_env = env;
  2827. env = cpu_single_env;
  2828. #ifdef DEBUG_UNASSIGNED
  2829. if (is_asi)
  2830. printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
  2831. " asi 0x%02x from " TARGET_FMT_lx "\n",
  2832. is_exec ? "exec" : is_write ? "write" : "read", size,
  2833. size == 1 ? "" : "s", addr, is_asi, env->pc);
  2834. else
  2835. printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
  2836. " from " TARGET_FMT_lx "\n",
  2837. is_exec ? "exec" : is_write ? "write" : "read", size,
  2838. size == 1 ? "" : "s", addr, env->pc);
  2839. #endif
  2840. if (env->mmuregs[3]) /* Fault status register */
  2841. env->mmuregs[3] = 1; /* overflow (not read before another fault) */
  2842. if (is_asi)
  2843. env->mmuregs[3] |= 1 << 16;
  2844. if (env->psrs)
  2845. env->mmuregs[3] |= 1 << 5;
  2846. if (is_exec)
  2847. env->mmuregs[3] |= 1 << 6;
  2848. if (is_write)
  2849. env->mmuregs[3] |= 1 << 7;
  2850. env->mmuregs[3] |= (5 << 2) | 2;
  2851. env->mmuregs[4] = addr; /* Fault address register */
  2852. if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
  2853. if (is_exec)
  2854. raise_exception(TT_CODE_ACCESS);
  2855. else
  2856. raise_exception(TT_DATA_ACCESS);
  2857. }
  2858. env = saved_env;
  2859. }
  2860. #else
  2861. void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
  2862. int is_asi, int size)
  2863. {
  2864. #ifdef DEBUG_UNASSIGNED
  2865. CPUState *saved_env;
  2866. /* XXX: hack to restore env in all cases, even if not called from
  2867. generated code */
  2868. saved_env = env;
  2869. env = cpu_single_env;
  2870. printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
  2871. "\n", addr, env->pc);
  2872. env = saved_env;
  2873. #endif
  2874. if (is_exec)
  2875. raise_exception(TT_CODE_ACCESS);
  2876. else
  2877. raise_exception(TT_DATA_ACCESS);
  2878. }
  2879. #endif
  2880. #ifdef TARGET_SPARC64
  2881. void helper_tick_set_count(void *opaque, uint64_t count)
  2882. {
  2883. #if !defined(CONFIG_USER_ONLY)
  2884. cpu_tick_set_count(opaque, count);
  2885. #endif
  2886. }
  2887. uint64_t helper_tick_get_count(void *opaque)
  2888. {
  2889. #if !defined(CONFIG_USER_ONLY)
  2890. return cpu_tick_get_count(opaque);
  2891. #else
  2892. return 0;
  2893. #endif
  2894. }
  2895. void helper_tick_set_limit(void *opaque, uint64_t limit)
  2896. {
  2897. #if !defined(CONFIG_USER_ONLY)
  2898. cpu_tick_set_limit(opaque, limit);
  2899. #endif
  2900. }
  2901. #endif