aboutsummaryrefslogtreecommitdiff
path: root/sjit_c.c
diff options
context:
space:
mode:
Diffstat (limited to 'sjit_c.c')
-rw-r--r--sjit_c.c118
1 files changed, 77 insertions, 41 deletions
diff --git a/sjit_c.c b/sjit_c.c
index caae10f..21a4b70 100644
--- a/sjit_c.c
+++ b/sjit_c.c
@@ -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: