asmout.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  1. #include "l.h"
  2. #define OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1))
  3. #define OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc))
  4. #define OP(o,xo) OPVCC((o),(xo),0,0)
  5. /* the order is dest, a/s, b/imm for both arithmetic and logical operations */
  6. #define AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
  7. #define AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF))
  8. #define LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
  9. #define LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF))
  10. #define OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1))
  11. #define OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1))
  12. #define OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16))
  13. #define OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\
  14. (((mb)&31L)<<6)|(((me)&31L)<<1))
  15. #define OP_ADD OPVCC(31,266,0,0)
  16. #define OP_ADDI OPVCC(14,0,0,0)
  17. #define OP_ADDIS OPVCC(15,0,0,0)
  18. #define OP_ANDI OPVCC(28,0,0,0)
  19. #define OP_EXTSB OPVCC(31,954,0,0)
  20. #define OP_EXTSH OPVCC(31,922,0,0)
  21. #define OP_MCRF OPVCC(19,0,0,0)
  22. #define OP_MCRFS OPVCC(63,64,0,0)
  23. #define OP_MCRXR OPVCC(31,512,0,0)
  24. #define OP_MFCR OPVCC(31,19,0,0)
  25. #define OP_MFFS OPVCC(63,583,0,0)
  26. #define OP_MFMSR OPVCC(31,83,0,0)
  27. #define OP_MFSPR OPVCC(31,339,0,0)
  28. #define OP_MFSR OPVCC(31,595,0,0)
  29. #define OP_MFSRIN OPVCC(31,659,0,0)
  30. #define OP_MTCRF OPVCC(31,144,0,0)
  31. #define OP_MTFSF OPVCC(63,711,0,0)
  32. #define OP_MTFSFI OPVCC(63,134,0,0)
  33. #define OP_MTMSR OPVCC(31,146,0,0)
  34. #define OP_MTSPR OPVCC(31,467,0,0)
  35. #define OP_MTSR OPVCC(31,210,0,0)
  36. #define OP_MTSRIN OPVCC(31,242,0,0)
  37. #define OP_MULLW OPVCC(31,235,0,0)
  38. #define OP_OR OPVCC(31,444,0,0)
  39. #define OP_ORI OPVCC(24,0,0,0)
  40. #define OP_RLWINM OPVCC(21,0,0,0)
  41. #define OP_SUBF OPVCC(31,40,0,0)
  42. #define oclass(v) ((v).class-1)
  43. long oprrr(int), opirr(int), opload(int), opstore(int), oploadx(int), opstorex(int);
  44. int
  45. getmask(uchar *m, ulong v)
  46. {
  47. int i;
  48. m[0] = m[1] = 0;
  49. if(v != ~0L && v & (1<<31) && v & 1){ /* MB > ME */
  50. if(getmask(m, ~v)){
  51. i = m[0]; m[0] = m[1]+1; m[1] = i-1;
  52. return 1;
  53. }
  54. return 0;
  55. }
  56. for(i=0; i<32; i++)
  57. if(v & (1<<(31-i))){
  58. m[0] = i;
  59. do {
  60. m[1] = i;
  61. } while(++i<32 && (v & (1<<(31-i))) != 0);
  62. for(; i<32; i++)
  63. if(v & (1<<(31-i)))
  64. return 0;
  65. return 1;
  66. }
  67. return 0;
  68. }
  69. void
  70. maskgen(Prog *p, uchar *m, ulong v)
  71. {
  72. if(!getmask(m, v))
  73. diag("cannot generate mask #%lux\n%P", v, p);
  74. }
  75. int
  76. asmout(Prog *p, Optab *o, int aflag)
  77. {
  78. long o1, o2, o3, o4, o5, v;
  79. Prog *ct;
  80. int r, a;
  81. uchar mask[2];
  82. o1 = 0;
  83. o2 = 0;
  84. o3 = 0;
  85. o4 = 0;
  86. o5 = 0;
  87. switch(o->type) {
  88. default:
  89. if(aflag)
  90. return 0;
  91. diag("unknown type %d\n", o->type);
  92. if(!debug['a'])
  93. prasm(p);
  94. break;
  95. case 0: /* pseudo ops */
  96. if(aflag) {
  97. if(p->link) {
  98. if(p->as == ATEXT) {
  99. ct = curtext;
  100. o2 = autosize;
  101. curtext = p;
  102. autosize = p->to.offset + 4;
  103. o1 = asmout(p->link, oplook(p->link), aflag);
  104. curtext = ct;
  105. autosize = o2;
  106. } else
  107. o1 = asmout(p->link, oplook(p->link), aflag);
  108. }
  109. return o1;
  110. }
  111. break;
  112. case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */
  113. o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg);
  114. break;
  115. case 2: /* int/cr/fp op Rb,[Ra],Rd */
  116. r = p->reg;
  117. if(r == NREG)
  118. r = p->to.reg;
  119. o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);
  120. break;
  121. case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
  122. v = regoff(&p->from);
  123. r = p->from.reg;
  124. if(r == NREG)
  125. r = o->param;
  126. a = OP_ADDI;
  127. if(o->a1 == C_UCON) {
  128. a = OP_ADDIS;
  129. v >>= 16;
  130. }
  131. o1 = AOP_IRR(a, p->to.reg, r, v);
  132. break;
  133. case 4: /* add/mul $scon,[r1],r2 */
  134. v = regoff(&p->from);
  135. r = p->reg;
  136. if(r == NREG)
  137. r = p->to.reg;
  138. else if(p->as == AADD && r == 0)
  139. diag("literal operation on R0\n%P", p);
  140. o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v);
  141. break;
  142. case 5: /* syscall */
  143. if(aflag)
  144. return 0;
  145. o1 = oprrr(p->as);
  146. break;
  147. case 6: /* logical op Rb,[Rs,]Ra; no literal */
  148. r = p->reg;
  149. if(r == NREG)
  150. r = p->to.reg;
  151. o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);
  152. break;
  153. case 7: /* mov r, soreg ==> stw o(r) */
  154. r = p->to.reg;
  155. if(r == NREG)
  156. r = o->param;
  157. v = regoff(&p->to);
  158. if(p->to.type == D_OREG && p->reg != NREG) {
  159. if(v)
  160. diag("illegal indexed instruction\n%P", p);
  161. o1 = AOP_RRR(opstorex(p->as), p->from.reg, p->reg, r);
  162. } else
  163. o1 = AOP_IRR(opstore(p->as), p->from.reg, r, v);
  164. break;
  165. case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
  166. r = p->from.reg;
  167. if(r == NREG)
  168. r = o->param;
  169. v = regoff(&p->from);
  170. if(p->from.type == D_OREG && p->reg != NREG) {
  171. if(v)
  172. diag("illegal indexed instruction\n%P", p);
  173. o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r);
  174. } else
  175. o1 = AOP_IRR(opload(p->as), p->to.reg, r, v);
  176. break;
  177. case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
  178. r = p->from.reg;
  179. if(r == NREG)
  180. r = o->param;
  181. v = regoff(&p->from);
  182. if(p->from.type == D_OREG && p->reg != NREG) {
  183. if(v)
  184. diag("illegal indexed instruction\n%P", p);
  185. o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r);
  186. } else
  187. o1 = AOP_IRR(opload(p->as), p->to.reg, r, v);
  188. o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
  189. break;
  190. case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
  191. r = p->reg;
  192. if(r == NREG)
  193. r = p->to.reg;
  194. o1 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, r);
  195. break;
  196. case 11: /* br/bl lbra */
  197. if(aflag)
  198. return 0;
  199. v = 0;
  200. if(p->cond)
  201. v = p->cond->pc - p->pc;
  202. if(v & 03) {
  203. diag("odd branch target address\n%P", p);
  204. v &= ~03;
  205. }
  206. if(v < -(1L<<25) || v >= (1L<<25))
  207. diag("branch too far\n%P", p);
  208. o1 = OP_BR(opirr(p->as), v, 0);
  209. break;
  210. case 12: /* movb r,r (signed); extsb is on PowerPC but not POWER */
  211. o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0);
  212. break;
  213. case 13: /* mov[bh]z r,r; uses rlwinm not andi. to avoid changing CC */
  214. if(p->as == AMOVBZ)
  215. o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31);
  216. else if(p->as == AMOVH)
  217. o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0);
  218. else if(p->as == AMOVHZ)
  219. o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31);
  220. else
  221. diag("internal: bad mov[bh]z\n%P", p);
  222. break;
  223. /*14 */
  224. case 17: /* bc bo,bi,lbra (same for now) */
  225. case 16: /* bc bo,bi,sbra */
  226. if(aflag)
  227. return 0;
  228. a = 0;
  229. if(p->from.type == D_CONST)
  230. a = regoff(&p->from);
  231. r = p->reg;
  232. if(r == NREG)
  233. r = 0;
  234. v = 0;
  235. if(p->cond)
  236. v = p->cond->pc - p->pc;
  237. if(v & 03) {
  238. diag("odd branch target address\n%P", p);
  239. v &= ~03;
  240. }
  241. if(v < -(1L<<16) || v >= (1L<<16))
  242. diag("branch too far\n%P", p);
  243. o1 = OP_BC(opirr(p->as), a, r, v, 0);
  244. break;
  245. case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */
  246. if(aflag)
  247. return 0;
  248. if(p->as == ABC || p->as == ABCL)
  249. v = regoff(&p->to)&31L;
  250. else
  251. v = 20; /* unconditional */
  252. r = p->reg;
  253. if(r == NREG)
  254. r = 0;
  255. o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);
  256. o2 = OPVCC(19, 16, 0, 0);
  257. if(p->as == ABL || p->as == ABCL)
  258. o2 |= 1;
  259. o2 = OP_BCR(o2, v, r);
  260. break;
  261. case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
  262. if(aflag)
  263. return 0;
  264. if(p->as == ABC || p->as == ABCL)
  265. v = regoff(&p->from)&31L;
  266. else
  267. v = 20; /* unconditional */
  268. r = p->reg;
  269. if(r == NREG)
  270. r = 0;
  271. switch(oclass(p->to)) {
  272. case C_CTR:
  273. o1 = OPVCC(19, 528, 0, 0);
  274. break;
  275. case C_LR:
  276. o1 = OPVCC(19, 16, 0, 0);
  277. break;
  278. default:
  279. diag("bad optab entry (18): %d\n%P", p->to.class, p);
  280. v = 0;
  281. }
  282. if(p->as == ABL || p->as == ABCL)
  283. o1 |= 1;
  284. o1 = OP_BCR(o1, v, r);
  285. break;
  286. case 19: /* mov $lcon,r ==> cau+or */
  287. v = regoff(&p->from);
  288. o1 = AOP_IRR(OP_ADDIS, p->to.reg, REGZERO, v>>16);
  289. o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, v);
  290. break;
  291. case 20: /* add $ucon,,r */
  292. v = regoff(&p->from);
  293. r = p->reg;
  294. if(r == NREG)
  295. r = p->to.reg;
  296. if(p->as == AADD && r == 0)
  297. diag("literal operation on R0\n%P", p);
  298. o1 = AOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16);
  299. break;
  300. case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */
  301. v = regoff(&p->from);
  302. if(p->to.reg == REGTMP || p->reg == REGTMP)
  303. diag("cant synthesize large constant\n%P\n", p);
  304. o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
  305. o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
  306. r = p->reg;
  307. if(r == NREG)
  308. r = p->to.reg;
  309. o3 = AOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r);
  310. break;
  311. case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */
  312. v = regoff(&p->from);
  313. if(p->to.reg == REGTMP || p->reg == REGTMP)
  314. diag("cant synthesize large constant\n%P\n", p);
  315. o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
  316. o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
  317. r = p->reg;
  318. if(r == NREG)
  319. r = p->to.reg;
  320. o3 = LOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r);
  321. break;
  322. /*24*/
  323. case 26: /* mov $lsext/auto/oreg,,r2 ==> cau+add */
  324. v = regoff(&p->from);
  325. if(v & 0x8000L)
  326. v += 0x10000L;
  327. if(p->to.reg == REGTMP)
  328. diag("can't synthesize large constant\n%P\n", p);
  329. r = p->from.reg;
  330. if(r == NREG)
  331. r = o->param;
  332. o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
  333. o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v);
  334. break;
  335. case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
  336. v = regoff(&p->from3);
  337. r = p->from.reg;
  338. o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v);
  339. break;
  340. case 28: /* subc r1,$lcon,r2 ==> cau+or+subfc */
  341. v = regoff(&p->from3);
  342. if(p->to.reg == REGTMP || p->from.reg == REGTMP)
  343. diag("can't synthesize large constant\n%P\n", p);
  344. o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
  345. o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
  346. o3 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, REGTMP);
  347. break;
  348. /*29, 30, 31 */
  349. case 32: /* fmul frc,fra,frd */
  350. r = p->reg;
  351. if(r == NREG)
  352. r = p->to.reg;
  353. o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6);
  354. break;
  355. case 33: /* fabs [frb,]frd; fmr. frb,frd */
  356. r = p->from.reg;
  357. if(oclass(p->from) == C_NONE)
  358. r = p->to.reg;
  359. o1 = AOP_RRR(oprrr(p->as), p->to.reg, 0, r);
  360. break;
  361. case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c) */
  362. o1 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, p->reg)|((p->from3.reg&31L)<<6);
  363. break;
  364. case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
  365. v = regoff(&p->to);
  366. if(v & 0x8000L)
  367. v += 0x10000L;
  368. r = p->to.reg;
  369. if(r == NREG)
  370. r = o->param;
  371. o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
  372. o2 = AOP_IRR(opstore(p->as), p->from.reg, REGTMP, v);
  373. break;
  374. case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
  375. v = regoff(&p->from);
  376. if(v & 0x8000L)
  377. v += 0x10000L;
  378. r = p->from.reg;
  379. if(r == NREG)
  380. r = o->param;
  381. o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
  382. o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v);
  383. break;
  384. case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
  385. v = regoff(&p->from);
  386. if(v & 0x8000L)
  387. v += 0x10000L;
  388. r = p->from.reg;
  389. if(r == NREG)
  390. r = o->param;
  391. o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
  392. o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v);
  393. o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
  394. break;
  395. case 40: /* word */
  396. if(aflag)
  397. return 0;
  398. o1 = regoff(&p->from);
  399. break;
  400. case 41: /* stswi */
  401. o1 = AOP_RRR(opirr(p->as), p->from.reg, p->to.reg, 0) | ((regoff(&p->from3)&0x7F)<<11);
  402. break;
  403. case 42: /* lswi */
  404. o1 = AOP_RRR(opirr(p->as), p->to.reg, p->from.reg, 0) | ((regoff(&p->from3)&0x7F)<<11);
  405. break;
  406. case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
  407. r = p->reg;
  408. if(r == NREG)
  409. r = 0;
  410. o1 = AOP_RRR(oprrr(p->as), 0, r, p->from.reg);
  411. break;
  412. case 44: /* indexed store */
  413. r = p->reg;
  414. if(r == NREG)
  415. r = 0;
  416. o1 = AOP_RRR(opstorex(p->as), p->from.reg, r, p->to.reg);
  417. break;
  418. case 45: /* indexed load */
  419. r = p->reg;
  420. if(r == NREG)
  421. r = 0;
  422. o1 = AOP_RRR(oploadx(p->as), p->to.reg, r, p->from.reg);
  423. break;
  424. case 46: /* plain op */
  425. o1 = oprrr(p->as);
  426. break;
  427. case 47: /* op Ra, Rd; also op [Ra,] Rd */
  428. r = p->from.reg;
  429. if(r == NREG)
  430. r = p->to.reg;
  431. o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, 0);
  432. break;
  433. case 48: /* op Rs, Ra */
  434. r = p->from.reg;
  435. if(r == NREG)
  436. r = p->to.reg;
  437. o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, 0);
  438. break;
  439. case 49: /* op Rb */
  440. o1 = AOP_RRR(oprrr(p->as), 0, 0, p->from.reg);
  441. break;
  442. /*50*/
  443. case 51: /* rem[u] r1[,r2],r3 */
  444. r = p->reg;
  445. if(r == NREG)
  446. r = p->to.reg;
  447. o1 = AOP_RRR(oprrr(p->as), REGTMP, r, p->from.reg);
  448. o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
  449. o3 = AOP_RRR(OP_SUBF, p->to.reg, REGTMP, r); /* BUG: check V, CC */
  450. break;
  451. case 52: /* mtfsbNx cr(n) */
  452. v = regoff(&p->from)&31L;
  453. o1 = AOP_RRR(oprrr(p->as), v, 0, 0);
  454. break;
  455. case 53: /* mffsX ,fr1 */
  456. o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0);
  457. break;
  458. case 54: /* mov msr,r1; mov r1, msr*/
  459. if(oclass(p->from) == C_REG)
  460. o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0);
  461. else
  462. o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0);
  463. break;
  464. case 55: /* mov sreg,r1; mov r1,sreg */
  465. v = 0;
  466. if(p->from.type == D_SREG) {
  467. r = p->from.reg;
  468. o1 = OP_MFSR;
  469. if(r == NREG && p->reg != NREG) {
  470. r = 0;
  471. v = p->reg;
  472. o1 = OP_MFSRIN;
  473. }
  474. o1 = AOP_RRR(o1, p->to.reg, r&15L, v);
  475. } else {
  476. r = p->to.reg;
  477. o1 = OP_MTSR;
  478. if(r == NREG && p->reg != NREG) {
  479. r = 0;
  480. v = p->reg;
  481. o1 = OP_MTSRIN;
  482. }
  483. o1 = AOP_RRR(o1, p->from.reg, r&15L, v);
  484. }
  485. if(r == NREG)
  486. diag("illegal move indirect to/from segment register\n%P", p);
  487. break;
  488. case 56: /* sra $sh,[s,]a */
  489. v = regoff(&p->from);
  490. r = p->reg;
  491. if(r == NREG)
  492. r = p->to.reg;
  493. o1 = AOP_RRR(opirr(p->as), r, p->to.reg, v&31L);
  494. break;
  495. case 57: /* slw $sh,[s,]a -> rlwinm ... */
  496. v = regoff(&p->from);
  497. r = p->reg;
  498. if(r == NREG)
  499. r = p->to.reg;
  500. if(v < 0 || v > 31)
  501. diag("illegal shift %ld\n%P", v, p);
  502. if(v < 0)
  503. v = 0;
  504. else if(v > 32)
  505. v = 32;
  506. if(p->as == ASRW || p->as == ASRWCC) { /* shift right */
  507. mask[0] = v;
  508. mask[1] = 31;
  509. v = 32-v;
  510. } else {
  511. mask[0] = 0;
  512. mask[1] = 31-v;
  513. }
  514. o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]);
  515. if(p->as == ASLWCC || p->as == ASRWCC)
  516. o1 |= 1; /* Rc */
  517. break;
  518. case 58: /* logical $andcon,[s],a */
  519. v = regoff(&p->from);
  520. r = p->reg;
  521. if(r == NREG)
  522. r = p->to.reg;
  523. o1 = LOP_IRR(opirr(p->as), p->to.reg, r, v);
  524. break;
  525. case 59: /* or/and $ucon,,r */
  526. v = regoff(&p->from);
  527. r = p->reg;
  528. if(r == NREG)
  529. r = p->to.reg;
  530. o1 = LOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16); /* oris, xoris, andis */
  531. break;
  532. case 60: /* tw to,a,b */
  533. r = regoff(&p->from)&31L;
  534. o1 = AOP_RRR(oprrr(p->as), r, p->reg, p->to.reg);
  535. break;
  536. case 61: /* tw to,a,$simm */
  537. r = regoff(&p->from)&31L;
  538. v = regoff(&p->to);
  539. o1 = AOP_IRR(opirr(p->as), r, p->reg, v);
  540. break;
  541. case 62: /* rlwmi $sh,s,$mask,a */
  542. v = regoff(&p->from);
  543. maskgen(p, mask, regoff(&p->from3));
  544. o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, v);
  545. o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
  546. break;
  547. case 63: /* rlwmi b,s,$mask,a */
  548. maskgen(p, mask, regoff(&p->from3));
  549. o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, p->from.reg);
  550. o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
  551. break;
  552. case 64: /* mtfsf fr[, $m] {,fpcsr} */
  553. if(p->from3.type != D_NONE)
  554. v = regoff(&p->from3)&255L;
  555. else
  556. v = 255;
  557. o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11);
  558. break;
  559. case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
  560. if(p->to.reg == NREG)
  561. diag("must specify FPSCR(n)\n%P", p);
  562. o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(&p->from)&31L)<<12);
  563. break;
  564. case 66: /* mov spr,r1; mov r1,spr */
  565. if(p->from.type == D_REG) {
  566. r = p->from.reg;
  567. v = p->to.offset;
  568. o1 = OPVCC(31,467,0,0); /* mtspr */
  569. } else {
  570. r = p->to.reg;
  571. v = p->from.offset;
  572. o1 = OPVCC(31,339,0,0); /* mfspr */
  573. }
  574. o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11);
  575. break;
  576. case 67: /* mcrf crfD,crfS */
  577. if(p->from.type != D_CREG || p->from.reg == NREG ||
  578. p->to.type != D_CREG || p->to.reg == NREG)
  579. diag("illegal CR field number\n%P", p);
  580. o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
  581. break;
  582. case 68: /* mfcr rD */
  583. if(p->from.type == D_CREG && p->from.reg != NREG)
  584. diag("must move whole CR to register\n%P", p);
  585. o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0);
  586. break;
  587. case 69: /* mtcrf CRM,rS */
  588. if(p->from3.type != D_NONE) {
  589. if(p->to.reg != NREG)
  590. diag("can't use both mask and CR(n)\n%P", p);
  591. v = regoff(&p->from3) & 0xff;
  592. } else {
  593. if(p->to.reg == NREG)
  594. v = 0xff; /* CR */
  595. else
  596. v = 1<<(7-(p->to.reg&7)); /* CR(n) */
  597. }
  598. o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12);
  599. break;
  600. case 70: /* [f]cmp r,r,cr*/
  601. if(p->reg == NREG)
  602. r = 0;
  603. else
  604. r = (p->reg&7)<<2;
  605. o1 = AOP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg);
  606. break;
  607. case 71: /* cmp[l] r,i,cr*/
  608. if(p->reg == NREG)
  609. r = 0;
  610. else
  611. r = (p->reg&7)<<2;
  612. o1 = AOP_RRR(opirr(p->as), r, p->from.reg, 0) | (regoff(&p->to)&0xffff);
  613. break;
  614. case 72: /* mcrxr crfD */
  615. if(p->to.reg == NREG)
  616. diag("must move XER to CR(n)\n%P", p);
  617. o1 = AOP_RRR(OP_MCRXR, ((p->to.reg&7L)<<2), 0, 0);
  618. break;
  619. case 73: /* mcrfs crfD,crfS */
  620. if(p->from.type != D_FPSCR || p->from.reg == NREG ||
  621. p->to.type != D_CREG || p->to.reg == NREG)
  622. diag("illegal FPSCR/CR field number\n%P", p);
  623. o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
  624. break;
  625. }
  626. if(aflag)
  627. return o1;
  628. v = p->pc;
  629. switch(o->size) {
  630. default:
  631. if(debug['a'])
  632. Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
  633. break;
  634. case 4:
  635. if(debug['a'])
  636. Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
  637. lput(o1);
  638. break;
  639. case 8:
  640. if(debug['a'])
  641. Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
  642. lput(o1);
  643. lput(o2);
  644. break;
  645. case 12:
  646. if(debug['a'])
  647. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
  648. lput(o1);
  649. lput(o2);
  650. lput(o3);
  651. break;
  652. case 16:
  653. if(debug['a'])
  654. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
  655. v, o1, o2, o3, o4, p);
  656. lput(o1);
  657. lput(o2);
  658. lput(o3);
  659. lput(o4);
  660. break;
  661. case 20:
  662. if(debug['a'])
  663. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
  664. v, o1, o2, o3, o4, o5, p);
  665. lput(o1);
  666. lput(o2);
  667. lput(o3);
  668. lput(o4);
  669. lput(o5);
  670. break;
  671. }
  672. return 0;
  673. }
  674. long
  675. oprrr(int a)
  676. {
  677. switch(a) {
  678. case AADD: return OPVCC(31,266,0,0);
  679. case AADDCC: return OPVCC(31,266,0,1);
  680. case AADDV: return OPVCC(31,266,1,0);
  681. case AADDVCC: return OPVCC(31,266,1,1);
  682. case AADDC: return OPVCC(31,10,0,0);
  683. case AADDCCC: return OPVCC(31,10,0,1);
  684. case AADDCV: return OPVCC(31,10,1,0);
  685. case AADDCVCC: return OPVCC(31,10,1,1);
  686. case AADDE: return OPVCC(31,138,0,0);
  687. case AADDECC: return OPVCC(31,138,0,1);
  688. case AADDEV: return OPVCC(31,138,1,0);
  689. case AADDEVCC: return OPVCC(31,138,1,1);
  690. case AADDME: return OPVCC(31,234,0,0);
  691. case AADDMECC: return OPVCC(31,234,0,1);
  692. case AADDMEV: return OPVCC(31,234,1,0);
  693. case AADDMEVCC: return OPVCC(31,234,1,1);
  694. case AADDZE: return OPVCC(31,202,0,0);
  695. case AADDZECC: return OPVCC(31,202,0,1);
  696. case AADDZEV: return OPVCC(31,202,1,0);
  697. case AADDZEVCC: return OPVCC(31,202,1,1);
  698. case AAND: return OPVCC(31,28,0,0);
  699. case AANDCC: return OPVCC(31,28,0,1);
  700. case AANDN: return OPVCC(31,60,0,0);
  701. case AANDNCC: return OPVCC(31,60,0,1);
  702. case ACMP: return OPVCC(31,0,0,0);
  703. case ACMPU: return OPVCC(31,32,0,0);
  704. case ACNTLZW: return OPVCC(31,26,0,0);
  705. case ACNTLZWCC: return OPVCC(31,26,0,1);
  706. case ACRAND: return OPVCC(19,257,0,0);
  707. case ACRANDN: return OPVCC(19,129,0,0);
  708. case ACREQV: return OPVCC(19,289,0,0);
  709. case ACRNAND: return OPVCC(19,225,0,0);
  710. case ACRNOR: return OPVCC(19,33,0,0);
  711. case ACROR: return OPVCC(19,449,0,0);
  712. case ACRORN: return OPVCC(19,417,0,0);
  713. case ACRXOR: return OPVCC(19,193,0,0);
  714. case ADCBF: return OPVCC(31,86,0,0);
  715. case ADCBI: return OPVCC(31,470,0,0);
  716. case ADCBST: return OPVCC(31,54,0,0);
  717. case ADCBT: return OPVCC(31,278,0,0);
  718. case ADCBTST: return OPVCC(31,246,0,0);
  719. case ADCBZ: return OPVCC(31,1014,0,0);
  720. case AREM:
  721. case ADIVW: return OPVCC(31,491,0,0);
  722. case AREMCC:
  723. case ADIVWCC: return OPVCC(31,491,0,1);
  724. case AREMV:
  725. case ADIVWV: return OPVCC(31,491,1,0);
  726. case AREMVCC:
  727. case ADIVWVCC: return OPVCC(31,491,1,1);
  728. case AREMU:
  729. case ADIVWU: return OPVCC(31,459,0,0);
  730. case AREMUCC:
  731. case ADIVWUCC: return OPVCC(31,459,0,1);
  732. case AREMUV:
  733. case ADIVWUV: return OPVCC(31,459,1,0);
  734. case AREMUVCC:
  735. case ADIVWUVCC: return OPVCC(31,459,1,1);
  736. case AEIEIO: return OPVCC(31,854,0,0);
  737. case AEQV: return OPVCC(31,284,0,0);
  738. case AEQVCC: return OPVCC(31,284,0,1);
  739. case AEXTSB: return OPVCC(31,954,0,0);
  740. case AEXTSBCC: return OPVCC(31,954,0,1);
  741. case AEXTSH: return OPVCC(31,922,0,0);
  742. case AEXTSHCC: return OPVCC(31,922,0,1);
  743. case AFABS: return OPVCC(63,264,0,0);
  744. case AFABSCC: return OPVCC(63,264,0,1);
  745. case AFADD: return OPVCC(63,21,0,0);
  746. case AFADDCC: return OPVCC(63,21,0,1);
  747. case AFADDS: return OPVCC(59,21,0,0);
  748. case AFADDSCC: return OPVCC(59,21,0,1);
  749. case AFCMPO: return OPVCC(63,32,0,0);
  750. case AFCMPU: return OPVCC(63,0,0,0);
  751. case AFCTIW: return OPVCC(63,14,0,0);
  752. case AFCTIWCC: return OPVCC(63,14,0,1);
  753. case AFCTIWZ: return OPVCC(63,15,0,0);
  754. case AFCTIWZCC: return OPVCC(63,15,0,1);
  755. case AFDIV: return OPVCC(63,18,0,0);
  756. case AFDIVCC: return OPVCC(63,18,0,1);
  757. case AFDIVS: return OPVCC(59,18,0,0);
  758. case AFDIVSCC: return OPVCC(59,18,0,1);
  759. case AFMADD: return OPVCC(63,29,0,0);
  760. case AFMADDCC: return OPVCC(63,29,0,1);
  761. case AFMADDS: return OPVCC(59,29,0,0);
  762. case AFMADDSCC: return OPVCC(59,29,0,1);
  763. case AFMOVS:
  764. case AFMOVD: return OPVCC(63,72,0,0); /* load */
  765. case AFMOVDCC: return OPVCC(63,72,0,1);
  766. case AFMSUB: return OPVCC(63,28,0,0);
  767. case AFMSUBCC: return OPVCC(63,28,0,1);
  768. case AFMSUBS: return OPVCC(59,28,0,0);
  769. case AFMSUBSCC: return OPVCC(59,28,0,1);
  770. case AFMUL: return OPVCC(63,25,0,0);
  771. case AFMULCC: return OPVCC(63,25,0,1);
  772. case AFMULS: return OPVCC(59,25,0,0);
  773. case AFMULSCC: return OPVCC(59,25,0,1);
  774. case AFNABS: return OPVCC(63,136,0,0);
  775. case AFNABSCC: return OPVCC(63,136,0,1);
  776. case AFNEG: return OPVCC(63,40,0,0);
  777. case AFNEGCC: return OPVCC(63,40,0,1);
  778. case AFNMADD: return OPVCC(63,31,0,0);
  779. case AFNMADDCC: return OPVCC(63,31,0,1);
  780. case AFNMADDS: return OPVCC(59,31,0,0);
  781. case AFNMADDSCC: return OPVCC(59,31,0,1);
  782. case AFNMSUB: return OPVCC(63,30,0,0);
  783. case AFNMSUBCC: return OPVCC(63,30,0,1);
  784. case AFNMSUBS: return OPVCC(59,30,0,0);
  785. case AFNMSUBSCC: return OPVCC(59,30,0,1);
  786. case AFRSP: return OPVCC(63,12,0,0);
  787. case AFRSPCC: return OPVCC(63,12,0,1);
  788. case AFSUB: return OPVCC(63,20,0,0);
  789. case AFSUBCC: return OPVCC(63,20,0,1);
  790. case AFSUBS: return OPVCC(59,20,0,0);
  791. case AFSUBSCC: return OPVCC(59,20,0,1);
  792. case AICBI: return OPVCC(31,982,0,0);
  793. case AISYNC: return OPVCC(19,150,0,0);
  794. /* lscb etc are not PowerPC instructions */
  795. case AMTFSB0: return OPVCC(63,70,0,0);
  796. case AMTFSB0CC: return OPVCC(63,70,0,1);
  797. case AMTFSB1: return OPVCC(63,38,0,0);
  798. case AMTFSB1CC: return OPVCC(63,38,0,1);
  799. case AMULHW: return OPVCC(31,75,0,0);
  800. case AMULHWCC: return OPVCC(31,75,0,1);
  801. case AMULHWU: return OPVCC(31,11,0,0);
  802. case AMULHWUCC: return OPVCC(31,11,0,1);
  803. case AMULLW: return OPVCC(31,235,0,0);
  804. case AMULLWCC: return OPVCC(31,235,0,1);
  805. case AMULLWV: return OPVCC(31,235,1,0);
  806. case AMULLWVCC: return OPVCC(31,235,1,1);
  807. case ANAND: return OPVCC(31,476,0,0);
  808. case ANANDCC: return OPVCC(31,476,0,1);
  809. case ANEG: return OPVCC(31,104,0,0);
  810. case ANEGCC: return OPVCC(31,104,0,1);
  811. case ANEGV: return OPVCC(31,104,1,0);
  812. case ANEGVCC: return OPVCC(31,104,1,1);
  813. case ANOR: return OPVCC(31,124,0,0);
  814. case ANORCC: return OPVCC(31,124,0,1);
  815. case AOR: return OPVCC(31,444,0,0);
  816. case AORCC: return OPVCC(31,444,0,1);
  817. case AORN: return OPVCC(31,412,0,0);
  818. case AORNCC: return OPVCC(31,412,0,1);
  819. case ARFI: return OPVCC(19,50,0,0);
  820. case ARLWMI: return OPVCC(20,0,0,0);
  821. case ARLWMICC: return OPVCC(20,0,0,1);
  822. case ARLWNM: return OPVCC(23,0,0,0);
  823. case ARLWNMCC: return OPVCC(23,0,0,1);
  824. case ASYSCALL: return OPVCC(17,1,0,0);
  825. case ASLW: return OPVCC(31,24,0,0);
  826. case ASLWCC: return OPVCC(31,24,0,1);
  827. case ASRAW: return OPVCC(31,792,0,0);
  828. case ASRAWCC: return OPVCC(31,792,0,1);
  829. case ASRW: return OPVCC(31,536,0,0);
  830. case ASRWCC: return OPVCC(31,536,0,1);
  831. case ASUB: return OPVCC(31,40,0,0);
  832. case ASUBCC: return OPVCC(31,40,0,1);
  833. case ASUBV: return OPVCC(31,40,1,0);
  834. case ASUBVCC: return OPVCC(31,40,1,1);
  835. case ASUBC: return OPVCC(31,8,0,0);
  836. case ASUBCCC: return OPVCC(31,8,0,1);
  837. case ASUBCV: return OPVCC(31,8,1,0);
  838. case ASUBCVCC: return OPVCC(31,8,1,1);
  839. case ASUBE: return OPVCC(31,136,0,0);
  840. case ASUBECC: return OPVCC(31,136,0,1);
  841. case ASUBEV: return OPVCC(31,136,1,0);
  842. case ASUBEVCC: return OPVCC(31,136,1,1);
  843. case ASUBME: return OPVCC(31,232,0,0);
  844. case ASUBMECC: return OPVCC(31,232,0,1);
  845. case ASUBMEV: return OPVCC(31,232,1,0);
  846. case ASUBMEVCC: return OPVCC(31,232,1,1);
  847. case ASUBZE: return OPVCC(31,200,0,0);
  848. case ASUBZECC: return OPVCC(31,200,0,1);
  849. case ASUBZEV: return OPVCC(31,200,1,0);
  850. case ASUBZEVCC: return OPVCC(31,200,1,1);
  851. case ASYNC: return OPVCC(31,598,0,0);
  852. case ATLBIE: return OPVCC(31,306,0,0);
  853. case ATW: return OPVCC(31,4,0,0);
  854. case AXOR: return OPVCC(31,316,0,0);
  855. }
  856. diag("bad r/r opcode %A\n", a);
  857. return 0;
  858. }
  859. long
  860. opirr(int a)
  861. {
  862. switch(a) {
  863. case AADD: return OPVCC(14,0,0,0);
  864. case AADDC: return OPVCC(12,0,0,0);
  865. case AADDCCC: return OPVCC(13,0,0,0);
  866. case AADD+AEND: return OPVCC(15,0,0,0); /* ADDIS/CAU */
  867. case AANDCC: return OPVCC(28,0,0,0);
  868. case AANDCC+AEND: return OPVCC(29,0,0,0); /* ANDIS./ANDIU. */
  869. case ABR: return OPVCC(18,0,0,0);
  870. case ABL: return OPVCC(18,0,0,0) | 1;
  871. case ABC: return OPVCC(16,0,0,0);
  872. case ABCL: return OPVCC(16,0,0,0) | 1;
  873. case ABEQ: return AOP_RRR(16<<26,12,2,0);
  874. case ABGE: return AOP_RRR(16<<26,4,0,0);
  875. case ABGT: return AOP_RRR(16<<26,12,1,0);
  876. case ABLE: return AOP_RRR(16<<26,4,1,0);
  877. case ABLT: return AOP_RRR(16<<26,12,0,0);
  878. case ABNE: return AOP_RRR(16<<26,4,2,0);
  879. case ABVC: return AOP_RRR(16<<26,4,3,0);
  880. case ABVS: return AOP_RRR(16<<26,12,3,0);
  881. case ACMP: return OPVCC(11,0,0,0);
  882. case ACMPU: return OPVCC(10,0,0,0);
  883. case ALSW: return OPVCC(31,597,0,0);
  884. case AMULLW: return OPVCC(7,0,0,0);
  885. case AOR: return OPVCC(24,0,0,0);
  886. case AOR+AEND: return OPVCC(25,0,0,0); /* ORIS/ORIU */
  887. case ARLWMI: return OPVCC(20,0,0,0); /* rlwimi */
  888. case ARLWMICC: return OPVCC(20,0,0,1);
  889. case ARLWNM: return OPVCC(21,0,0,0); /* rlwinm */
  890. case ARLWNMCC: return OPVCC(21,0,0,1);
  891. case ASRAW: return OPVCC(31,824,0,0);
  892. case ASRAWCC: return OPVCC(31,824,0,1);
  893. case ASTSW: return OPVCC(31,725,0,0);
  894. case ASUBC: return OPVCC(8,0,0,0);
  895. case ATW: return OPVCC(3,0,0,0);
  896. case AXOR: return OPVCC(26,0,0,0); /* XORIL */
  897. case AXOR+AEND: return OPVCC(27,0,0,0); /* XORIU */
  898. }
  899. diag("bad opcode i/r %A\n", a);
  900. return 0;
  901. }
  902. /*
  903. * load o(a),d
  904. */
  905. long
  906. opload(int a)
  907. {
  908. switch(a) {
  909. case AMOVW: return OPVCC(32,0,0,0); /* lwz */
  910. case AMOVWU: return OPVCC(33,0,0,0); /* lwzu */
  911. case AMOVB:
  912. case AMOVBZ: return OPVCC(34,0,0,0); /* load */
  913. case AMOVBU:
  914. case AMOVBZU: return OPVCC(35,0,0,0);
  915. case AFMOVD: return OPVCC(50,0,0,0);
  916. case AFMOVDU: return OPVCC(51,0,0,0);
  917. case AFMOVS: return OPVCC(48,0,0,0);
  918. case AFMOVSU: return OPVCC(49,0,0,0);
  919. case AMOVH: return OPVCC(42,0,0,0);
  920. case AMOVHU: return OPVCC(43,0,0,0);
  921. case AMOVHZ: return OPVCC(40,0,0,0);
  922. case AMOVHZU: return OPVCC(41,0,0,0);
  923. case AMOVMW: return OPVCC(46,0,0,0); /* lmw */
  924. }
  925. diag("bad load opcode %A\n", a);
  926. return 0;
  927. }
  928. /*
  929. * indexed load a(b),d
  930. */
  931. long
  932. oploadx(int a)
  933. {
  934. switch(a) {
  935. case AMOVW: return OPVCC(31,23,0,0); /* lwzx */
  936. case AMOVWU: return OPVCC(31,55,0,0); /* lwzux */
  937. case AMOVB:
  938. case AMOVBZ: return OPVCC(31,87,0,0); /* lbzx */
  939. case AMOVBU:
  940. case AMOVBZU: return OPVCC(31,119,0,0); /* lbzux */
  941. case AFMOVD: return OPVCC(31,599,0,0); /* lfdx */
  942. case AFMOVDU: return OPVCC(31,631,0,0); /* lfdux */
  943. case AFMOVS: return OPVCC(31,535,0,0); /* lfsx */
  944. case AFMOVSU: return OPVCC(31,567,0,0); /* lfsux */
  945. case AMOVH: return OPVCC(31,343,0,0); /* lhax */
  946. case AMOVHU: return OPVCC(31,375,0,0); /* lhaux */
  947. case AMOVHBR: return OPVCC(31,790,0,0); /* lhbrx */
  948. case AMOVWBR: return OPVCC(31,534,0,0); /* lwbrx */
  949. case AMOVHZ: return OPVCC(31,279,0,0); /* lhzx */
  950. case AMOVHZU: return OPVCC(31,311,0,0); /* lhzux */
  951. case AECIWX: return OPVCC(31,310,0,0); /* eciwx */
  952. case ALWAR: return OPVCC(31,20,0,0); /* lwarx */
  953. case ALSW: return OPVCC(31,533,0,0); /* lswx */
  954. }
  955. diag("bad loadx opcode %A\n", a);
  956. return 0;
  957. }
  958. /*
  959. * store s,o(d)
  960. */
  961. long
  962. opstore(int a)
  963. {
  964. switch(a) {
  965. case AMOVB:
  966. case AMOVBZ: return OPVCC(38,0,0,0); /* stb */
  967. case AMOVBU:
  968. case AMOVBZU: return OPVCC(39,0,0,0); /* stbu */
  969. case AFMOVD: return OPVCC(54,0,0,0); /* stfd */
  970. case AFMOVDU: return OPVCC(55,0,0,0); /* stfdu */
  971. case AFMOVS: return OPVCC(52,0,0,0); /* stfs */
  972. case AFMOVSU: return OPVCC(53,0,0,0); /* stfsu */
  973. case AMOVHZ:
  974. case AMOVH: return OPVCC(44,0,0,0); /* sth */
  975. case AMOVHZU:
  976. case AMOVHU: return OPVCC(45,0,0,0); /* sthu */
  977. case AMOVMW: return OPVCC(47,0,0,0); /* stmw */
  978. case ASTSW: return OPVCC(31,725,0,0); /* stswi */
  979. case AMOVW: return OPVCC(36,0,0,0); /* stw */
  980. case AMOVWU: return OPVCC(37,0,0,0); /* stwu */
  981. }
  982. diag("unknown store opcode %A", a);
  983. return 0;
  984. }
  985. /*
  986. * indexed store s,a(b)
  987. */
  988. long
  989. opstorex(int a)
  990. {
  991. switch(a) {
  992. case AMOVB:
  993. case AMOVBZ: return OPVCC(31,215,0,0); /* stbx */
  994. case AMOVBU:
  995. case AMOVBZU: return OPVCC(31,247,0,0); /* stbux */
  996. case AFMOVD: return OPVCC(31,727,0,0); /* stfdx */
  997. case AFMOVDU: return OPVCC(31,759,0,0); /* stfdux */
  998. case AFMOVS: return OPVCC(31,663,0,0); /* stfsx */
  999. case AFMOVSU: return OPVCC(31,695,0,0); /* stfsux */
  1000. case AMOVHZ:
  1001. case AMOVH: return OPVCC(31,407,0,0); /* sthx */
  1002. case AMOVHBR: return OPVCC(31,918,0,0); /* sthbrx */
  1003. case AMOVHZU:
  1004. case AMOVHU: return OPVCC(31,439,0,0); /* sthux */
  1005. case AMOVW: return OPVCC(31,151,0,0); /* stwx */
  1006. case AMOVWU: return OPVCC(31,183,0,0); /* stwux */
  1007. case ASTSW: return OPVCC(31,661,0,0); /* stswx */
  1008. case AMOVWBR: return OPVCC(31,662,0,0); /* stwbrx */
  1009. case ASTWCCC: return OPVCC(31,150,0,1); /* stwcx. */
  1010. case AECOWX: return OPVCC(31,438,0,0); /* ecowx */
  1011. }
  1012. diag("unknown storex opcode %A", a);
  1013. return 0;
  1014. }