~ubuntu-branches/ubuntu/jaunty/openarena/jaunty

« back to all changes in this revision

Viewing changes to code/qcommon/vm_x86_64_assembler.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno "Fuddl" Kleinert, Bruno "Fuddl" Kleinert
  • Date: 2008-04-24 14:33:54 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080424143354-0cuxsalv98ajw2js
Tags: 0.7.6-1
[ Bruno "Fuddl" Kleinert ]
* New upstream release
* Freshen 10_fix_build_and_binary_on_alpha.dpatch to apply to latest
  upstream sources
* Remove 10-fix_menudef.h_includes.dpatch which pulled in a missing header
  file. The header is now included in the upstream tarball.
* Remove debian/watch, because upstream places its new releases too often to
  different download locations
* Updated debian/copyright to reflect the download location
* Expand copyright years in debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
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
 
 
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
 
 
83
static inline void emit2(u16 v)
 
84
{
 
85
        emit1(v&0xFF);
 
86
        emit1((v>>8)&0xFF);
 
87
}
 
88
 
 
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
 
 
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
 
 
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!
 
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
 
 
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
 
 
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
 
 
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
 
 
304
static inline int iss8(u64 v)
 
305
{
 
306
        return (labs(v) <= 0x80);
 
307
}
 
308
 
 
309
static inline int isu8(u64 v)
 
310
{
 
311
        return (v <= 0xff);
 
312
}
 
313
 
 
314
static inline int iss16(u64 v)
 
315
{
 
316
        return (labs(v) <= 0x8000);
 
317
}
 
318
 
 
319
static inline int isu16(u64 v)
 
320
{
 
321
        return (v <= 0xffff);
 
322
}
 
323
 
 
324
static inline int iss32(u64 v)
 
325
{
 
326
        return (labs(v) <= 0x80000000);
 
327
}
 
328
 
 
329
static inline int isu32(u64 v)
 
330
{
 
331
        return (v <= 0xffffffff);
 
332
}
 
333
 
 
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
 
 
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
 
 
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
 
 
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 */
 
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 */
 
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 */
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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, &params_add },
 
902
        { "addq", emit_subaddand, &params_add },
 
903
        { "addss", emit_twobyte, &params_addss },
 
904
        { "andl", emit_subaddand, &params_and },
 
905
        { "andq", emit_subaddand, &params_and },
 
906
        { "callq", emit_call, NULL },
 
907
        { "cbw", emit_opsingle16, (void*)0x98 },
 
908
        { "cdq", emit_opsingle, (void*)0x99 },
 
909
        { "cmpl", emit_subaddand, &params_cmp },
 
910
        { "cmpq", emit_subaddand, &params_cmp },
 
911
        { "cvtsi2ss", emit_twobyte, &params_cvtsi2ss },
 
912
        { "cvttss2si", emit_twobyte, &params_cvttss2si },
 
913
        { "cwde", emit_opsingle, (void*)0x98 },
 
914
        { "decl", emit_op_rm, &params_dec },
 
915
        { "decq", emit_op_rm, &params_dec },
 
916
        { "divl", emit_op_rm, &params_div },
 
917
        { "divq", emit_op_rm, &params_div },
 
918
        { "divss", emit_twobyte, &params_divss },
 
919
        { "idivl", emit_op_rm, &params_idiv },
 
920
        { "imull", emit_op_rm, &params_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, &params_movss },
 
946
        { "movw", emit_mov, NULL },
 
947
        { "mull", emit_op_rm, &params_mul },
 
948
        { "mulss", emit_twobyte, &params_mulss },
 
949
        { "negl", emit_op_rm, &params_neg },
 
950
        { "negq", emit_op_rm, &params_neg },
 
951
        { "nop", emit_opsingle, (void*)0x90 },
 
952
        { "notl", emit_op_rm, &params_not },
 
953
        { "notq", emit_op_rm, &params_not },
 
954
        { "or",   emit_subaddand, &params_or },
 
955
        { "orl",  emit_subaddand, &params_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, &params_sar },
 
960
        { "shl", emit_op_rm_cl, &params_shl },
 
961
        { "shrl", emit_op_rm_cl, &params_shr },
 
962
        { "subl", emit_subaddand, &params_sub },
 
963
        { "subq", emit_subaddand, &params_sub },
 
964
        { "subss", emit_twobyte, &params_subss },
 
965
        { "ucomiss", emit_twobyte, &params_ucomiss },
 
966
        { "xorl",  emit_subaddand, &params_xor },
 
967
        { "xorq",  emit_subaddand, &params_xor },
 
968
        { NULL, NULL, NULL }
 
969
};
 
970
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
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
 
 
1287
size_t assembler_get_code_size(void)
 
1288
{
 
1289
        return compiledOfs;
 
1290
}
 
1291
 
 
1292
void assembler_set_output(char* buf)
 
1293
{
 
1294
        out = buf;
 
1295
}
 
1296
 
 
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
 
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