diff options
author | Camil Staps | 2018-12-25 10:39:25 +0100 |
---|---|---|
committer | Camil Staps | 2018-12-25 10:39:25 +0100 |
commit | 930f3d68b02bd0089e209eb80328f5db2e6fd821 (patch) | |
tree | a230ab013258eece6554b6e6dc8291d6646d2252 /sjit_c.c | |
parent | Inline +, *, - and / (diff) |
Add comparisons; tak example
Diffstat (limited to 'sjit_c.c')
-rw-r--r-- | sjit_c.c | 118 |
1 files changed, 77 insertions, 41 deletions
@@ -12,18 +12,27 @@ enum instr { Call, Jmp, - JmpTrue, + JmpCond, Ret, Halt, - IAdd, - IMul, - ISub, - IDiv + Op }; -static inline uint32_t instr_size(enum instr instr) { - switch (instr) { +enum op { + OAdd, OMul, + OSub, ODiv +}; + +enum cond { + CEq, CNe, + CLt, CLe, + CGt, CGe, + CTrue +}; + +static inline uint32_t instr_size(uint64_t *pgm) { + switch (*pgm) { case PushRef: return 5+1; case PushI: return 7+1; case Put: return 1+5; @@ -31,17 +40,25 @@ static inline uint32_t instr_size(enum instr instr) { case Call: return 5; case Jmp: return 5; - case JmpTrue: return 1+3+6; + case JmpCond: switch (pgm[1]) { + case CTrue: return 1+3+6; + default: return 1+1+3+6; + } case Ret: return 1; case Halt: return 1+1; - case IAdd: - case ISub: return 1+4+3+4; - case IMul: return 1+4+4+4; - case IDiv: return 1+4+3+3+4; + case Op: switch (pgm[1]) { + case OAdd: + case OSub: return 1+4+3+4; + case OMul: return 1+4+4+4; + case ODiv: return 1+4+3+3+4; + default: + fprintf(stderr,"unknown operator %d\n",(int)pgm[1]); + exit(1); + } default: - fprintf(stderr,"unknown instruction %d\n",instr); + fprintf(stderr,"unknown instruction %d\n",(int)*pgm); exit(1); } } @@ -127,21 +144,41 @@ static inline void gen_instr(char *full_code, char **code_p, uint64_t **pgm_p, u pgm+=2; code+=5; break; - case JmpTrue: - arg=pgm[1]; + case JmpCond: + { + enum cond cond=pgm[1]; + arg=pgm[2]; #ifdef DEBUG_JIT_INSTRUCTIONS - fprintf(stderr,"JmpTrue %lu -> %d\n",arg,mapping[arg]-(uint32_t)(&code[10]-full_code)); + fprintf(stderr,"JmpCond %d %lu -> %d\n",(int)cond,arg,mapping[arg]-(uint32_t)(&code[10]-full_code)); #endif code[0]='\x59'; /* pop rcx */ - code[1]='\x48'; /* test rcx,rcx */ - code[2]='\x85'; - code[3]='\xc9'; - code[4]='\x0f'; /* jne ARG */ - code[5]='\x85'; - *(uint32_t*)&code[6]=mapping[arg]-(&code[10]-full_code); - pgm+=2; - code+=10; + if (cond==CTrue) { + code[1]='\x48'; /* test rcx,rcx */ + code[2]='\x85'; + code[3]='\xc9'; + code+=4; + } else { + code[1]='\x58'; /* pop rax */ + code[2]='\x48'; /* cmp rax,rcx */ + code[3]='\x3b'; + code[4]='\xc1'; + code+=5; + } + code[0]='\x0f'; /* jcc */ + switch (cond) { + case CEq: code[1]='\x84'; break; + case CTrue: + case CNe: code[1]='\x85'; break; + case CLt: code[1]='\x8c'; break; + case CLe: code[1]='\x8e'; break; + case CGt: code[1]='\x8f'; break; + case CGe: code[1]='\x8d'; break; + } + *(uint32_t*)&code[2]=mapping[arg]-(&code[6]-full_code); + pgm+=3; + code+=6; break; + } case Ret: #ifdef DEBUG_JIT_INSTRUCTIONS fprintf(stderr,"Ret\n"); @@ -160,32 +197,30 @@ static inline void gen_instr(char *full_code, char **code_p, uint64_t **pgm_p, u code+=2; break; - case IAdd: - case IMul: - case ISub: - case IDiv: + case Op: + arg=pgm[1]; #ifdef DEBUG_JIT_INSTRUCTIONS - fprintf(stderr,"I<Op>\n"); + fprintf(stderr,"Op %d\n",(int)arg); #endif /* pop rax */ code[0]='\x58'; /* mov rcx,[rsp] */ code[1]='\x48'; code[2]='\x8b'; code[3]='\x0c'; code[4]='\x24'; - switch (*pgm) { - case IAdd: - case ISub: + switch (arg) { + case OAdd: + case OSub: /* {add,sub} rax,rcx */ code[5]='\x48'; - code[6]=*pgm==IAdd ? '\x01' : '\x29'; + code[6]=arg==OAdd ? '\x01' : '\x29'; code[7]='\xc8'; code+=8; break; - case IMul: + case OMul: /* imul rax,rcx */ code[5]='\x48'; code[6]='\x0f'; code[7]='\xaf'; code[8]='\xc1'; code+=9; break; - case IDiv: + case ODiv: /* xor rdx,rdx */ code[5]='\x48'; code[6]='\x31'; code[7]='\xd2'; /* idiv rcx */ @@ -195,7 +230,7 @@ static inline void gen_instr(char *full_code, char **code_p, uint64_t **pgm_p, u } /* mov [rsp],rax */ code[0]='\x48'; code[1]='\x89'; code[2]='\x04'; code[3]='\x24'; - pgm++; + pgm+=2; code+=4; break; @@ -222,19 +257,20 @@ char *jit_append(char *code_block, uint32_t code_len, char *code_ptr, uint64_t *pgm_p=pgm; for (i=n_instr; i<n_instr+len; i++) { - enum instr instr=(enum instr)*pgm_p; - mapping[i]=code_i; - code_i+=instr_size(instr); + code_i+=instr_size(pgm_p); - switch (instr) { + switch (*pgm_p) { + case JmpCond: + pgm_p+=3; + break; case PushRef: case PushI: case Put: case Pop: case Call: case Jmp: - case JmpTrue: + case Op: pgm_p+=2; break; default: |