maverick.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206
  1. /* maverick.c -- Cirrus/DSP co-processor interface.
  2. Copyright (C) 2003 Free Software Foundation, Inc.
  3. Contributed by Aldy Hernandez (aldyh@redhat.com).
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  15. #include <assert.h>
  16. #include "core/arm/interpreter/armdefs.h"
  17. #include "core/arm/interpreter/armemu.h"
  18. /*#define CIRRUS_DEBUG 1 */
  19. #if CIRRUS_DEBUG
  20. # define printfdbg printf
  21. #else
  22. # define printfdbg printf_nothing
  23. #endif
  24. #define POS64(i) ( (~(i)) >> 63 )
  25. #define NEG64(i) ( (i) >> 63 )
  26. /* Define Co-Processor instruction handlers here. */
  27. /* Here's ARMulator's DSP definition. A few things to note:
  28. 1) it has 16 64-bit registers and 4 72-bit accumulators
  29. 2) you can only access its registers with MCR and MRC. */
  30. /* We can't define these in here because this file might not be linked
  31. unless the target is arm9e-*. They are defined in wrapper.c.
  32. Eventually the simulator should be made to handle any coprocessor
  33. at run time. */
  34. struct maverick_regs
  35. {
  36. union
  37. {
  38. int i;
  39. float f;
  40. } upper;
  41. union
  42. {
  43. int i;
  44. float f;
  45. } lower;
  46. };
  47. union maverick_acc_regs
  48. {
  49. long double ld; /* Acc registers are 72-bits. */
  50. };
  51. struct maverick_regs DSPregs[16];
  52. union maverick_acc_regs DSPacc[4];
  53. ARMword DSPsc;
  54. #define DEST_REG (BITS (12, 15))
  55. #define SRC1_REG (BITS (16, 19))
  56. #define SRC2_REG (BITS (0, 3))
  57. static int lsw_int_index, msw_int_index;
  58. static int lsw_float_index, msw_float_index;
  59. static double mv_getRegDouble (int);
  60. static long long mv_getReg64int (int);
  61. static void mv_setRegDouble (int, double val);
  62. static void mv_setReg64int (int, long long val);
  63. static union
  64. {
  65. double d;
  66. long long ll;
  67. int ints[2];
  68. } reg_conv;
  69. static void
  70. printf_nothing (void *foo, ...)
  71. {
  72. }
  73. static void
  74. cirrus_not_implemented (char *insn)
  75. {
  76. fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
  77. fprintf (stderr, "aborting!\n");
  78. // skyeye_exit (1);
  79. }
  80. static unsigned
  81. DSPInit (ARMul_State * state)
  82. {
  83. NOTICE_LOG(ARM11, "ARMul_ConsolePrint: DSP present");
  84. return TRUE;
  85. }
  86. unsigned
  87. DSPMRC4 (ARMul_State * state,
  88. unsigned type, ARMword instr, ARMword * value)
  89. {
  90. switch (BITS (5, 7)) {
  91. case 0: /* cfmvrdl */
  92. /* Move lower half of a DF stored in a DSP reg into an Arm reg. */
  93. printfdbg ("cfmvrdl\n");
  94. printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
  95. printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
  96. *value = (ARMword) DSPregs[SRC1_REG].lower.i;
  97. break;
  98. case 1: /* cfmvrdh */
  99. /* Move upper half of a DF stored in a DSP reg into an Arm reg. */
  100. printfdbg ("cfmvrdh\n");
  101. printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
  102. printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
  103. *value = (ARMword) DSPregs[SRC1_REG].upper.i;
  104. break;
  105. case 2: /* cfmvrs */
  106. /* Move SF from upper half of a DSP register to an Arm register. */
  107. *value = (ARMword) DSPregs[SRC1_REG].upper.i;
  108. printfdbg ("cfmvrs = mvf%d <-- %f\n",
  109. SRC1_REG, DSPregs[SRC1_REG].upper.f);
  110. break;
  111. #ifdef doesnt_work
  112. case 4: /* cfcmps */
  113. {
  114. float a, b;
  115. int n, z, c, v;
  116. a = DSPregs[SRC1_REG].upper.f;
  117. b = DSPregs[SRC2_REG].upper.f;
  118. printfdbg ("cfcmps\n");
  119. printfdbg ("\tcomparing %f and %f\n", a, b);
  120. z = a == b; /* zero */
  121. n = a != b; /* negative */
  122. v = a > b; /* overflow */
  123. c = 0; /* carry */
  124. *value = (n << 31) | (z << 30) | (c << 29) | (v <<
  125. 28);
  126. break;
  127. }
  128. case 5: /* cfcmpd */
  129. {
  130. double a, b;
  131. int n, z, c, v;
  132. a = mv_getRegDouble (SRC1_REG);
  133. b = mv_getRegDouble (SRC2_REG);
  134. printfdbg ("cfcmpd\n");
  135. printfdbg ("\tcomparing %g and %g\n", a, b);
  136. z = a == b; /* zero */
  137. n = a != b; /* negative */
  138. v = a > b; /* overflow */
  139. c = 0; /* carry */
  140. *value = (n << 31) | (z << 30) | (c << 29) | (v <<
  141. 28);
  142. break;
  143. }
  144. #else
  145. case 4: /* cfcmps */
  146. {
  147. float a, b;
  148. int n, z, c, v;
  149. a = DSPregs[SRC1_REG].upper.f;
  150. b = DSPregs[SRC2_REG].upper.f;
  151. printfdbg ("cfcmps\n");
  152. printfdbg ("\tcomparing %f and %f\n", a, b);
  153. z = a == b; /* zero */
  154. n = a < b; /* negative */
  155. c = a > b; /* carry */
  156. v = 0; /* fixme */
  157. printfdbg ("\tz = %d, n = %d\n", z, n);
  158. *value = (n << 31) | (z << 30) | (c << 29) | (v <<
  159. 28);
  160. break;
  161. }
  162. case 5: /* cfcmpd */
  163. {
  164. double a, b;
  165. int n, z, c, v;
  166. a = mv_getRegDouble (SRC1_REG);
  167. b = mv_getRegDouble (SRC2_REG);
  168. printfdbg ("cfcmpd\n");
  169. printfdbg ("\tcomparing %g and %g\n", a, b);
  170. z = a == b; /* zero */
  171. n = a < b; /* negative */
  172. c = a > b; /* carry */
  173. v = 0; /* fixme */
  174. *value = (n << 31) | (z << 30) | (c << 29) | (v <<
  175. 28);
  176. break;
  177. }
  178. #endif
  179. default:
  180. fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
  181. cirrus_not_implemented ("unknown");
  182. break;
  183. }
  184. return ARMul_DONE;
  185. }
  186. unsigned
  187. DSPMRC5 (ARMul_State * state,
  188. unsigned type, ARMword instr, ARMword * value)
  189. {
  190. switch (BITS (5, 7)) {
  191. case 0: /* cfmvr64l */
  192. /* Move lower half of 64bit int from Cirrus to Arm. */
  193. *value = (ARMword) DSPregs[SRC1_REG].lower.i;
  194. printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
  195. DEST_REG, (int) *value);
  196. break;
  197. case 1: /* cfmvr64h */
  198. /* Move upper half of 64bit int from Cirrus to Arm. */
  199. *value = (ARMword) DSPregs[SRC1_REG].upper.i;
  200. printfdbg ("cfmvr64h <-- %d\n", (int) *value);
  201. break;
  202. case 4: /* cfcmp32 */
  203. {
  204. int res;
  205. int n, z, c, v;
  206. unsigned int a, b;
  207. printfdbg ("cfcmp32 mvfx%d - mvfx%d\n", SRC1_REG,
  208. SRC2_REG);
  209. /* FIXME: see comment for cfcmps. */
  210. a = DSPregs[SRC1_REG].lower.i;
  211. b = DSPregs[SRC2_REG].lower.i;
  212. res = DSPregs[SRC1_REG].lower.i -
  213. DSPregs[SRC2_REG].lower.i;
  214. /* zero */
  215. z = res == 0;
  216. /* negative */
  217. n = res < 0;
  218. /* overflow */
  219. v = SubOverflow (DSPregs[SRC1_REG].lower.i,
  220. DSPregs[SRC2_REG].lower.i, res);
  221. /* carry */
  222. c = (NEG (a) && POS (b) ||
  223. (NEG (a) && POS (res)) || (POS (b)
  224. && POS (res)));
  225. *value = (n << 31) | (z << 30) | (c << 29) | (v <<
  226. 28);
  227. break;
  228. }
  229. case 5: /* cfcmp64 */
  230. {
  231. long long res;
  232. int n, z, c, v;
  233. unsigned long long a, b;
  234. printfdbg ("cfcmp64 mvdx%d - mvdx%d\n", SRC1_REG,
  235. SRC2_REG);
  236. /* fixme: see comment for cfcmps. */
  237. a = mv_getReg64int (SRC1_REG);
  238. b = mv_getReg64int (SRC2_REG);
  239. res = mv_getReg64int (SRC1_REG) -
  240. mv_getReg64int (SRC2_REG);
  241. /* zero */
  242. z = res == 0;
  243. /* negative */
  244. n = res < 0;
  245. /* overflow */
  246. v = ((NEG64 (a) && POS64 (b) && POS64 (res))
  247. || (POS64 (a) && NEG64 (b) && NEG64 (res)));
  248. /* carry */
  249. c = (NEG64 (a) && POS64 (b) ||
  250. (NEG64 (a) && POS64 (res)) || (POS64 (b)
  251. && POS64 (res)));
  252. *value = (n << 31) | (z << 30) | (c << 29) | (v <<
  253. 28);
  254. break;
  255. }
  256. default:
  257. fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
  258. cirrus_not_implemented ("unknown");
  259. break;
  260. }
  261. return ARMul_DONE;
  262. }
  263. unsigned
  264. DSPMRC6 (ARMul_State * state,
  265. unsigned type, ARMword instr, ARMword * value)
  266. {
  267. switch (BITS (5, 7)) {
  268. case 0: /* cfmval32 */
  269. cirrus_not_implemented ("cfmval32");
  270. break;
  271. case 1: /* cfmvam32 */
  272. cirrus_not_implemented ("cfmvam32");
  273. break;
  274. case 2: /* cfmvah32 */
  275. cirrus_not_implemented ("cfmvah32");
  276. break;
  277. case 3: /* cfmva32 */
  278. cirrus_not_implemented ("cfmva32");
  279. break;
  280. case 4: /* cfmva64 */
  281. cirrus_not_implemented ("cfmva64");
  282. break;
  283. case 5: /* cfmvsc32 */
  284. cirrus_not_implemented ("cfmvsc32");
  285. break;
  286. default:
  287. fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
  288. cirrus_not_implemented ("unknown");
  289. break;
  290. }
  291. return ARMul_DONE;
  292. }
  293. unsigned
  294. DSPMCR4 (ARMul_State * state,
  295. unsigned type, ARMword instr, ARMword value)
  296. {
  297. switch (BITS (5, 7)) {
  298. case 0: /* cfmvdlr */
  299. /* Move the lower half of a DF value from an Arm register into
  300. the lower half of a Cirrus register. */
  301. printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
  302. DSPregs[SRC1_REG].lower.i = (int) value;
  303. break;
  304. case 1: /* cfmvdhr */
  305. /* Move the upper half of a DF value from an Arm register into
  306. the upper half of a Cirrus register. */
  307. printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
  308. DSPregs[SRC1_REG].upper.i = (int) value;
  309. break;
  310. case 2: /* cfmvsr */
  311. /* Move SF from Arm register into upper half of Cirrus register. */
  312. printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
  313. DSPregs[SRC1_REG].upper.i = (int) value;
  314. break;
  315. default:
  316. fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
  317. cirrus_not_implemented ("unknown");
  318. break;
  319. }
  320. return ARMul_DONE;
  321. }
  322. unsigned
  323. DSPMCR5 (ARMul_State * state,
  324. unsigned type, ARMword instr, ARMword value)
  325. {
  326. union
  327. {
  328. int s;
  329. unsigned int us;
  330. } val;
  331. switch (BITS (5, 7)) {
  332. case 0: /* cfmv64lr */
  333. /* Move lower half of a 64bit int from an ARM register into the
  334. lower half of a DSP register and sign extend it. */
  335. printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG,
  336. (int) value);
  337. DSPregs[SRC1_REG].lower.i = (int) value;
  338. break;
  339. case 1: /* cfmv64hr */
  340. /* Move upper half of a 64bit int from an ARM register into the
  341. upper half of a DSP register. */
  342. printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
  343. SRC1_REG, (int) value);
  344. DSPregs[SRC1_REG].upper.i = (int) value;
  345. break;
  346. case 2: /* cfrshl32 */
  347. printfdbg ("cfrshl32\n");
  348. val.us = value;
  349. if (val.s > 0)
  350. DSPregs[SRC2_REG].lower.i =
  351. DSPregs[SRC1_REG].lower.i << value;
  352. else
  353. DSPregs[SRC2_REG].lower.i =
  354. DSPregs[SRC1_REG].lower.i >> -value;
  355. break;
  356. case 3: /* cfrshl64 */
  357. printfdbg ("cfrshl64\n");
  358. val.us = value;
  359. if (val.s > 0)
  360. mv_setReg64int (SRC2_REG,
  361. mv_getReg64int (SRC1_REG) << value);
  362. else
  363. mv_setReg64int (SRC2_REG,
  364. mv_getReg64int (SRC1_REG) >> -value);
  365. break;
  366. default:
  367. fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
  368. cirrus_not_implemented ("unknown");
  369. break;
  370. }
  371. return ARMul_DONE;
  372. }
  373. unsigned
  374. DSPMCR6 (ARMul_State * state,
  375. unsigned type, ARMword instr, ARMword value)
  376. {
  377. switch (BITS (5, 7)) {
  378. case 0: /* cfmv32al */
  379. cirrus_not_implemented ("cfmv32al");
  380. break;
  381. case 1: /* cfmv32am */
  382. cirrus_not_implemented ("cfmv32am");
  383. break;
  384. case 2: /* cfmv32ah */
  385. cirrus_not_implemented ("cfmv32ah");
  386. break;
  387. case 3: /* cfmv32a */
  388. cirrus_not_implemented ("cfmv32a");
  389. break;
  390. case 4: /* cfmv64a */
  391. cirrus_not_implemented ("cfmv64a");
  392. break;
  393. case 5: /* cfmv32sc */
  394. cirrus_not_implemented ("cfmv32sc");
  395. break;
  396. default:
  397. fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
  398. cirrus_not_implemented ("unknown");
  399. break;
  400. }
  401. return ARMul_DONE;
  402. }
  403. unsigned
  404. DSPLDC4 (ARMul_State * state,
  405. unsigned type, ARMword instr, ARMword data)
  406. {
  407. static unsigned words;
  408. if (type != ARMul_DATA) {
  409. words = 0;
  410. return ARMul_DONE;
  411. }
  412. if (BIT (22)) { /* it's a long access, get two words */
  413. /* cfldrd */
  414. printfdbg
  415. ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
  416. data, words, state->bigendSig, DEST_REG);
  417. if (words == 0) {
  418. if (state->bigendSig)
  419. DSPregs[DEST_REG].upper.i = (int) data;
  420. else
  421. DSPregs[DEST_REG].lower.i = (int) data;
  422. }
  423. else {
  424. if (state->bigendSig)
  425. DSPregs[DEST_REG].lower.i = (int) data;
  426. else
  427. DSPregs[DEST_REG].upper.i = (int) data;
  428. }
  429. ++words;
  430. if (words == 2) {
  431. printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
  432. mv_getRegDouble (DEST_REG));
  433. return ARMul_DONE;
  434. }
  435. else
  436. return ARMul_INC;
  437. }
  438. else {
  439. /* Get just one word. */
  440. /* cfldrs */
  441. printfdbg ("cfldrs\n");
  442. DSPregs[DEST_REG].upper.i = (int) data;
  443. printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
  444. DSPregs[DEST_REG].upper.f);
  445. return ARMul_DONE;
  446. }
  447. }
  448. unsigned
  449. DSPLDC5 (ARMul_State * state,
  450. unsigned type, ARMword instr, ARMword data)
  451. {
  452. static unsigned words;
  453. if (type != ARMul_DATA) {
  454. words = 0;
  455. return ARMul_DONE;
  456. }
  457. if (BIT (22)) {
  458. /* It's a long access, get two words. */
  459. /* cfldr64 */
  460. printfdbg ("cfldr64: %d\n", data);
  461. if (words == 0) {
  462. if (state->bigendSig)
  463. DSPregs[DEST_REG].upper.i = (int) data;
  464. else
  465. DSPregs[DEST_REG].lower.i = (int) data;
  466. }
  467. else {
  468. if (state->bigendSig)
  469. DSPregs[DEST_REG].lower.i = (int) data;
  470. else
  471. DSPregs[DEST_REG].upper.i = (int) data;
  472. }
  473. ++words;
  474. if (words == 2) {
  475. printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
  476. mv_getReg64int (DEST_REG));
  477. return ARMul_DONE;
  478. }
  479. else
  480. return ARMul_INC;
  481. }
  482. else {
  483. /* Get just one word. */
  484. /* cfldr32 */
  485. printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
  486. /* 32bit ints should be sign extended to 64bits when loaded. */
  487. mv_setReg64int (DEST_REG, (long long) data);
  488. return ARMul_DONE;
  489. }
  490. }
  491. unsigned
  492. DSPSTC4 (ARMul_State * state,
  493. unsigned type, ARMword instr, ARMword * data)
  494. {
  495. static unsigned words;
  496. if (type != ARMul_DATA) {
  497. words = 0;
  498. return ARMul_DONE;
  499. }
  500. if (BIT (22)) {
  501. /* It's a long access, get two words. */
  502. /* cfstrd */
  503. printfdbg ("cfstrd\n");
  504. if (words == 0) {
  505. if (state->bigendSig)
  506. *data = (ARMword) DSPregs[DEST_REG].upper.i;
  507. else
  508. *data = (ARMword) DSPregs[DEST_REG].lower.i;
  509. }
  510. else {
  511. if (state->bigendSig)
  512. *data = (ARMword) DSPregs[DEST_REG].lower.i;
  513. else
  514. *data = (ARMword) DSPregs[DEST_REG].upper.i;
  515. }
  516. ++words;
  517. if (words == 2) {
  518. printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
  519. mv_getRegDouble (DEST_REG));
  520. return ARMul_DONE;
  521. }
  522. else
  523. return ARMul_INC;
  524. }
  525. else {
  526. /* Get just one word. */
  527. /* cfstrs */
  528. printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
  529. DSPregs[DEST_REG].upper.f);
  530. *data = (ARMword) DSPregs[DEST_REG].upper.i;
  531. return ARMul_DONE;
  532. }
  533. }
  534. unsigned
  535. DSPSTC5 (ARMul_State * state,
  536. unsigned type, ARMword instr, ARMword * data)
  537. {
  538. static unsigned words;
  539. if (type != ARMul_DATA) {
  540. words = 0;
  541. return ARMul_DONE;
  542. }
  543. if (BIT (22)) {
  544. /* It's a long access, store two words. */
  545. /* cfstr64 */
  546. printfdbg ("cfstr64\n");
  547. if (words == 0) {
  548. if (state->bigendSig)
  549. *data = (ARMword) DSPregs[DEST_REG].upper.i;
  550. else
  551. *data = (ARMword) DSPregs[DEST_REG].lower.i;
  552. }
  553. else {
  554. if (state->bigendSig)
  555. *data = (ARMword) DSPregs[DEST_REG].lower.i;
  556. else
  557. *data = (ARMword) DSPregs[DEST_REG].upper.i;
  558. }
  559. ++words;
  560. if (words == 2) {
  561. printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
  562. mv_getReg64int (DEST_REG));
  563. return ARMul_DONE;
  564. }
  565. else
  566. return ARMul_INC;
  567. }
  568. else {
  569. /* Store just one word. */
  570. /* cfstr32 */
  571. *data = (ARMword) DSPregs[DEST_REG].lower.i;
  572. printfdbg ("cfstr32 MEM = %d\n", (int) *data);
  573. return ARMul_DONE;
  574. }
  575. }
  576. unsigned
  577. DSPCDP4 (ARMul_State * state, unsigned type, ARMword instr)
  578. {
  579. int opcode2;
  580. opcode2 = BITS (5, 7);
  581. switch (BITS (20, 21)) {
  582. case 0:
  583. switch (opcode2) {
  584. case 0: /* cfcpys */
  585. printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
  586. DEST_REG, SRC1_REG,
  587. DSPregs[SRC1_REG].upper.f);
  588. DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
  589. break;
  590. case 1: /* cfcpyd */
  591. printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
  592. DEST_REG, SRC1_REG,
  593. mv_getRegDouble (SRC1_REG));
  594. mv_setRegDouble (DEST_REG,
  595. mv_getRegDouble (SRC1_REG));
  596. break;
  597. case 2: /* cfcvtds */
  598. printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
  599. DEST_REG, SRC1_REG,
  600. (float) mv_getRegDouble (SRC1_REG));
  601. DSPregs[DEST_REG].upper.f =
  602. (float) mv_getRegDouble (SRC1_REG);
  603. break;
  604. case 3: /* cfcvtsd */
  605. printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
  606. DEST_REG, SRC1_REG,
  607. (double) DSPregs[SRC1_REG].upper.f);
  608. mv_setRegDouble (DEST_REG,
  609. (double) DSPregs[SRC1_REG].upper.f);
  610. break;
  611. case 4: /* cfcvt32s */
  612. printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
  613. DEST_REG, SRC1_REG,
  614. (float) DSPregs[SRC1_REG].lower.i);
  615. DSPregs[DEST_REG].upper.f =
  616. (float) DSPregs[SRC1_REG].lower.i;
  617. break;
  618. case 5: /* cfcvt32d */
  619. printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
  620. DEST_REG, SRC1_REG,
  621. (double) DSPregs[SRC1_REG].lower.i);
  622. mv_setRegDouble (DEST_REG,
  623. (double) DSPregs[SRC1_REG].lower.i);
  624. break;
  625. case 6: /* cfcvt64s */
  626. printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
  627. DEST_REG, SRC1_REG,
  628. (float) mv_getReg64int (SRC1_REG));
  629. DSPregs[DEST_REG].upper.f =
  630. (float) mv_getReg64int (SRC1_REG);
  631. break;
  632. case 7: /* cfcvt64d */
  633. printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
  634. DEST_REG, SRC1_REG,
  635. (double) mv_getReg64int (SRC1_REG));
  636. mv_setRegDouble (DEST_REG,
  637. (double) mv_getReg64int (SRC1_REG));
  638. break;
  639. }
  640. break;
  641. case 1:
  642. switch (opcode2) {
  643. case 0: /* cfmuls */
  644. printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
  645. DEST_REG,
  646. SRC1_REG,
  647. DSPregs[SRC1_REG].upper.f *
  648. DSPregs[SRC2_REG].upper.f);
  649. DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
  650. * DSPregs[SRC2_REG].upper.f;
  651. break;
  652. case 1: /* cfmuld */
  653. printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
  654. DEST_REG,
  655. SRC1_REG,
  656. mv_getRegDouble (SRC1_REG) *
  657. mv_getRegDouble (SRC2_REG));
  658. mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
  659. * mv_getRegDouble (SRC2_REG));
  660. break;
  661. default:
  662. fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n",
  663. instr);
  664. cirrus_not_implemented ("unknown");
  665. break;
  666. }
  667. break;
  668. case 3:
  669. switch (opcode2) {
  670. case 0: /* cfabss */
  671. DSPregs[DEST_REG].upper.f =
  672. (DSPregs[SRC1_REG].upper.f <
  673. 0.0F ? -DSPregs[SRC1_REG].upper.
  674. f : DSPregs[SRC1_REG].upper.f);
  675. printfdbg ("cfabss mvf%d = |mvf%d| = %f\n", DEST_REG,
  676. SRC1_REG, DSPregs[DEST_REG].upper.f);
  677. break;
  678. case 1: /* cfabsd */
  679. mv_setRegDouble (DEST_REG,
  680. (mv_getRegDouble (SRC1_REG) < 0.0 ?
  681. -mv_getRegDouble (SRC1_REG)
  682. : mv_getRegDouble (SRC1_REG)));
  683. printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
  684. DEST_REG, SRC1_REG,
  685. mv_getRegDouble (DEST_REG));
  686. break;
  687. case 2: /* cfnegs */
  688. DSPregs[DEST_REG].upper.f =
  689. -DSPregs[SRC1_REG].upper.f;
  690. printfdbg ("cfnegs mvf%d = -mvf%d = %f\n", DEST_REG,
  691. SRC1_REG, DSPregs[DEST_REG].upper.f);
  692. break;
  693. case 3: /* cfnegd */
  694. mv_setRegDouble (DEST_REG,
  695. -mv_getRegDouble (SRC1_REG));
  696. printfdbg ("cfnegd mvd%d = -mvd%d = %g\n", DEST_REG,
  697. mv_getRegDouble (DEST_REG));
  698. break;
  699. case 4: /* cfadds */
  700. DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
  701. + DSPregs[SRC2_REG].upper.f;
  702. printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
  703. DEST_REG, SRC1_REG, SRC2_REG,
  704. DSPregs[DEST_REG].upper.f);
  705. break;
  706. case 5: /* cfaddd */
  707. mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
  708. + mv_getRegDouble (SRC2_REG));
  709. printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
  710. DEST_REG,
  711. SRC1_REG, SRC2_REG,
  712. mv_getRegDouble (DEST_REG));
  713. break;
  714. case 6: /* cfsubs */
  715. DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
  716. - DSPregs[SRC2_REG].upper.f;
  717. printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
  718. DEST_REG, SRC1_REG, SRC2_REG,
  719. DSPregs[DEST_REG].upper.f);
  720. break;
  721. case 7: /* cfsubd */
  722. mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)
  723. - mv_getRegDouble (SRC2_REG));
  724. printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
  725. DEST_REG,
  726. SRC1_REG, SRC2_REG,
  727. mv_getRegDouble (DEST_REG));
  728. break;
  729. }
  730. break;
  731. default:
  732. fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
  733. cirrus_not_implemented ("unknown");
  734. break;
  735. }
  736. return ARMul_DONE;
  737. }
  738. unsigned
  739. DSPCDP5 (ARMul_State * state, unsigned type, ARMword instr)
  740. {
  741. int opcode2;
  742. char shift;
  743. opcode2 = BITS (5, 7);
  744. /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */
  745. shift = BITS (0, 3) | (BITS (5, 7)) << 4;
  746. if (shift & 0x40)
  747. shift |= 0xc0;
  748. switch (BITS (20, 21)) {
  749. case 0:
  750. /* cfsh32 */
  751. printfdbg ("cfsh32 %s amount=%d\n",
  752. shift < 0 ? "right" : "left", shift);
  753. if (shift < 0)
  754. /* Negative shift is a right shift. */
  755. DSPregs[DEST_REG].lower.i =
  756. DSPregs[SRC1_REG].lower.i >> -shift;
  757. else
  758. /* Positive shift is a left shift. */
  759. DSPregs[DEST_REG].lower.i =
  760. DSPregs[SRC1_REG].lower.i << shift;
  761. break;
  762. case 1:
  763. switch (opcode2) {
  764. case 0: /* cfmul32 */
  765. DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
  766. * DSPregs[SRC2_REG].lower.i;
  767. printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
  768. DEST_REG, SRC1_REG, SRC2_REG,
  769. DSPregs[DEST_REG].lower.i);
  770. break;
  771. case 1: /* cfmul64 */
  772. mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
  773. * mv_getReg64int (SRC2_REG));
  774. printfdbg
  775. ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
  776. DEST_REG, SRC1_REG, SRC2_REG,
  777. mv_getReg64int (DEST_REG));
  778. break;
  779. case 2: /* cfmac32 */
  780. DSPregs[DEST_REG].lower.i
  781. +=
  782. DSPregs[SRC1_REG].lower.i *
  783. DSPregs[SRC2_REG].lower.i;
  784. printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
  785. DEST_REG, SRC1_REG, SRC2_REG,
  786. DSPregs[DEST_REG].lower.i);
  787. break;
  788. case 3: /* cfmsc32 */
  789. DSPregs[DEST_REG].lower.i
  790. -=
  791. DSPregs[SRC1_REG].lower.i *
  792. DSPregs[SRC2_REG].lower.i;
  793. printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
  794. DEST_REG, SRC1_REG, SRC2_REG,
  795. DSPregs[DEST_REG].lower.i);
  796. break;
  797. case 4: /* cfcvts32 */
  798. /* fixme: this should round */
  799. DSPregs[DEST_REG].lower.i =
  800. (int) DSPregs[SRC1_REG].upper.f;
  801. printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n", DEST_REG,
  802. SRC1_REG, DSPregs[DEST_REG].lower.i);
  803. break;
  804. case 5: /* cfcvtd32 */
  805. /* fixme: this should round */
  806. DSPregs[DEST_REG].lower.i =
  807. (int) mv_getRegDouble (SRC1_REG);
  808. printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n", DEST_REG,
  809. SRC1_REG, DSPregs[DEST_REG].lower.i);
  810. break;
  811. case 6: /* cftruncs32 */
  812. DSPregs[DEST_REG].lower.i =
  813. (int) DSPregs[SRC1_REG].upper.f;
  814. printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
  815. DEST_REG, SRC1_REG,
  816. DSPregs[DEST_REG].lower.i);
  817. break;
  818. case 7: /* cftruncd32 */
  819. DSPregs[DEST_REG].lower.i =
  820. (int) mv_getRegDouble (SRC1_REG);
  821. printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
  822. DEST_REG, SRC1_REG,
  823. DSPregs[DEST_REG].lower.i);
  824. break;
  825. }
  826. break;
  827. case 2:
  828. /* cfsh64 */
  829. printfdbg ("cfsh64\n");
  830. if (shift < 0)
  831. /* Negative shift is a right shift. */
  832. mv_setReg64int (DEST_REG,
  833. mv_getReg64int (SRC1_REG) >> -shift);
  834. else
  835. /* Positive shift is a left shift. */
  836. mv_setReg64int (DEST_REG,
  837. mv_getReg64int (SRC1_REG) << shift);
  838. printfdbg ("\t%llx\n", mv_getReg64int (DEST_REG));
  839. break;
  840. case 3:
  841. switch (opcode2) {
  842. case 0: /* cfabs32 */
  843. DSPregs[DEST_REG].lower.i =
  844. (DSPregs[SRC1_REG].lower.i <
  845. 0 ? -DSPregs[SRC1_REG].lower.
  846. i : DSPregs[SRC1_REG].lower.i);
  847. printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
  848. DEST_REG, SRC1_REG, SRC2_REG,
  849. DSPregs[DEST_REG].lower.i);
  850. break;
  851. case 1: /* cfabs64 */
  852. mv_setReg64int (DEST_REG,
  853. (mv_getReg64int (SRC1_REG) < 0
  854. ? -mv_getReg64int (SRC1_REG)
  855. : mv_getReg64int (SRC1_REG)));
  856. printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
  857. DEST_REG, SRC1_REG, SRC2_REG,
  858. mv_getReg64int (DEST_REG));
  859. break;
  860. case 2: /* cfneg32 */
  861. DSPregs[DEST_REG].lower.i =
  862. -DSPregs[SRC1_REG].lower.i;
  863. printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
  864. DEST_REG, SRC1_REG, SRC2_REG,
  865. DSPregs[DEST_REG].lower.i);
  866. break;
  867. case 3: /* cfneg64 */
  868. mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
  869. printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
  870. DEST_REG, SRC1_REG, SRC2_REG,
  871. mv_getReg64int (DEST_REG));
  872. break;
  873. case 4: /* cfadd32 */
  874. DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
  875. + DSPregs[SRC2_REG].lower.i;
  876. printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
  877. DEST_REG, SRC1_REG, SRC2_REG,
  878. DSPregs[DEST_REG].lower.i);
  879. break;
  880. case 5: /* cfadd64 */
  881. mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
  882. + mv_getReg64int (SRC2_REG));
  883. printfdbg
  884. ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
  885. DEST_REG, SRC1_REG, SRC2_REG,
  886. mv_getReg64int (DEST_REG));
  887. break;
  888. case 6: /* cfsub32 */
  889. DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
  890. - DSPregs[SRC2_REG].lower.i;
  891. printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
  892. DEST_REG, SRC1_REG, SRC2_REG,
  893. DSPregs[DEST_REG].lower.i);
  894. break;
  895. case 7: /* cfsub64 */
  896. mv_setReg64int (DEST_REG, mv_getReg64int (SRC1_REG)
  897. - mv_getReg64int (SRC2_REG));
  898. printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
  899. DEST_REG, SRC1_REG, SRC2_REG,
  900. mv_getReg64int (DEST_REG));
  901. break;
  902. }
  903. break;
  904. default:
  905. fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
  906. cirrus_not_implemented ("unknown");
  907. break;
  908. }
  909. return ARMul_DONE;
  910. }
  911. unsigned
  912. DSPCDP6 (ARMul_State * state, unsigned type, ARMword instr)
  913. {
  914. int opcode2;
  915. opcode2 = BITS (5, 7);
  916. switch (BITS (20, 21)) {
  917. case 0:
  918. /* cfmadd32 */
  919. cirrus_not_implemented ("cfmadd32");
  920. break;
  921. case 1:
  922. /* cfmsub32 */
  923. cirrus_not_implemented ("cfmsub32");
  924. break;
  925. case 2:
  926. /* cfmadda32 */
  927. cirrus_not_implemented ("cfmadda32");
  928. break;
  929. case 3:
  930. /* cfmsuba32 */
  931. cirrus_not_implemented ("cfmsuba32");
  932. break;
  933. default:
  934. fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
  935. }
  936. return ARMul_DONE;
  937. }
  938. /* Conversion functions.
  939. 32-bit integers are stored in the LOWER half of a 64-bit physical
  940. register.
  941. Single precision floats are stored in the UPPER half of a 64-bit
  942. physical register. */
  943. static double
  944. mv_getRegDouble (int regnum)
  945. {
  946. reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
  947. reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
  948. return reg_conv.d;
  949. }
  950. static void
  951. mv_setRegDouble (int regnum, double val)
  952. {
  953. reg_conv.d = val;
  954. DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
  955. DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
  956. }
  957. static long long
  958. mv_getReg64int (int regnum)
  959. {
  960. reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
  961. reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
  962. return reg_conv.ll;
  963. }
  964. static void
  965. mv_setReg64int (int regnum, long long val)
  966. {
  967. reg_conv.ll = val;
  968. DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
  969. DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
  970. }
  971. /* Compute LSW in a double and a long long. */
  972. void
  973. mv_compute_host_endianness (ARMul_State * state)
  974. {
  975. static union
  976. {
  977. long long ll;
  978. int ints[2];
  979. int i;
  980. double d;
  981. float floats[2];
  982. float f;
  983. } conv;
  984. /* Calculate where's the LSW in a 64bit int. */
  985. conv.ll = 45;
  986. if (conv.ints[0] == 0) {
  987. msw_int_index = 0;
  988. lsw_int_index = 1;
  989. }
  990. else {
  991. assert (conv.ints[1] == 0);
  992. msw_int_index = 1;
  993. lsw_int_index = 0;
  994. }
  995. /* Calculate where's the LSW in a double. */
  996. conv.d = 3.0;
  997. if (conv.ints[0] == 0) {
  998. msw_float_index = 0;
  999. lsw_float_index = 1;
  1000. }
  1001. else {
  1002. assert (conv.ints[1] == 0);
  1003. msw_float_index = 1;
  1004. lsw_float_index = 0;
  1005. }
  1006. printfdbg ("lsw_int_index %d\n", lsw_int_index);
  1007. printfdbg ("lsw_float_index %d\n", lsw_float_index);
  1008. }