1 /**
2  * Copyright (c)2004 Jean-Christophe Hoelt <jeko@ios-software.com>
3  */
4 
5 #include <stdlib.h>
6 #include <string.h>
7 
8 #define JITC_MAXLABEL 1024
9 #define JITC_LABEL_SIZE 64
10 
11 /**
12  * low level macros
13  */
14 
15  /* {{{ Registres Generaux */
16 #define EAX 0
17 #define ECX 1
18 #define EDX 2
19 #define EBX 3
20 #define ESP 4
21 #define EBP 5
22 #define ESI 6
23 #define EDI 7
24  /* }}} */
25  /* {{{ Registres MMX */
26 #define MM0 0
27 #define MM1 1
28 #define MM2 2
29 #define MM3 3
30 #define MM4 4
31 #define MM5 5
32 #define MM6 6
33 #define MM7 7
34  /* }}} */
35  /* {{{  Registres SSE*/
36 #define XMM0 0
37 #define XMM1 1
38 #define XMM2 2
39 #define XMM3 3
40 #define XMM4 4
41 #define XMM5 5
42 #define XMM6 6
43 #define XMM7 7
44  /* }}} */
45  /* {{{ Alias aux registres */
46 #define R0 0
47 #define R1 1
48 #define R2 2
49 #define R3 3
50 #define R4 4
51 #define R5 5
52 #define R6 6
53 #define R7 7
54  /* }}} */
55 
56  /* {{{ Conditions */
57 #define COND_OVERFLOW    0
58 #define COND_NO_OVERFLOW 1
59 #define COND_BELOW       2
60 #define COND_NOT_BELOW   3
61 #define COND_EQUAL       4
62 #define COND_ZERO        4
63 #define COND_NOT_EQUAL   5
64 #define COND_NOT_ZERO    5
65 #define COND_NOT_ABOVE   6
66 #define COND_ABOVE       7
67 #define COND_SIGN        8
68 #define COND_NOT_SIGN    9
69 #define COND_EVEN       10
70 #define COND_ODD        11
71 #define COND_LESS_THAN  12
72 #define COND_GREATER_EQUAL 13
73 #define COND_LESS_EQUAL    14
74 #define COND_GREATER_THAN  15
75  /* }}} */
76 
77 typedef int (*JitcFunc)(void);
78 
79 typedef struct _LABEL_ADDR {
80   char label[JITC_LABEL_SIZE];
81   int  address;
82 } LabelAddr;
83 
84 typedef struct _JITC_X86_ENV {
85   unsigned char *_memory;
86   unsigned char *memory;
87   unsigned int  used;
88 
89   int nbUsedLabel;
90   int nbKnownLabel;
91   LabelAddr    *usedLabel;
92   LabelAddr    *knownLabel;
93 } JitcX86Env;
94 
95 #define DISPLAY_GENCODE
96 /*#define DISPLAY_GENCODE_HEXA*/
97 
98 #ifdef DISPLAY_GENCODE_HEXA
99   #define JITC_ADD_UCHAR(jitc,op) printf(" 0x%02x", op) && (jitc->memory[jitc->used++]=op)
100 #else
101   #define JITC_ADD_UCHAR(jitc,op) (jitc->memory[jitc->used++]=op)
102 #endif
103 
104 #define JITC_ADD_USHORT(jitc,i) { JITC_ADD_UCHAR(jitc,i&0xff); JITC_ADD_UCHAR(jitc,(i>>8)&0xff); }
105 #define JITC_ADD_UINT(jitc,i)   { \
106     JITC_ADD_UCHAR(jitc,i&0xff); \
107     JITC_ADD_UCHAR(jitc,(i>>8)&0xff); \
108     JITC_ADD_UCHAR(jitc,(i>>16)&0xff); \
109     JITC_ADD_UCHAR(jitc,(i>>24)&0xff); \
110 }
111 #define JITC_ADD_2UCHAR(jitc,op1,op2) {JITC_ADD_UCHAR(jitc,op1); JITC_ADD_UCHAR(jitc,op2);}
112 
113 #define JITC_MODRM(jitc,mod,reg,rm) { JITC_ADD_UCHAR(jitc,((int)mod<<6)|((int)reg<<3)|((int)rm)); }
114 
115 /* special values for R/M */
116 #define JITC_RM_DISP32 0x05
117 
118 #define JITC_MOD_pREG_REG      0x00
119 #define JITC_MOD_disp8REG_REG  0x01
120 #define JITC_MOD_disp32REG_REG 0x02
121 #define JITC_MOD_REG_REG       0x03
122 /* cf 24319101 p.27 */
123 
124 #define JITC_OP_REG_REG(jitc,op,dest,src)     { JITC_ADD_UCHAR(jitc,op); JITC_ADD_UCHAR(jitc,0xc0+(src<<3)+dest); }
125 #define JITC_OP_REG_pREG(jitc,op,dest,src)    { JITC_ADD_UCHAR(jitc,op); JITC_ADD_UCHAR(jitc,(dest<<3)+src); }
126 #define JITC_OP_pREG_REG(jitc,op,dest,src)    { JITC_ADD_UCHAR(jitc,op); JITC_ADD_UCHAR(jitc,(src<<3)+dest); }
127 
128 /**
129  * "high" level macro
130  */
131 
132 #define JITC_LOAD_REG_IMM32(jitc,reg,imm32) { JITC_ADD_UCHAR  (jitc,0xb8+reg); JITC_ADD_UINT(jitc,(int)(imm32)); }
133 #define JITC_LOAD_REG_REG(jitc,dest,src)    { JITC_OP_REG_REG (jitc,0x89,dest,src); }
134 
135 #define JITC_LOAD_REG_pREG(jitc,dest,src)   { JITC_OP_REG_pREG(jitc,0x8b,dest,src); }
136 #define JITC_LOAD_pREG_REG(jitc,dest,src)   { JITC_OP_pREG_REG(jitc,0x89,dest,src); }
137 
138 #define JITC_DEC_REG(jitc,reg)              { JITC_ADD_UCHAR  (jitc,0x48+reg); }
139 #define JITC_INC_REG(jitc,reg)              { JITC_ADD_UCHAR  (jitc,0x40+reg); }
140 
141 #define JITC_ADD_REG_REG(jitc,dest,src)     { JITC_OP_REG_REG (jitc,0x01,dest,src); }
142 #define JITC_ADD_REG_IMM32(jitc,reg,imm32)  { JITC_ADD_UCHAR (jitc,0x81);\
143                                               JITC_ADD_UCHAR (jitc,0xc0+reg);\
144                                               JITC_ADD_UINT  (jitc,(int)imm32); }
145 
146 #define JITC_AND_REG_REG(jitc,dest,src)     { JITC_OP_REG_REG (jitc,0x21,dest,src); }
147 #define JITC_CMP_REG_REG(jitc,dest,src)     { JITC_OP_REG_REG (jitc,0x39,dest,src); }
148 #define JITC_CMP_REG_IMM32(jitc,reg,imm32)  { JITC_ADD_2UCHAR (jitc,0x81,0xf8+reg); \
149                                               JITC_ADD_UINT   (jitc,(int)imm32); }
150 
151 #define JITC_IDIV_EAX_REG(jitc,reg)         { JITC_ADD_2UCHAR(jitc, 0xf7, 0xf8+reg); }
152 #define JITC_IMUL_EAX_REG(jitc,reg)         { JITC_ADD_2UCHAR(jitc, 0xf7, 0xe8+reg); }
153 
154 /*#define JITC_SUB_REG_REG(jitc,dest,src)     { JITC_OP_REG_REG (jitc,0x29,dest,src); }
155 #define JITC_SUB_EAX_IMM32(jitc,imm32)      { JITC_ADD_UCHAR  (jitc,0x2d); JITC_ADD_UINT(jitc,(int)imm32); }
156 #define JITC_SUB_REG_IMM32(jitc,reg,imm32)  { JITC_ADD_2UCHAR (jitc,0x81, 0xe8+reg);\
157                                               JITC_ADD_UINT   (jitc,(int)imm32); }*/
158 #define JITC_SUB_REG_IMM8(jitc,reg,imm8)    { JITC_ADD_2UCHAR (jitc,0x83, 0xe8+reg);\
159                                               JITC_ADD_UCHAR(jitc,imm8); }
160 
161 /* Floating points */
162 
163 #define JITC_FLD_pIMM32(jitc,address)       { JITC_ADD_UCHAR  (jitc, 0xD9); \
164                                               JITC_MODRM      (jitc, 0x00, 0x00,JITC_RM_DISP32); \
165                                               JITC_ADD_UINT(jitc,(int)(address)); }
166 #define JITC_FLD_STi(jict,reg)              { JITC_ADD_2UCHAR (jitc, 0xD9, 0xC0+reg); }
167 
168 #define JITC_FST_pIMM32(jitc,address)       { JITC_ADD_UCHAR  (jitc, 0xD9); \
169                                               JITC_MODRM      (jitc, 0x00, 0x02,JITC_RM_DISP32); \
170                                               JITC_ADD_UINT(jitc,(int)(ADDRess)); }
171 #define JITC_FST_STi(jict,reg)              { JITC_ADD_2UCHAR (jitc, 0xDD, 0xD0+reg); }
172 
173 #define JITC_FSTP_pIMM32(jitc,address)      { JITC_ADD_UCHAR  (jitc, 0xD9); \
174                                               JITC_MODRM      (jitc, 0x00, 0x03, JITC_RM_DISP32); \
175                                               JITC_ADD_UINT(jitc,(int)(address)); }
176 #define JITC_FSTP_STi(jict,reg)             { JITC_ADD_2UCHAR (jitc, 0xDD, 0xD8+reg); }
177 
178 #define JITC_FADD
179 
180 /* Jumps */
181 
182 #define JITC_ADD_LABEL(jitc,label)          { jitc_add_known_label(jitc,label,jitc->used); }
183 
184 #define JITC_JUMP(jitc,offset)              { JITC_ADD_UCHAR(jitc,0xe9); JITC_ADD_UINT(jitc,offset); }
185 #define JITC_JUMP_LABEL(jitc,label)         { jitc_add_used_label(jitc,label,jitc->used+1); JITC_JUMP(jitc,0); }
186 #define JITC_JUMP_COND(jitc,cond,offset)    { JITC_ADD_UCHAR(jitc,0x0f);\
187                                               JITC_ADD_UCHAR(jitc,0x80+cond);\
188                                               JITC_ADD_UINT(jitc,offset); }
189 #define JITC_JUMP_COND_LABEL(jitc,cond,label) { jitc_add_used_label(jitc,label,jitc->used+2); JITC_JUMP_COND(jitc,cond,0); }
190 #define JITC_CALL(jitc,function)            { int __offset__ = (int)function - (int)(&jitc->memory[jitc->used+5]);\
191                                               JITC_ADD_UCHAR(jitc,0xe8); JITC_ADD_UINT(jitc,__offset__); }
192 /*#define JITC_CALL_pREG(jitc,reg)            { JITC_ADD_UCHAR(jitc,0xff); JITC_ADD_UCHAR(jitc,0xd0+reg); }
193 #define JITC_CALL_LABEL(jitc,label)         { jitc_add_used_label(jitc,label,jitc->used+1); JITC_CALL(jitc,0); }*/
194 
195 /* save all registers (except EAX,ESP,EBP) */
196 #define JITC_PUSH_ALL(jitc) { jitc_add(jitc,"push ecx"); jitc_add(jitc,"push edx"); jitc_add(jitc,"push ebx"); \
197                               jitc_add(jitc,"push esi"); jitc_add(jitc,"push edi"); }
198 
199 /* restore all registers (except EAX,ESP,EBP) */
200 #define JITC_POP_ALL(jitc)  { jitc_add(jitc,"pop edi"); jitc_add(jitc,"pop esi"); jitc_add(jitc,"pop ebx"); \
201                               jitc_add(jitc,"pop edx"); jitc_add(jitc,"pop ecx"); }
202 
203 /* public methods */
204 JitcX86Env *jitc_x86_env_new(int memory_size);
205 JitcFunc    jitc_prepare_func(JitcX86Env *jitc);
206 void        jitc_add(JitcX86Env *jitc, const char *instr, ...);
207 void        jitc_validate_func(JitcX86Env *jitc);
208 void        jitc_x86_delete(JitcX86Env *jitc);
209 
210 
211 /* private methods */
212 void jitc_add_used_label(JitcX86Env *jitc, char *label, int where);
213 void jitc_add_known_label(JitcX86Env *jitc, char *label, int where);
214 void jitc_resolve_labels(JitcX86Env *jitc);
215