asmcoder.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. // asmcoder.h
  2. // by [email protected]
  3. // v0.5
  4. // point sets nonused bits to 1
  5. // v0.4
  6. // direct pixel address now expected
  7. // x,y args removed span removed
  8. // v0.3
  9. // span changed to bytes
  10. // pixfield indirect dropped, passed directy to plot
  11. // ret(n) added to remove args from fastcall stack
  12. // CodePoint() method added
  13. /*
  14. asmcoder provides inline assembly generator for high speed runtime tasks
  15. methods:
  16. CodePlot(codebase,depth,amask,rmask,gmask,bmask)
  17. CodePoint(codebase,depth,amask,rmask,gmask,bmask)
  18. CodeSpan(codebase,depth,amask,rmask,gmask,bmask)
  19. codebase=executable memory (64 bytes)
  20. depth=pixel depth (8,16,24,32)
  21. amask=32bit alpha pixel mask
  22. rmask=32bit red pixel mask
  23. gmask=32bit green pixel mask
  24. bmask=32bit blue pixel mask
  25. returns number of bytes of code generated (max 64 bytes)
  26. call resulting code by typecasting codebase with
  27. void (__fastcall *plot)(void *pix,int argb)
  28. int (__fastcall *point)(void *pix)
  29. void (__fastcall *span)(void *pix,int *argb,int count)
  30. ToDo:
  31. */
  32. #ifndef ASMCODER_H
  33. #define ASMCODER_H
  34. class IA32
  35. {
  36. public:
  37. char *ptr;
  38. int off;
  39. enum Reg32{eax,ecx,edx,ebx,esp,ebp,esi,edi};
  40. void Reset(void *p) {ptr=(char *)p;off=0;}
  41. void Code(int c){if (ptr) ptr[off]=c;off++;}
  42. void Code16(int c){if (ptr) *(short*)(ptr+off)=c;off+=2;}
  43. void Code32(int c){if (ptr) *(int*)(ptr+off)=c;off+=4;}
  44. void push(Reg32 reg) {Code(0x50+reg);}
  45. void pop(Reg32 reg) {Code(0x58+reg);}
  46. void ret(int n=0) {if (n==0) Code(0xc3);else {Code(0xc2);Code(n);Code(0);}}
  47. void mov(Reg32 dest,Reg32 src) {Code(0x8b);Code((0xc0)|(dest<<3)|(src));}
  48. void or(Reg32 dest,Reg32 src) {Code(0x0b);Code((0xc0)|(dest<<3)|(src));}
  49. void add(Reg32 dest,Reg32 src) {Code(0x03);Code((0xc0)|(dest<<3)|(src));}
  50. void load32(Reg32 dest,Reg32 src,int disp=0)
  51. {
  52. if (disp==0 && src!=ebp) {Code(0x8b);Code((dest<<3)|(src));}
  53. else {Code(0x8b);Code((0x40)|(dest<<3)|(src));Code(disp);}
  54. }
  55. void load16(Reg32 dest,Reg32 src,int disp=0) {Code(0x66);load32(dest,src,disp);}
  56. void load8(Reg32 dest,Reg32 src,int disp=0)
  57. {
  58. Code(0x8a);if (disp==0 && src!=ebp) {Code((dest<<3)|(src));} else {Code((0x40)|(dest<<3)|(src));Code(disp);}
  59. }
  60. void store32(Reg32 dest,int disp,Reg32 src)
  61. {
  62. if (disp==0 && dest!=ebp) {Code(0x89);Code((src<<3)|(dest));Code(0);}
  63. else {Code(0x89);Code((0x40)|(src<<3)|(dest));Code(disp);}
  64. }
  65. void store16(Reg32 dest,int disp,Reg32 src) {Code(0x66);store32(dest,disp,src);}
  66. void store8(Reg32 dest,int disp,Reg32 src)
  67. {
  68. Code(0x88);
  69. if (disp==0 && dest!=ebp) {Code((src<<3)|(dest));Code(0);} else {Code((0x40)|(src<<3)|(dest));Code(disp);}
  70. }
  71. void lea(Reg32 dest,int scale,Reg32 src1,Reg32 src2,int disp=0)
  72. {
  73. int n,mod,sib;
  74. if (disp==0) n=0;else {if (disp>=-128 && disp<128) n=1;else n=2;}
  75. mod=(n<<6)|4;
  76. sib=(src1<<3)|src2;
  77. if (scale==2) sib|=0x40;
  78. if (scale==4) sib|=0x80;
  79. if (scale==8) sib|=0xc0;
  80. Code(0x8d);Code(mod);Code(sib);
  81. if (n==1) Code(disp);else if (n==2) Code32(disp);
  82. }
  83. void lea(Reg32 dest,int scale,Reg32 src,int disp=0)
  84. {
  85. int mod,sib;
  86. sib=(src<<3)|5;
  87. mod=(dest<<3)|4;
  88. if (scale==2) sib|=0x40;
  89. if (scale==4) sib|=0x80;
  90. if (scale==8) sib|=0xc0;
  91. Code(0x8d);Code(mod);Code(sib);Code32(disp);
  92. }
  93. void imul(Reg32 dest,int imm,Reg32 src)
  94. {
  95. Code(0x69);Code((0xc0)|(dest<<3)|(src));Code32(imm);
  96. }
  97. void shift(Reg32 reg,int imm) //+imm=left -imm=right
  98. {
  99. int op;
  100. if (imm==0) return;
  101. if (imm>0) {op=0xe0+reg;} else {op=0xe8+reg;imm=-imm;}
  102. if (imm==1) {Code(0xd1);Code(op);} else {Code(0xc1);Code(op);Code(imm);}
  103. }
  104. void and(Reg32 reg,int imm)
  105. {
  106. if (imm==0xffffffff) return;
  107. if (imm>=-128 && imm<128)
  108. {
  109. Code(0x83);Code(0xe0+reg);Code(imm);
  110. }
  111. else
  112. {
  113. if (reg==eax) {Code(0x25);} else {Code(0x81);Code(0xe0+reg);}Code32(imm);
  114. }
  115. }
  116. void or(Reg32 reg,int imm)
  117. {
  118. if (imm==0) return;
  119. if (imm>=-128 && imm<128)
  120. {
  121. Code(0x83);Code(0xc0+reg);Code(imm);
  122. }
  123. else
  124. {
  125. if (reg==eax) {Code(0x0d);} else {Code(0x81);Code(0xc0+reg);}
  126. Code32(imm);
  127. }
  128. }
  129. void jnz(int label) {Code(0x75);Code(label-(off+1));}
  130. void add(Reg32 reg,int imm) {Code(0x83);Code(0xc0+reg);Code(imm);}
  131. void neg(Reg32 reg) {Code(0xf7);Code(0xd8+reg);}
  132. };
  133. class AsmCoder : IA32
  134. {
  135. public:
  136. int amsb,rmsb,gmsb,bmsb;
  137. void CalcMSBs(int amask,int rmask,int gmask,int bmask)
  138. {
  139. unsigned int u;
  140. amsb=0;if (u=amask) {while (u!=1) {u>>=1;amsb++;}}
  141. rmsb=0;if (u=rmask) {while (u!=1) {u>>=1;rmsb++;}}
  142. gmsb=0;if (u=gmask) {while (u!=1) {u>>=1;gmsb++;}}
  143. bmsb=0;if (u=bmask) {while (u!=1) {u>>=1;bmsb++;}}
  144. }
  145. // ecx=void *t pixel
  146. // edx=int argb
  147. int CodePlot(void *code,int depth,int amask,int rmask,int gmask,int bmask)
  148. {
  149. Reset(code);
  150. CalcMSBs(amask,rmask,gmask,bmask);
  151. push (ebx);
  152. push (ebp);
  153. mov (eax,edx);
  154. mov (ebp,ecx);
  155. if (rmask==0xff0000 && gmask==0xff00 && bmask==0xff)
  156. {
  157. if (amask==0 && depth>24) and(eax,0xffffff);
  158. }
  159. else
  160. {
  161. mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
  162. shift (eax,bmsb-7); //3-0);
  163. mov (ecx,ebx);
  164. shift (ebx,gmsb-15);
  165. if (amask) mov (edx,ecx); //alph
  166. if (amask) shift (edx,amsb-31); //alph
  167. and (eax,bmask);
  168. shift (ecx,rmsb-23);
  169. if (amask) and (edx,amask); //alph
  170. and (ebx,gmask);
  171. if (amask) or (eax,edx); //alph
  172. and (ecx,rmask);
  173. or (eax,ebx);
  174. or (eax,ecx);
  175. }
  176. switch (depth)
  177. {
  178. case 16:store16(ebp,0,eax);break;
  179. // case 24:store16(ebp,0,eax);shift(eax,-16);store8(ebp,2,eax);break;
  180. case 24:store8(ebp,0,eax);shift(eax,-8);store16(ebp,1,eax);break;
  181. case 32:store32(ebp,0,eax);break;
  182. default:store8(ebp,0,eax);
  183. }
  184. pop(ebp);
  185. pop(ebx);
  186. ret();
  187. return off;
  188. }
  189. // ecx=void*pix
  190. int CodePoint(void *code,int depth,int amask,int rmask,int gmask,int bmask)
  191. {
  192. Reset(code);
  193. CalcMSBs(amask,rmask,gmask,bmask);
  194. push (ebx);
  195. switch (depth)
  196. {
  197. case 16:load16(eax,ecx);break;
  198. // case 24:load16(eax,ecx);shift(eax,-16);load8(eax,ecx,2);break;
  199. case 24:load16(eax,ecx,1);shift(eax,8);load8(eax,ecx);break;
  200. case 32:load32(eax,ecx);break;
  201. default:load8(eax,ecx);
  202. }
  203. if ((amask==0 || amask==0xff000000) && (rmask==0xff0000 && gmask==0xff00 && bmask==0xff))
  204. {
  205. //
  206. }
  207. else
  208. {
  209. mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
  210. mov (ecx,eax);
  211. if (amask) mov (edx,eax);
  212. and (eax,bmask);
  213. shift (eax,7-bmsb);
  214. and (ebx,gmask);
  215. shift (ebx,15-gmsb);
  216. and (ecx,rmask);
  217. shift (ecx,23-rmsb);
  218. if (amask) and (edx,amask);
  219. or (eax,ebx);
  220. if (amask) shift (edx,31-amsb);
  221. or (eax,ecx);
  222. if (amask) or (eax,edx);
  223. }
  224. pop(ebx);
  225. int oor=0;
  226. if( !amask ) oor|=0xff000000;
  227. if( !rmask ) oor|=0x00ff0000;
  228. if( !gmask ) oor|=0x0000ff00;
  229. if( !bmask ) oor|=0x000000ff;
  230. if( oor ) or( eax,oor );
  231. ret();
  232. return off;
  233. }
  234. // ecx=void *t pixel
  235. // edx=int *argb
  236. // 8(esp)=count
  237. int CodeSpan(void *code,int depth,int amask,int rmask,int gmask,int bmask)
  238. {
  239. int loop;
  240. Reset(code);
  241. CalcMSBs(amask,rmask,gmask,bmask);
  242. push (ebp);
  243. mov (ebp,esp);
  244. push (ebx);
  245. push (esi);
  246. push (edi);
  247. load32 (edi,ebp,8); //edi=count
  248. mov (esi,edx); //esi=[argb]
  249. mov (ebp,ecx); //ebp=[pix]
  250. neg (edi);
  251. loop=off;
  252. // loop
  253. load32 (eax,esi);
  254. add (esi,4);
  255. if (rmask==0xff0000 && gmask==0xff00 && bmask==0xff)
  256. {
  257. if (amask==0 && depth>24) and(eax,0xffffff);
  258. }
  259. else
  260. {
  261. mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
  262. shift (eax,bmsb-7); //3-0);
  263. mov (ecx,ebx);
  264. shift (ebx,gmsb-15);
  265. if (amask) mov (edx,ecx); //alph
  266. if (amask) shift (edx,amsb-31); //alph
  267. and (eax,bmask);
  268. shift (ecx,rmsb-23);
  269. if (amask) and (edx,amask); //alph
  270. and (ebx,gmask);
  271. if (amask) or (eax,edx); //alph
  272. and (ecx,rmask);
  273. or (eax,ebx);
  274. or (eax,ecx);
  275. }
  276. switch (depth)
  277. {
  278. case 16:store16(ebp,0,eax);add(ebp,2);break;
  279. case 24:store8(ebp,0,eax);shift(eax,-8);store16(ebp,1,eax);add(ebp,3);break;
  280. case 32:store32(ebp,0,eax);add(ebp,4);break;
  281. default:store8(ebp,0,eax);add(ebp,1);
  282. }
  283. add (edi,1);
  284. jnz (loop);
  285. pop (edi);
  286. pop (esi);
  287. pop (ebx);
  288. pop (ebp);
  289. ret (4);
  290. return off;
  291. }
  292. };
  293. #endif