1 /*
2 ===========================================================================
3 vm_x86_64_assembler.c -- assembler for x86-64
4
5 Copyright (C) 2007 Ludwig Nussel <ludwig.nussel@suse.de>, Novell inc.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27
28 typedef unsigned char u8;
29 typedef unsigned short u16;
30 typedef unsigned int u32;
31 typedef unsigned long u64;
32
33 static char* out;
34 static unsigned compiledOfs;
35 static unsigned assembler_pass;
36
37 static const char* cur_line;
38
39 static FILE* fout;
40
41 #define MIN(a,b) ((a) < (b) ? (a) : (b))
42 #define MAX(a,b) ((a) > (b) ? (a) : (b))
43
44 #define crap(fmt, args...) do { \
45 _crap(__FUNCTION__, fmt, ##args); \
46 } while(0)
47
48 #define CRAP_INVALID_ARGS crap("invalid arguments %s, %s", argtype2str(arg1.type),argtype2str(arg2.type));
49
50 #ifdef DEBUG
51 #define debug(fmt, args...) printf(fmt, ##args)
52 #else
53 #define debug(fmt, args...)
54 #endif
55
_crap(const char * func,const char * fmt,...)56 static void _crap(const char* func, const char* fmt, ...)
57 {
58 va_list ap;
59 fprintf(stderr, "%s() - ", func);
60 va_start(ap, fmt);
61 vfprintf(stderr, fmt, ap);
62 va_end(ap);
63 fputc('\n', stderr);
64 if(cur_line && cur_line[0])
65 fprintf(stderr, "-> %s\n", cur_line);
66 exit(1);
67 }
68
emit1(unsigned char v)69 static void emit1(unsigned char v)
70 {
71 if(assembler_pass)
72 {
73 out[compiledOfs++] = v;
74 if(fout) fwrite(&v, 1, 1, fout);
75 debug("%02hhx ", v);
76 }
77 else
78 {
79 ++compiledOfs;
80 }
81 }
82
emit2(u16 v)83 static inline void emit2(u16 v)
84 {
85 emit1(v&0xFF);
86 emit1((v>>8)&0xFF);
87 }
88
emit4(u32 v)89 static inline void emit4(u32 v)
90 {
91 emit1(v&0xFF);
92 emit1((v>>8)&0xFF);
93 emit1((v>>16)&0xFF);
94 emit1((v>>24)&0xFF);
95 }
96
emit8(u64 v)97 static inline void emit8(u64 v)
98 {
99 emit4(v&0xFFFFFFFF);
100 emit4((v>>32)&0xFFFFFFFF);
101 }
102
103 enum {
104 REX_W = 0x08,
105 REX_R = 0x04,
106 REX_X = 0x02,
107 REX_B = 0x01,
108 };
109
110 enum {
111 MODRM_MOD_00 = 0x00,
112 MODRM_MOD_01 = 0x01 << 6,
113 MODRM_MOD_10 = 0x02 << 6,
114 MODRM_MOD_11 = 0x03 << 6,
115 MODRM_RM_SIB = 0x04,
116 };
117
118 typedef enum
119 {
120 T_NONE = 0x00,
121 T_REGISTER = 0x01,
122 T_IMMEDIATE = 0x02,
123 T_MEMORY = 0x04,
124 T_LABEL = 0x08,
125 T_ABSOLUTE = 0x80
126 } argtype_t;
127
128 typedef enum {
129 R_8 = 0x100,
130 R_16 = 0x200,
131 R_64 = 0x800,
132 R_MSZ = 0xF00, // size mask
133 R_XMM = 0x2000, // xmm register. year, sucks
134 R_EAX = 0x00,
135 R_EBX = 0x03,
136 R_ECX = 0x01,
137 R_EDX = 0x02,
138 R_ESI = 0x06,
139 R_EDI = 0x07,
140 R_ESP = 0x04,
141 R_RAX = R_EAX | R_64,
142 R_RBX = R_EBX | R_64,
143 R_RCX = R_ECX | R_64,
144 R_RDX = R_EDX | R_64,
145 R_RSI = R_ESI | R_64,
146 R_RDI = R_EDI | R_64,
147 R_RSP = R_ESP | R_64,
148 R_R8 = 0x08 | R_64,
149 R_R9 = 0x09 | R_64,
150 R_R10 = 0x0A | R_64,
151 R_R15 = 0x0F | R_64,
152 R_AL = R_EAX | R_8,
153 R_AX = R_EAX | R_16,
154 R_CL = R_ECX | R_8,
155 R_XMM0 = 0x00 | R_XMM,
156 R_MGP = 0x0F, // mask for general purpose registers
157 } reg_t;
158
159 typedef enum {
160 MODRM_SIB = 0,
161 MODRM_NOSIB = 0x3,
162 } modrm_sib_t;
163
164 typedef struct {
165 unsigned disp;
166 argtype_t basetype;
167 union {
168 u64 imm;
169 reg_t reg;
170 } base;
171 argtype_t indextype;
172 union {
173 u64 imm;
174 reg_t reg;
175 } index;
176 unsigned scale;
177 } memref_t;
178
179 #define LABELLEN 32
180
181 typedef struct {
182 argtype_t type;
183 union {
184 u64 imm;
185 reg_t reg;
186 memref_t mem;
187 char label[LABELLEN];
188 } v;
189 int absolute:1;
190 } arg_t;
191
192 typedef void (*emitfunc)(const char* op, arg_t arg1, arg_t arg2, void* data);
193
194 typedef struct {
195 char* mnemonic;
196 emitfunc func;
197 void* data;
198 } op_t;
199
200 typedef struct {
201 u8 xmmprefix;
202 u8 subcode; // in modrm
203 u8 rmcode; // opcode for reg/mem, reg
204 u8 mrcode; // opcode for reg, reg/mem
205 u8 rcode8; // opcode for reg8/mem8
206 u8 rcode; // opcode for reg/mem
207 } opparam_t;
208
209 /* ************************* */
210
hashkey(const char * string,unsigned len)211 static unsigned hashkey(const char *string, unsigned len) {
212 unsigned register hash, i;
213
214 hash = 0;
215 for (i = 0; i < len && string[i] != '\0'; ++i) {
216 hash += string[i] * (119 + i);
217 }
218 hash = (hash ^ (hash >> 10) ^ (hash >> 20));
219 return hash;
220 }
221
222 struct hashentry {
223 char* label;
224 unsigned address;
225 struct hashentry* next;
226 };
227 static struct hashentry* labelhash[1021];
228
229 // no dup check!
hash_add_label(const char * label,unsigned address)230 static void hash_add_label(const char* label, unsigned address)
231 {
232 struct hashentry* h;
233 unsigned i = hashkey(label, -1U);
234 i %= sizeof(labelhash)/sizeof(labelhash[0]);
235 h = malloc(sizeof(struct hashentry));
236 h->label = strdup(label);
237 h->address = address;
238 h->next = labelhash[i];
239 labelhash[i] = h;
240 }
241
lookup_label(const char * label)242 static unsigned lookup_label(const char* label)
243 {
244 struct hashentry* h;
245 unsigned i = hashkey(label, -1U);
246 i %= sizeof(labelhash)/sizeof(labelhash[0]);
247 for(h = labelhash[i]; h; h = h->next )
248 {
249 if(!strcmp(h->label, label))
250 return h->address;
251 }
252 if(assembler_pass)
253 crap("label %s undefined", label);
254 return 0;
255 }
256
labelhash_free(void)257 static void labelhash_free(void)
258 {
259 struct hashentry* h;
260 unsigned i;
261 unsigned z = 0, min = -1U, max = 0, t = 0;
262 for ( i = 0; i < sizeof(labelhash)/sizeof(labelhash[0]); ++i)
263 {
264 unsigned n = 0;
265 h = labelhash[i];
266 while(h)
267 {
268 struct hashentry* next = h->next;
269 free(h->label);
270 free(h);
271 h = next;
272 ++n;
273 }
274 t+=n;
275 if(!n) ++z;
276 //else printf("%u\n", n);
277 min = MIN(min, n);
278 max = MAX(max, n);
279 }
280 printf("total %u, hsize %lu, zero %u, min %u, max %u\n", t, sizeof(labelhash)/sizeof(labelhash[0]), z, min, max);
281 memset(labelhash, 0, sizeof(labelhash));
282 }
283
284 /* ************************* */
285
286
argtype2str(argtype_t t)287 static const char* argtype2str(argtype_t t)
288 {
289 switch(t)
290 {
291 case T_NONE: return "none";
292 case T_REGISTER: return "register";
293 case T_IMMEDIATE: return "immediate";
294 case T_MEMORY: return "memory";
295 case T_LABEL: return "label";
296 default: crap("invalid type");
297 }
298 /* not reached */
299 return T_NONE;
300 }
301
302 /* ************************* */
303
iss8(u64 v)304 static inline int iss8(u64 v)
305 {
306 return (labs(v) <= 0x80);
307 }
308
isu8(u64 v)309 static inline int isu8(u64 v)
310 {
311 return (v <= 0xff);
312 }
313
iss16(u64 v)314 static inline int iss16(u64 v)
315 {
316 return (labs(v) <= 0x8000);
317 }
318
isu16(u64 v)319 static inline int isu16(u64 v)
320 {
321 return (v <= 0xffff);
322 }
323
iss32(u64 v)324 static inline int iss32(u64 v)
325 {
326 return (labs(v) <= 0x80000000);
327 }
328
isu32(u64 v)329 static inline int isu32(u64 v)
330 {
331 return (v <= 0xffffffff);
332 }
333
emit_opsingle(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)334 static void emit_opsingle(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
335 {
336 u8 op = (u8)((unsigned long) data);
337
338 if(arg1.type != T_NONE || arg2.type != T_NONE)
339 CRAP_INVALID_ARGS;
340
341 emit1(op);
342 }
343
emit_opsingle16(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)344 static void emit_opsingle16(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
345 {
346 emit1(0x66);
347 emit_opsingle(mnemonic, arg1, arg2, data);
348 }
349
compute_rexmodrmsib(u8 * rex_r,u8 * modrm_r,u8 * sib_r,arg_t * arg1,arg_t * arg2)350 static void compute_rexmodrmsib(u8* rex_r, u8* modrm_r, u8* sib_r, arg_t* arg1, arg_t* arg2)
351 {
352 u8 rex = 0;
353 u8 modrm = 0;
354 u8 sib = 0;
355
356 if((arg1->type == T_REGISTER && arg2->type == T_REGISTER)
357 && ((arg1->v.reg & R_MSZ) != (arg2->v.reg & R_MSZ))
358 && !((arg1->v.reg & R_XMM) || (arg2->v.reg & R_XMM)))
359 crap("both registers must be of same width");
360
361 if((arg1->type == T_REGISTER && arg1->v.reg & R_64)
362 || (arg2->type == T_REGISTER && arg2->v.reg & R_64))
363 {
364 rex |= REX_W;
365 }
366
367 if(arg1->type == T_REGISTER)
368 {
369 if((arg1->v.reg & R_MGP) > 0x07)
370 rex |= REX_R;
371
372 modrm |= (arg1->v.reg & 0x07) << 3;
373 }
374
375 if(arg2->type == T_REGISTER)
376 {
377 if((arg2->v.reg & R_MGP) > 0x07)
378 rex |= REX_B;
379
380 modrm |= (arg2->v.reg & 0x07);
381 }
382
383 if(arg2->type == T_MEMORY)
384 {
385 if((arg2->v.mem.basetype == T_REGISTER && !(arg2->v.mem.base.reg & R_64))
386 || (arg2->v.mem.indextype == T_REGISTER && !(arg2->v.mem.index.reg & R_64)))
387 {
388 crap("only 64bit base/index registers are %x %x", arg2->v.mem.base.reg, arg2->v.mem.index.reg);
389 }
390
391 if(arg2->v.mem.indextype == T_REGISTER)
392 {
393 modrm |= MODRM_RM_SIB;
394 if(!arg2->v.mem.disp)
395 {
396 modrm |= MODRM_MOD_00;
397 }
398 else if(iss8(arg2->v.mem.disp))
399 {
400 modrm |= MODRM_MOD_01;
401 }
402 else if(isu32(arg2->v.mem.disp))
403 {
404 modrm |= MODRM_MOD_10;
405 }
406 else
407 {
408 crap("invalid displacement");
409 }
410
411 if((arg2->v.mem.index.reg & R_MGP) > 0x07)
412 rex |= REX_X;
413
414 if((arg2->v.mem.base.reg & R_MGP) > 0x07)
415 rex |= REX_B;
416
417 if(arg2->v.mem.basetype != T_REGISTER)
418 crap("base must be register");
419 switch(arg2->v.mem.scale)
420 {
421 case 1: break;
422 case 2: sib |= 1 << 6; break;
423 case 4: sib |= 2 << 6; break;
424 case 8: sib |= 3 << 6; break;
425 }
426 sib |= (arg2->v.mem.index.reg & 0x07) << 3;
427 sib |= (arg2->v.mem.base.reg & 0x07);
428 }
429 else if(arg2->v.mem.indextype == T_NONE)
430 {
431 if(!arg2->v.mem.disp)
432 {
433 modrm |= MODRM_MOD_00;
434 }
435 else if(iss8(arg2->v.mem.disp))
436 {
437 modrm |= MODRM_MOD_01;
438 }
439 else if(isu32(arg2->v.mem.disp))
440 {
441 modrm |= MODRM_MOD_10;
442 }
443 else
444 {
445 crap("invalid displacement");
446 }
447
448 if(arg2->v.mem.basetype != T_REGISTER)
449 crap("todo: base != register");
450
451 if((arg2->v.mem.base.reg & R_MGP) > 0x07)
452 rex |= REX_B;
453
454 modrm |= arg2->v.mem.base.reg & 0x07;
455 }
456 else
457 {
458 crap("invalid indextype");
459 }
460 }
461 else
462 {
463 modrm |= MODRM_MOD_11;
464 }
465
466 if(rex)
467 rex |= 0x40; // XXX
468
469 *rex_r = rex;
470 *modrm_r = modrm;
471 *sib_r = sib;
472 }
473
maybe_emit_displacement(arg_t * arg)474 static void maybe_emit_displacement(arg_t* arg)
475 {
476 if(arg->type != T_MEMORY)
477 return;
478
479 if(arg->v.mem.disp)
480 {
481 if(iss8(arg->v.mem.disp))
482 {
483 emit1((u8)arg->v.mem.disp);
484 }
485 else if(isu32(arg->v.mem.disp))
486 {
487 emit4(arg->v.mem.disp);
488 }
489 else
490 {
491 crap("invalid displacement");
492 }
493 }
494 }
495
496 /* one byte operator with register added to operator */
emit_opreg(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)497 static void emit_opreg(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
498 {
499 u8 op = (u8)((unsigned long) data);
500
501 if(arg1.type != T_REGISTER || arg2.type != T_NONE)
502 CRAP_INVALID_ARGS;
503
504 if((arg1.v.reg & R_MGP) > 0x07)
505 emit1(0x40 | REX_B);
506
507 op |= (arg1.v.reg & 0x07);
508
509 emit1(op);
510 }
511
512 /* operator which operates on reg/mem */
emit_op_rm(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)513 static void emit_op_rm(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
514 {
515 u8 rex, modrm, sib;
516 opparam_t* params = data;
517
518 if((arg1.type != T_REGISTER && arg1.type != T_MEMORY) || arg2.type != T_NONE)
519 CRAP_INVALID_ARGS;
520
521 compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
522
523 modrm |= params->subcode << 3;
524
525 if(arg1.v.reg & R_16)
526 emit1(0x66);
527
528 if(rex) emit1(rex);
529 if(arg1.v.reg & R_8)
530 emit1(params->rcode8); // op reg8/mem8,
531 else
532 emit1(params->rcode); // op reg/mem,
533 emit1(modrm);
534 if((modrm & 0x07) == MODRM_RM_SIB)
535 emit1(sib);
536
537 maybe_emit_displacement(&arg1);
538 }
539
540 /* operator which operates on reg/mem with cl */
emit_op_rm_cl(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)541 static void emit_op_rm_cl(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
542 {
543 u8 rex, modrm, sib;
544 opparam_t* params = data;
545
546 if(arg2.type != T_REGISTER || arg1.type != T_REGISTER)
547 CRAP_INVALID_ARGS;
548
549 if((arg1.v.reg & R_MGP) != R_ECX && !(arg1.v.reg & R_8))
550 crap("only cl register is valid");
551
552 arg1.type = T_NONE; // don't complain, we know it's cl anyways
553
554 compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
555
556 modrm |= params->subcode << 3;
557
558 if(arg2.v.reg & R_16)
559 emit1(0x66);
560
561 if(rex) emit1(rex);
562 if(arg2.v.reg & R_8)
563 emit1(params->rcode8); // op reg8/mem8,
564 else
565 emit1(params->rcode); // op reg/mem,
566 emit1(modrm);
567 if((modrm & 0x07) == MODRM_RM_SIB)
568 emit1(sib);
569
570 maybe_emit_displacement(&arg2);
571 }
572
emit_mov(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)573 static void emit_mov(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
574 {
575 u8 rex = 0;
576 u8 modrm = 0;
577 u8 sib = 0;
578
579 if(arg1.type == T_IMMEDIATE && arg2.type == T_REGISTER)
580 {
581 u8 op = 0xb8;
582
583 if(arg2.v.reg & R_8)
584 {
585 if(!isu8(arg1.v.imm))
586 crap("value too large for 8bit register");
587
588 op = 0xb0;
589 }
590 else if(arg2.v.reg & R_16)
591 {
592 if(!isu16(arg1.v.imm))
593 crap("value too large for 16bit register");
594 emit1(0x66);
595 }
596 else if(!arg2.v.reg & R_64)
597 {
598 if(!isu32(arg1.v.imm))
599 crap("value too large for 32bit register");
600 }
601
602 compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
603
604 if(rex) emit1(rex);
605
606 op |= (arg2.v.reg & 0x07);
607
608 emit1(op);
609
610 if(arg2.v.reg & R_8) emit1(arg1.v.imm);
611 else if(arg2.v.reg & R_16) emit2(arg1.v.imm);
612 else if(arg2.v.reg & R_64) emit8(arg1.v.imm);
613 else emit4(arg1.v.imm);
614 }
615 else if(arg1.type == T_IMMEDIATE && arg2.type == T_MEMORY)
616 {
617 if(!iss32(arg1.v.imm))
618 {
619 crap("only 32bit immediates supported");
620 }
621
622 compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
623 if(rex) emit1(rex);
624 emit1(0xc7); // mov reg/mem, imm
625 emit1(modrm);
626 if((modrm & 0x07) == MODRM_RM_SIB)
627 emit1(sib);
628
629 emit4(arg1.v.imm);
630 }
631 else if(arg1.type == T_REGISTER && arg2.type == T_REGISTER) // XXX: same as next
632 {
633 if(arg1.type != T_REGISTER || arg2.type != T_REGISTER)
634 crap("both args must be registers");
635
636 if((arg1.v.reg & R_MSZ) != (arg2.v.reg & R_MSZ))
637 crap("both registers must be same width");
638
639 compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
640
641 if(rex) emit1(rex);
642 emit1(0x89); // mov reg reg/mem,
643 emit1(modrm);
644 }
645 else if(arg1.type == T_REGISTER && arg2.type == T_MEMORY)
646 {
647 compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
648
649 if(arg1.v.reg & R_16)
650 emit1(0x66);
651
652 if(rex) emit1(rex);
653 if(arg1.v.reg & R_8)
654 emit1(0x88); // mov reg reg/mem,
655 else
656 emit1(0x89); // mov reg reg/mem,
657 emit1(modrm);
658 if((modrm & 0x07) == MODRM_RM_SIB)
659 emit1(sib);
660
661 maybe_emit_displacement(&arg2);
662 }
663 else if(arg1.type == T_MEMORY && arg2.type == T_REGISTER)
664 {
665 compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
666
667 if(arg2.v.reg & R_16)
668 emit1(0x66);
669
670 if(rex) emit1(rex);
671 if(arg2.v.reg & R_8)
672 emit1(0x8a); // mov reg/mem, reg
673 else
674 emit1(0x8b); // mov reg/mem, reg
675 emit1(modrm);
676 if((modrm & 0x07) == MODRM_RM_SIB)
677 emit1(sib);
678
679 maybe_emit_displacement(&arg1);
680 }
681 else
682 CRAP_INVALID_ARGS;
683 }
684
emit_subaddand(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)685 static void emit_subaddand(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
686 {
687 u8 rex = 0;
688 u8 modrm = 0;
689 u8 sib = 0;
690
691 opparam_t* params = data;
692
693 if(arg1.type == T_IMMEDIATE && arg2.type == T_REGISTER)
694 {
695 if(!iss32(arg1.v.imm))
696 {
697 crap("only 8 and 32 bit immediates supported");
698 }
699
700 compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
701
702 modrm |= params->subcode << 3;
703
704 if(rex) emit1(rex);
705 #if 0
706 if(isu8(arg1.v.imm))
707 {
708 emit1(0x83); // sub reg/mem, imm8
709 emit1(modrm);
710 emit1(arg1.v.imm&0xFF);
711 }
712 else
713 #endif
714 {
715 emit1(0x81); // sub reg/mem, imm32
716 emit1(modrm);
717 emit4(arg1.v.imm);
718 }
719 }
720 else if(arg1.type == T_REGISTER && (arg2.type == T_MEMORY || arg2.type == T_REGISTER))
721 {
722 compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
723
724 if(rex) emit1(rex);
725 emit1(params->rmcode); // sub reg/mem, reg
726 emit1(modrm);
727 if(arg2.type == T_MEMORY && (modrm & 0x07) == MODRM_RM_SIB)
728 emit1(sib);
729
730 maybe_emit_displacement(&arg2);
731 }
732 else if(arg1.type == T_MEMORY && arg2.type == T_REGISTER && params->mrcode)
733 {
734 compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
735
736 if(rex) emit1(rex);
737 emit1(params->mrcode); // sub reg, reg/mem
738 emit1(modrm);
739 if((modrm & 0x07) == MODRM_RM_SIB)
740 emit1(sib);
741
742 maybe_emit_displacement(&arg1);
743 }
744 else
745 CRAP_INVALID_ARGS;
746 }
747
emit_condjump(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)748 static void emit_condjump(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
749 {
750 unsigned off;
751 int disp;
752 unsigned char opcode = (unsigned char)(((unsigned long)data)&0xFF);
753
754 if(arg1.type != T_LABEL || arg2.type != T_NONE)
755 crap("%s: argument must be label", mnemonic);
756
757 emit1(opcode);
758
759 off = lookup_label(arg1.v.label);
760 disp = off-(compiledOfs+1);
761 if(assembler_pass && abs(disp) > 127)
762 crap("cannot jump that far (%x -> %x = %x)", compiledOfs, off, disp);
763
764 emit1(disp);
765 }
766
emit_jmp(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)767 static void emit_jmp(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
768 {
769 if((arg1.type != T_LABEL && arg1.type != T_REGISTER && arg1.type != T_MEMORY) || arg2.type != T_NONE)
770 CRAP_INVALID_ARGS;
771
772 if(arg1.type == T_LABEL)
773 {
774 unsigned off;
775 int disp;
776
777 off = lookup_label(arg1.v.label);
778 disp = off-(compiledOfs+5);
779 emit1(0xe9);
780 emit4(disp);
781 }
782 else
783 {
784 u8 rex, modrm, sib;
785
786 if(arg1.type == T_REGISTER)
787 {
788 if(!arg1.absolute)
789 crap("jmp must be absolute");
790
791 if((arg1.v.reg & R_64) != R_64)
792 crap("register must be 64bit");
793
794 arg1.v.reg ^= R_64; // no rex required for call
795 }
796
797 compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
798
799 modrm |= 0x4 << 3;
800
801 if(rex) emit1(rex);
802 emit1(0xff);
803 emit1(modrm);
804 if((modrm & 0x07) == MODRM_RM_SIB)
805 emit1(sib);
806 maybe_emit_displacement(&arg1);
807 }
808 }
809
emit_call(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)810 static void emit_call(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
811 {
812 u8 rex, modrm, sib;
813
814 if(arg1.type != T_REGISTER || arg2.type != T_NONE)
815 CRAP_INVALID_ARGS;
816
817 if(!arg1.absolute)
818 crap("call must be absolute");
819
820 if((arg1.v.reg & R_64) != R_64)
821 crap("register must be 64bit");
822
823 arg1.v.reg ^= R_64; // no rex required for call
824
825 compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
826
827 modrm |= 0x2 << 3;
828
829 if(rex) emit1(rex);
830 emit1(0xff);
831 emit1(modrm);
832 }
833
834
emit_twobyte(const char * mnemonic,arg_t arg1,arg_t arg2,void * data)835 static void emit_twobyte(const char* mnemonic, arg_t arg1, arg_t arg2, void* data)
836 {
837 u8 rex, modrm, sib;
838
839 opparam_t* params = data;
840
841 if(arg1.type == T_REGISTER && (arg2.type == T_MEMORY || arg2.type == T_REGISTER))
842 {
843 compute_rexmodrmsib(&rex, &modrm, &sib, &arg1, &arg2);
844
845 if(params->xmmprefix) emit1(params->xmmprefix);
846 if(rex) emit1(rex);
847 emit1(0x0f);
848 emit1(params->rmcode); // sub reg/mem, reg
849 emit1(modrm);
850 if((modrm & 0x07) == MODRM_RM_SIB)
851 emit1(sib);
852
853 maybe_emit_displacement(&arg2);
854 }
855 else if(arg1.type == T_MEMORY && arg2.type == T_REGISTER && params->mrcode)
856 {
857 compute_rexmodrmsib(&rex, &modrm, &sib, &arg2, &arg1);
858
859 if(params->xmmprefix) emit1(params->xmmprefix);
860 if(rex) emit1(rex);
861 emit1(0x0f);
862 emit1(params->mrcode); // sub reg, reg/mem
863 emit1(modrm);
864 if((modrm & 0x07) == MODRM_RM_SIB)
865 emit1(sib);
866
867 maybe_emit_displacement(&arg1);
868 }
869 else
870 CRAP_INVALID_ARGS;
871 }
872
873 static opparam_t params_add = { subcode: 0, rmcode: 0x01, };
874 static opparam_t params_or = { subcode: 1, rmcode: 0x09, };
875 static opparam_t params_and = { subcode: 4, rmcode: 0x21, };
876 static opparam_t params_sub = { subcode: 5, rmcode: 0x29, };
877 static opparam_t params_xor = { subcode: 6, rmcode: 0x31, };
878 static opparam_t params_cmp = { subcode: 6, rmcode: 0x39, mrcode: 0x3b, };
879 static opparam_t params_dec = { subcode: 1, rcode: 0xff, rcode8: 0xfe, };
880 static opparam_t params_sar = { subcode: 7, rcode: 0xd3, rcode8: 0xd2, };
881 static opparam_t params_shl = { subcode: 4, rcode: 0xd3, rcode8: 0xd2, };
882 static opparam_t params_shr = { subcode: 5, rcode: 0xd3, rcode8: 0xd2, };
883 static opparam_t params_idiv = { subcode: 7, rcode: 0xf7, rcode8: 0xf6, };
884 static opparam_t params_div = { subcode: 6, rcode: 0xf7, rcode8: 0xf6, };
885 static opparam_t params_imul = { subcode: 5, rcode: 0xf7, rcode8: 0xf6, };
886 static opparam_t params_mul = { subcode: 4, rcode: 0xf7, rcode8: 0xf6, };
887 static opparam_t params_neg = { subcode: 3, rcode: 0xf7, rcode8: 0xf6, };
888 static opparam_t params_not = { subcode: 2, rcode: 0xf7, rcode8: 0xf6, };
889
890 static opparam_t params_cvtsi2ss = { xmmprefix: 0xf3, rmcode: 0x2a };
891 static opparam_t params_cvttss2si = { xmmprefix: 0xf3, rmcode: 0x2c };
892 static opparam_t params_addss = { xmmprefix: 0xf3, mrcode: 0x58 };
893 static opparam_t params_divss = { xmmprefix: 0xf3, mrcode: 0x5e };
894 static opparam_t params_movss = { xmmprefix: 0xf3, mrcode: 0x10, rmcode: 0x11 };
895 static opparam_t params_mulss = { xmmprefix: 0xf3, mrcode: 0x59 };
896 static opparam_t params_subss = { xmmprefix: 0xf3, mrcode: 0x5c };
897 static opparam_t params_ucomiss = { mrcode: 0x2e };
898
899 static int ops_sorted = 0;
900 static op_t ops[] = {
901 { "addl", emit_subaddand, ¶ms_add },
902 { "addq", emit_subaddand, ¶ms_add },
903 { "addss", emit_twobyte, ¶ms_addss },
904 { "andl", emit_subaddand, ¶ms_and },
905 { "andq", emit_subaddand, ¶ms_and },
906 { "callq", emit_call, NULL },
907 { "cbw", emit_opsingle16, (void*)0x98 },
908 { "cdq", emit_opsingle, (void*)0x99 },
909 { "cmpl", emit_subaddand, ¶ms_cmp },
910 { "cmpq", emit_subaddand, ¶ms_cmp },
911 { "cvtsi2ss", emit_twobyte, ¶ms_cvtsi2ss },
912 { "cvttss2si", emit_twobyte, ¶ms_cvttss2si },
913 { "cwde", emit_opsingle, (void*)0x98 },
914 { "decl", emit_op_rm, ¶ms_dec },
915 { "decq", emit_op_rm, ¶ms_dec },
916 { "divl", emit_op_rm, ¶ms_div },
917 { "divq", emit_op_rm, ¶ms_div },
918 { "divss", emit_twobyte, ¶ms_divss },
919 { "idivl", emit_op_rm, ¶ms_idiv },
920 { "imull", emit_op_rm, ¶ms_imul },
921 { "int3", emit_opsingle, (void*)0xcc },
922 { "ja", emit_condjump, (void*)0x77 },
923 { "jbe", emit_condjump, (void*)0x76 },
924 { "jb", emit_condjump, (void*)0x72 },
925 { "je", emit_condjump, (void*)0x74 },
926 { "jl", emit_condjump, (void*)0x7c },
927 { "jmp", emit_jmp, NULL },
928 { "jmpq", emit_jmp, NULL },
929 { "jnae", emit_condjump, (void*)0x72 },
930 { "jna", emit_condjump, (void*)0x76 },
931 { "jnbe", emit_condjump, (void*)0x77 },
932 { "jnb", emit_condjump, (void*)0x73 },
933 { "jnc", emit_condjump, (void*)0x73 },
934 { "jne", emit_condjump, (void*)0x75 },
935 { "jnge", emit_condjump, (void*)0x7c },
936 { "jng", emit_condjump, (void*)0x7e },
937 { "jnle", emit_condjump, (void*)0x7f },
938 { "jnl", emit_condjump, (void*)0x7d },
939 { "jnz", emit_condjump, (void*)0x75 },
940 { "jp", emit_condjump, (void*)0x7a },
941 { "jz", emit_condjump, (void*)0x74 },
942 { "movb", emit_mov, NULL },
943 { "movl", emit_mov, NULL },
944 { "movq", emit_mov, NULL },
945 { "movss", emit_twobyte, ¶ms_movss },
946 { "movw", emit_mov, NULL },
947 { "mull", emit_op_rm, ¶ms_mul },
948 { "mulss", emit_twobyte, ¶ms_mulss },
949 { "negl", emit_op_rm, ¶ms_neg },
950 { "negq", emit_op_rm, ¶ms_neg },
951 { "nop", emit_opsingle, (void*)0x90 },
952 { "notl", emit_op_rm, ¶ms_not },
953 { "notq", emit_op_rm, ¶ms_not },
954 { "or", emit_subaddand, ¶ms_or },
955 { "orl", emit_subaddand, ¶ms_or },
956 { "pop", emit_opreg, (void*)0x58 },
957 { "push", emit_opreg, (void*)0x50 },
958 { "ret", emit_opsingle, (void*)0xc3 },
959 { "sarl", emit_op_rm_cl, ¶ms_sar },
960 { "shl", emit_op_rm_cl, ¶ms_shl },
961 { "shrl", emit_op_rm_cl, ¶ms_shr },
962 { "subl", emit_subaddand, ¶ms_sub },
963 { "subq", emit_subaddand, ¶ms_sub },
964 { "subss", emit_twobyte, ¶ms_subss },
965 { "ucomiss", emit_twobyte, ¶ms_ucomiss },
966 { "xorl", emit_subaddand, ¶ms_xor },
967 { "xorq", emit_subaddand, ¶ms_xor },
968 { NULL, NULL, NULL }
969 };
970
opsort(const void * A,const void * B)971 static int opsort(const void* A, const void* B)
972 {
973 const op_t* a = A;
974 const op_t* b = B;
975 return strcmp(a->mnemonic, b->mnemonic);
976 }
977
getop(const char * n)978 static op_t* getop(const char* n)
979 {
980 #if 0
981 op_t* o = ops;
982 while(o->mnemonic)
983 {
984 if(!strcmp(o->mnemonic, n))
985 return o;
986 ++o;
987 }
988
989 #else
990 unsigned m, t, b;
991 int r;
992 t = sizeof(ops)/sizeof(ops[0])-1;
993 b = 0;
994
995 while(b <= t)
996 {
997 m = ((t-b)>>1) + b;
998 if((r = strcmp(ops[m].mnemonic, n)) == 0)
999 {
1000 return &ops[m];
1001 }
1002 else if(r < 0)
1003 {
1004 b = m + 1;
1005 }
1006 else
1007 {
1008 t = m - 1;
1009 }
1010 }
1011 #endif
1012
1013 return NULL;
1014 }
1015
parsereg(const char * str)1016 static reg_t parsereg(const char* str)
1017 {
1018 const char* s = str;
1019 if(*s == 'a' && s[1] == 'l' && !s[2])
1020 {
1021 return R_AL;
1022 }
1023 else if(*s == 'a' && s[1] == 'x' && !s[2])
1024 {
1025 return R_AX;
1026 }
1027 if(*s == 'c' && s[1] == 'l' && !s[2])
1028 {
1029 return R_CL;
1030 }
1031 if(*s == 'x')
1032 {
1033 if(!strcmp(s, "xmm0"))
1034 return R_XMM0;
1035 }
1036 else if(*s == 'r' && s[1])
1037 {
1038 ++s;
1039 if(s[1] == 'x')
1040 {
1041 switch(*s++)
1042 {
1043 case 'a': return R_RAX;
1044 case 'b': return R_RBX;
1045 case 'c': return R_RCX;
1046 case 'd': return R_RDX;
1047 }
1048 }
1049 else if(s[1] == 'i')
1050 {
1051 switch(*s++)
1052 {
1053 case 's': return R_RSI;
1054 case 'd': return R_RDI;
1055 }
1056 }
1057 else if(s[0] == 's' && s[1] == 'p' && !s[2])
1058 {
1059 return R_RSP;
1060 }
1061 else if(*s == '8' && !s[1])
1062 return R_R8;
1063 else if(*s == '9' && !s[1])
1064 return R_R9;
1065 else if(*s == '1' && s[1] == '0')
1066 return R_R10;
1067 else if(*s == '1' && s[1] == '5')
1068 return R_R15;
1069 }
1070 else if(*s == 'e' && s[1])
1071 {
1072 ++s;
1073 if(s[1] == 'x')
1074 {
1075 switch(*s++)
1076 {
1077 case 'a': return R_EAX;
1078 case 'b': return R_EBX;
1079 case 'c': return R_ECX;
1080 case 'd': return R_EDX;
1081 }
1082 }
1083 else if(s[1] == 'i')
1084 {
1085 switch(*s++)
1086 {
1087 case 's': return R_ESI;
1088 case 'd': return R_EDI;
1089 }
1090 }
1091 }
1092
1093 crap("invalid register %s", str);
1094
1095 return 0;
1096 }
1097
1098 typedef enum {
1099 TOK_LABEL = 0x80,
1100 TOK_INT = 0x81,
1101 TOK_END = 0x82,
1102 TOK_INVALID = 0x83,
1103 } token_t;
1104
nexttok(const char ** str,char * label,u64 * val)1105 static unsigned char nexttok(const char** str, char* label, u64* val)
1106 {
1107 const char* s = *str;
1108
1109 if(label) *label = 0;
1110 if(val) *val = 0;
1111
1112 while(*s && *s == ' ') ++s;
1113
1114 if(!*s)
1115 {
1116 return TOK_END;
1117 }
1118 else if(*s == '$' || *s == '*' || *s == '%' || *s == '-' || *s == ')' || *s == '(' || *s == ',')
1119 {
1120 *str = s+1;
1121 return *s;
1122 }
1123 else if(*s >= 'a' && *s <= 'z')
1124 {
1125 size_t a = strspn(s+1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
1126 if(a+1 >= LABELLEN)
1127 crap("label %s too long", s);
1128 if(label)
1129 {
1130 strncpy(label, s, a+1);
1131 label[a+1] = 0;
1132 }
1133 *str = s+a+1;
1134 return TOK_LABEL;
1135 }
1136 else if(*s >= '0' && *s <= '9')
1137 {
1138 char* endptr = NULL;
1139 u64 v = strtol(s, &endptr, 0);
1140 if(endptr && (endptr-s == 0))
1141 crap("invalid integer %s", s);
1142 if(val) *val = v;
1143 *str = endptr;
1144 return TOK_INT;
1145 }
1146 crap("can't parse '%s'", *str);
1147 return TOK_INVALID;
1148 }
1149
parsearg(const char ** str)1150 static arg_t parsearg(const char** str)
1151 {
1152 arg_t arg;
1153 const char* s = *str;
1154 char label[20];
1155 u64 val;
1156 int negative = 1;
1157 unsigned ttype;
1158
1159 arg.type = T_NONE;
1160 arg.absolute = 0;
1161
1162 while(*s && *s == ' ') ++s;
1163
1164 switch(nexttok(&s, label, &val))
1165 {
1166 case '$' :
1167 ttype = nexttok(&s, NULL, &val);
1168 if(ttype == '-')
1169 {
1170 negative = -1;
1171 ttype = nexttok(&s, NULL, &val);
1172 }
1173 if(ttype != TOK_INT)
1174 crap("expected integer");
1175 arg.type = T_IMMEDIATE;
1176 arg.v.imm = negative * val;
1177 break;
1178 case '*' :
1179 if((ttype = nexttok(&s, NULL, NULL)) != '%')
1180 {
1181 if(ttype == '(')
1182 goto tok_memory;
1183 crap("expected '%%'");
1184 }
1185 arg.absolute = 1;
1186 /* fall through */
1187 case '%' :
1188 if(nexttok(&s, label, &val) != TOK_LABEL)
1189 crap("expected label");
1190 arg.type = T_REGISTER;
1191 arg.v.reg = parsereg(label);
1192 break;
1193 case TOK_LABEL:
1194 arg.type = T_LABEL;
1195 strncpy(arg.v.label, label, LABELLEN);
1196 break;
1197 case '-':
1198 negative = -1;
1199 if(nexttok(&s, NULL, &val) != TOK_INT)
1200 crap("expected integer");
1201 /* fall through */
1202 case TOK_INT:
1203 if(nexttok(&s, label, NULL) != '(')
1204 crap("expected '('"); // mov to/from fixed address not supported
1205 /* fall through */
1206 case '(':
1207 tok_memory:
1208 arg.type = T_MEMORY;
1209 arg.v.mem.indextype = T_NONE;
1210 arg.v.mem.disp = negative * val;
1211 ttype = nexttok(&s, label, &val);
1212 if(ttype == '%' && nexttok(&s, label, &val) != TOK_LABEL)
1213 {
1214 crap("expected register");
1215 }
1216 if (ttype == '%')
1217 {
1218 arg.v.mem.basetype = T_REGISTER;
1219 arg.v.mem.base.reg = parsereg(label);
1220 }
1221 else if (ttype == TOK_INT)
1222 {
1223 arg.v.mem.basetype = T_IMMEDIATE;
1224 arg.v.mem.base.imm = val;
1225 }
1226 if((ttype = nexttok(&s, NULL, NULL)) == ',')
1227 {
1228 ttype = nexttok(&s, label, &val);
1229 if(ttype == '%' && nexttok(&s, label, &val) != TOK_LABEL)
1230 {
1231 crap("expected register");
1232 }
1233 if (ttype == '%')
1234 {
1235 arg.v.mem.indextype = T_REGISTER;
1236 arg.v.mem.index.reg = parsereg(label);
1237 }
1238 else if (ttype == TOK_INT)
1239 {
1240 crap("index must be register");
1241 arg.v.mem.indextype = T_IMMEDIATE;
1242 arg.v.mem.index.imm = val;
1243 }
1244 if(nexttok(&s, NULL, NULL) != ',')
1245 crap("expected ','");
1246 if(nexttok(&s, NULL, &val) != TOK_INT)
1247 crap("expected integer");
1248 if(val != 1 && val != 2 && val != 4 && val != 8)
1249 crap("scale must 1, 2, 4 or 8");
1250 arg.v.mem.scale = val;
1251
1252 ttype = nexttok(&s, NULL, NULL);
1253 }
1254 if(ttype != ')')
1255 {
1256 crap("expected ')' or ','");
1257 }
1258 break;
1259 default:
1260 crap("invalid token %hhu in %s", *(unsigned char*)s, *str);
1261 break;
1262 }
1263
1264 *str = s;
1265
1266 return arg;
1267 }
1268
1269 /* ************************* */
1270
assembler_init(int pass)1271 void assembler_init(int pass)
1272 {
1273 compiledOfs = 0;
1274 assembler_pass = pass;
1275 if(!pass)
1276 {
1277 labelhash_free();
1278 cur_line = NULL;
1279 }
1280 if(!ops_sorted)
1281 {
1282 ops_sorted = 1;
1283 qsort(ops, sizeof(ops)/sizeof(ops[0])-1, sizeof(ops[0]), opsort);
1284 }
1285 }
1286
assembler_get_code_size(void)1287 size_t assembler_get_code_size(void)
1288 {
1289 return compiledOfs;
1290 }
1291
assembler_set_output(char * buf)1292 void assembler_set_output(char* buf)
1293 {
1294 out = buf;
1295 }
1296
assemble_line(const char * input,size_t len)1297 void assemble_line(const char* input, size_t len)
1298 {
1299 char line[4096];
1300 char* s;
1301 op_t* o;
1302 char* opn;
1303 arg_t arg1, arg2;
1304
1305 arg1.type = T_NONE;
1306 arg2.type = T_NONE;
1307 opn = NULL;
1308 o = NULL;
1309
1310 if(len < 1)
1311 return;
1312
1313 if(len >= sizeof(line))
1314 crap("line too long");
1315
1316 memcpy(line, input, sizeof(line));
1317 cur_line = input;
1318
1319 if(line[len-1] == '\n') line[--len] = 0;
1320 if(line[len-1] == ':')
1321 {
1322 line[--len] = 0;
1323 if(assembler_pass)
1324 debug("%s: 0x%x\n", line, compiledOfs);
1325 else
1326 hash_add_label(line, compiledOfs);
1327 }
1328 else
1329 {
1330 opn = line;
1331 s = strchr(line, ' ');
1332 if(s)
1333 {
1334 *s++ = 0;
1335 arg1 = parsearg((const char**)&s);
1336 if(*s)
1337 {
1338 if(*s != ',')
1339 crap("expected ',', got '%c'", *s);
1340 ++s;
1341 arg2 = parsearg((const char**)&s);
1342 }
1343 }
1344
1345 if(!opn)
1346 {
1347 crap("no operator in %s", line);
1348 }
1349
1350 o = getop(opn);
1351 if(!o)
1352 {
1353 crap("cannot handle op %s", opn);
1354 }
1355 o->func(opn, arg1, arg2, o->data);
1356 if(assembler_pass)
1357 debug(" - %s%s", cur_line, cur_line[strlen(cur_line)-1]=='\n'?"":"\n");
1358 }
1359 }
1360
1361 #ifdef SA_STANDALONE
main(int argc,char * argv[])1362 int main(int argc, char* argv[])
1363 {
1364 char line[4096];
1365 size_t len;
1366 int pass;
1367 FILE* file = NULL;
1368
1369 if(argc < 2)
1370 {
1371 crap("specify file");
1372 }
1373
1374 file = fopen(argv[1], "r");
1375 if(!file)
1376 {
1377 crap("can't open file");
1378 }
1379
1380 if(argc > 2)
1381 {
1382 fout = fopen(argv[2], "w");
1383 if(!fout)
1384 {
1385 crap("can't open %s for writing", argv[2]);
1386 }
1387 }
1388
1389 for(pass = 0; pass < 2; ++pass)
1390 {
1391 if(fseek(file, 0, SEEK_SET))
1392 crap("can't rewind file");
1393
1394 if(pass)
1395 {
1396 char* b = malloc(assembler_get_code_size());
1397 if(!b)
1398 crap("cannot allocate memory");
1399 assembler_set_output(b);
1400 }
1401
1402 assembler_init(pass);
1403
1404 while(fgets(line, sizeof(line), file))
1405 {
1406 len = strlen(line);
1407 if(!len) continue;
1408
1409 assemble_line(line, len);
1410 }
1411 }
1412
1413 assembler_init(0);
1414
1415 fclose(file);
1416
1417 return 0;
1418 }
1419 #endif
1420