| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- // asmcoder.h
- // by [email protected]
- // v0.5
- // point sets nonused bits to 1
- // v0.4
- // direct pixel address now expected
- // x,y args removed span removed
- // v0.3
- // span changed to bytes
- // pixfield indirect dropped, passed directy to plot
- // ret(n) added to remove args from fastcall stack
- // CodePoint() method added
- /*
- asmcoder provides inline assembly generator for high speed runtime tasks
- methods:
- CodePlot(codebase,depth,amask,rmask,gmask,bmask)
- CodePoint(codebase,depth,amask,rmask,gmask,bmask)
- CodeSpan(codebase,depth,amask,rmask,gmask,bmask)
- codebase=executable memory (64 bytes)
- depth=pixel depth (8,16,24,32)
- amask=32bit alpha pixel mask
- rmask=32bit red pixel mask
- gmask=32bit green pixel mask
- bmask=32bit blue pixel mask
- returns number of bytes of code generated (max 64 bytes)
-
- call resulting code by typecasting codebase with
- void (__fastcall *plot)(void *pix,int argb)
- int (__fastcall *point)(void *pix)
- void (__fastcall *span)(void *pix,int *argb,int count)
- ToDo:
- */
- #ifndef ASMCODER_H
- #define ASMCODER_H
- class IA32
- {
- public:
- char *ptr;
- int off;
- enum Reg32{eax,ecx,edx,ebx,esp,ebp,esi,edi};
- void Reset(void *p) {ptr=(char *)p;off=0;}
- void Code(int c){if (ptr) ptr[off]=c;off++;}
- void Code16(int c){if (ptr) *(short*)(ptr+off)=c;off+=2;}
- void Code32(int c){if (ptr) *(int*)(ptr+off)=c;off+=4;}
- void push(Reg32 reg) {Code(0x50+reg);}
- void pop(Reg32 reg) {Code(0x58+reg);}
- void ret(int n=0) {if (n==0) Code(0xc3);else {Code(0xc2);Code(n);Code(0);}}
- void mov(Reg32 dest,Reg32 src) {Code(0x8b);Code((0xc0)|(dest<<3)|(src));}
- void or(Reg32 dest,Reg32 src) {Code(0x0b);Code((0xc0)|(dest<<3)|(src));}
- void add(Reg32 dest,Reg32 src) {Code(0x03);Code((0xc0)|(dest<<3)|(src));}
- void load32(Reg32 dest,Reg32 src,int disp=0)
- {
- if (disp==0 && src!=ebp) {Code(0x8b);Code((dest<<3)|(src));}
- else {Code(0x8b);Code((0x40)|(dest<<3)|(src));Code(disp);}
- }
- void load16(Reg32 dest,Reg32 src,int disp=0) {Code(0x66);load32(dest,src,disp);}
- void load8(Reg32 dest,Reg32 src,int disp=0)
- {
- Code(0x8a);if (disp==0 && src!=ebp) {Code((dest<<3)|(src));} else {Code((0x40)|(dest<<3)|(src));Code(disp);}
- }
- void store32(Reg32 dest,int disp,Reg32 src)
- {
- if (disp==0 && dest!=ebp) {Code(0x89);Code((src<<3)|(dest));Code(0);}
- else {Code(0x89);Code((0x40)|(src<<3)|(dest));Code(disp);}
- }
- void store16(Reg32 dest,int disp,Reg32 src) {Code(0x66);store32(dest,disp,src);}
- void store8(Reg32 dest,int disp,Reg32 src)
- {
- Code(0x88);
- if (disp==0 && dest!=ebp) {Code((src<<3)|(dest));Code(0);} else {Code((0x40)|(src<<3)|(dest));Code(disp);}
- }
- void lea(Reg32 dest,int scale,Reg32 src1,Reg32 src2,int disp=0)
- {
- int n,mod,sib;
- if (disp==0) n=0;else {if (disp>=-128 && disp<128) n=1;else n=2;}
- mod=(n<<6)|4;
- sib=(src1<<3)|src2;
- if (scale==2) sib|=0x40;
- if (scale==4) sib|=0x80;
- if (scale==8) sib|=0xc0;
- Code(0x8d);Code(mod);Code(sib);
- if (n==1) Code(disp);else if (n==2) Code32(disp);
- }
- void lea(Reg32 dest,int scale,Reg32 src,int disp=0)
- {
- int mod,sib;
- sib=(src<<3)|5;
- mod=(dest<<3)|4;
- if (scale==2) sib|=0x40;
- if (scale==4) sib|=0x80;
- if (scale==8) sib|=0xc0;
- Code(0x8d);Code(mod);Code(sib);Code32(disp);
- }
- void imul(Reg32 dest,int imm,Reg32 src)
- {
- Code(0x69);Code((0xc0)|(dest<<3)|(src));Code32(imm);
- }
- void shift(Reg32 reg,int imm) //+imm=left -imm=right
- {
- int op;
- if (imm==0) return;
- if (imm>0) {op=0xe0+reg;} else {op=0xe8+reg;imm=-imm;}
- if (imm==1) {Code(0xd1);Code(op);} else {Code(0xc1);Code(op);Code(imm);}
- }
- void and(Reg32 reg,int imm)
- {
- if (imm==0xffffffff) return;
- if (imm>=-128 && imm<128)
- {
- Code(0x83);Code(0xe0+reg);Code(imm);
- }
- else
- {
- if (reg==eax) {Code(0x25);} else {Code(0x81);Code(0xe0+reg);}Code32(imm);
- }
- }
- void or(Reg32 reg,int imm)
- {
- if (imm==0) return;
- if (imm>=-128 && imm<128)
- {
- Code(0x83);Code(0xc0+reg);Code(imm);
- }
- else
- {
- if (reg==eax) {Code(0x0d);} else {Code(0x81);Code(0xc0+reg);}
- Code32(imm);
- }
- }
- void jnz(int label) {Code(0x75);Code(label-(off+1));}
- void add(Reg32 reg,int imm) {Code(0x83);Code(0xc0+reg);Code(imm);}
- void neg(Reg32 reg) {Code(0xf7);Code(0xd8+reg);}
- };
- class AsmCoder : IA32
- {
- public:
- int amsb,rmsb,gmsb,bmsb;
- void CalcMSBs(int amask,int rmask,int gmask,int bmask)
- {
- unsigned int u;
- amsb=0;if (u=amask) {while (u!=1) {u>>=1;amsb++;}}
- rmsb=0;if (u=rmask) {while (u!=1) {u>>=1;rmsb++;}}
- gmsb=0;if (u=gmask) {while (u!=1) {u>>=1;gmsb++;}}
- bmsb=0;if (u=bmask) {while (u!=1) {u>>=1;bmsb++;}}
- }
- // ecx=void *t pixel
- // edx=int argb
- int CodePlot(void *code,int depth,int amask,int rmask,int gmask,int bmask)
- {
- Reset(code);
- CalcMSBs(amask,rmask,gmask,bmask);
- push (ebx);
- push (ebp);
- mov (eax,edx);
- mov (ebp,ecx);
- if (rmask==0xff0000 && gmask==0xff00 && bmask==0xff)
- {
- if (amask==0 && depth>24) and(eax,0xffffff);
- }
- else
- {
- mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
- shift (eax,bmsb-7); //3-0);
- mov (ecx,ebx);
- shift (ebx,gmsb-15);
- if (amask) mov (edx,ecx); //alph
- if (amask) shift (edx,amsb-31); //alph
- and (eax,bmask);
- shift (ecx,rmsb-23);
- if (amask) and (edx,amask); //alph
- and (ebx,gmask);
- if (amask) or (eax,edx); //alph
- and (ecx,rmask);
- or (eax,ebx);
- or (eax,ecx);
- }
- switch (depth)
- {
- case 16:store16(ebp,0,eax);break;
- // case 24:store16(ebp,0,eax);shift(eax,-16);store8(ebp,2,eax);break;
- case 24:store8(ebp,0,eax);shift(eax,-8);store16(ebp,1,eax);break;
- case 32:store32(ebp,0,eax);break;
- default:store8(ebp,0,eax);
- }
- pop(ebp);
- pop(ebx);
- ret();
- return off;
- }
- // ecx=void*pix
- int CodePoint(void *code,int depth,int amask,int rmask,int gmask,int bmask)
- {
- Reset(code);
- CalcMSBs(amask,rmask,gmask,bmask);
- push (ebx);
- switch (depth)
- {
- case 16:load16(eax,ecx);break;
- // case 24:load16(eax,ecx);shift(eax,-16);load8(eax,ecx,2);break;
- case 24:load16(eax,ecx,1);shift(eax,8);load8(eax,ecx);break;
- case 32:load32(eax,ecx);break;
- default:load8(eax,ecx);
- }
- if ((amask==0 || amask==0xff000000) && (rmask==0xff0000 && gmask==0xff00 && bmask==0xff))
- {
- //
- }
- else
- {
- mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
- mov (ecx,eax);
- if (amask) mov (edx,eax);
- and (eax,bmask);
- shift (eax,7-bmsb);
- and (ebx,gmask);
- shift (ebx,15-gmsb);
- and (ecx,rmask);
- shift (ecx,23-rmsb);
- if (amask) and (edx,amask);
- or (eax,ebx);
- if (amask) shift (edx,31-amsb);
- or (eax,ecx);
- if (amask) or (eax,edx);
- }
- pop(ebx);
- int oor=0;
- if( !amask ) oor|=0xff000000;
- if( !rmask ) oor|=0x00ff0000;
- if( !gmask ) oor|=0x0000ff00;
- if( !bmask ) oor|=0x000000ff;
- if( oor ) or( eax,oor );
- ret();
- return off;
- }
- // ecx=void *t pixel
- // edx=int *argb
- // 8(esp)=count
- int CodeSpan(void *code,int depth,int amask,int rmask,int gmask,int bmask)
- {
- int loop;
- Reset(code);
- CalcMSBs(amask,rmask,gmask,bmask);
- push (ebp);
- mov (ebp,esp);
- push (ebx);
- push (esi);
- push (edi);
- load32 (edi,ebp,8); //edi=count
- mov (esi,edx); //esi=[argb]
- mov (ebp,ecx); //ebp=[pix]
- neg (edi);
-
- loop=off;
- // loop
- load32 (eax,esi);
- add (esi,4);
- if (rmask==0xff0000 && gmask==0xff00 && bmask==0xff)
- {
- if (amask==0 && depth>24) and(eax,0xffffff);
- }
- else
- {
- mov (ebx,eax); //eax=b ebx=g ecx=r edx=a
- shift (eax,bmsb-7); //3-0);
- mov (ecx,ebx);
- shift (ebx,gmsb-15);
- if (amask) mov (edx,ecx); //alph
- if (amask) shift (edx,amsb-31); //alph
- and (eax,bmask);
- shift (ecx,rmsb-23);
- if (amask) and (edx,amask); //alph
- and (ebx,gmask);
- if (amask) or (eax,edx); //alph
- and (ecx,rmask);
- or (eax,ebx);
- or (eax,ecx);
- }
- switch (depth)
- {
- case 16:store16(ebp,0,eax);add(ebp,2);break;
- case 24:store8(ebp,0,eax);shift(eax,-8);store16(ebp,1,eax);add(ebp,3);break;
- case 32:store32(ebp,0,eax);add(ebp,4);break;
- default:store8(ebp,0,eax);add(ebp,1);
- }
- add (edi,1);
- jnz (loop);
- pop (edi);
- pop (esi);
- pop (ebx);
- pop (ebp);
- ret (4);
- return off;
- }
- };
- #endif
|