Annotation of frontvm/as68k/as68k.c, revision 1.1.1.1

1.1       root        1: 
                      2: #include <assert.h>
                      3: #include <stdio.h>
                      4: #include <stdlib.h>
                      5: #include <string.h>
                      6: #include <ctype.h>
                      7: #include <stdarg.h>
                      8: #include "dict.h"
                      9: 
                     10: #define LAB_LEN        32
                     11: #define BASE   0x1c
                     12: FILE *fin;
                     13: FILE *fout; 
                     14: char buf[4096];
                     15: Dict labels;
                     16: int dump_labels = 0;
                     17: int line_no = 0;
                     18: int last_op_addr;
                     19: enum SIZE { BYTE, WORD, LONG, LONG_FIXUP };
                     20: 
                     21: /* to convert weird move sizes to standard sizes */
                     22: const int move_size[4] = { 1, 3, 2, 0 };
                     23: const char *Bcc_str[16] = {
                     24:        "ra",NULL,"hi","ls","cc","cs","ne","eq",
                     25:        "vc","vs","pl","mi","ge","lt","gt","le"
                     26: };
                     27: const char *DBcc_str[16] = {
                     28:        "t","f","hi","ls","cc","cs","ne","eq",
                     29:        "vc","vs","pl","mi","ge","lt","gt","le"
                     30: };
                     31: 
                     32: #define check(ch)      do {  \
                     33:        if (*pos != (ch)) error ("Expected '%c'", ch); \
                     34:        pos++; \
                     35:        } while (0);
                     36: #define check_whitespace()     do { \
                     37:        if (!isspace (*pos)) error ("Line malformed."); \
                     38:        while (isspace (*pos)) pos++; \
                     39:        } while (0);
                     40: 
                     41: #define get_bitpos()   ((int)ftell (fout))
                     42: #define set_bitpos(pos)        (fseek (fout,pos,SEEK_SET))
                     43: 
                     44: #define F_DREG         (1<<0)
                     45: #define F_AREG         (1<<1)
                     46: #define F_IND          (1<<2)
                     47: #define F_POST         (1<<3)
                     48: #define F_PRE          (1<<4)
                     49: #define F_OFFSET       (1<<5)
                     50: #define F_INDEX                (1<<6)
                     51: #define F_MEM_W                (1<<7)
                     52: #define F_MEM_L                (1<<8)
                     53: #define F_IMM          (1<<9)
                     54: #define F_PC_OFFSET    (1<<10)
                     55: #define F_PC_INDEX     (1<<11)
                     56: 
                     57: #define F_NOLABELS     (1<<12)
                     58: 
                     59: #define F_NOIMM_NOPC_NOAREG    (F_DREG | F_IND | F_POST | F_PRE | \
                     60:                F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L)
                     61: #define F_ALL (0xffffffff & (~(F_NOLABELS)))
                     62: #define F_ALL_NOAREG   (F_ALL & (~F_AREG))
                     63: 
                     64: typedef union Opcode {
                     65:        unsigned short code;
                     66:        struct move {
                     67:                uint src_reg : 3;
                     68:                uint src_mode : 3;
                     69:                uint dest_mode : 3;
                     70:                uint dest_reg : 3;
                     71:                uint size : 2;
                     72:                uint op : 2;
                     73:        } move;
                     74:        struct adr_index {
                     75:                int displacement : 8;
                     76:                uint zeros : 3;
                     77:                uint ind_size : 1;
                     78:                uint reg : 3;
                     79:                uint reg_type : 1;
                     80:        } adr_index;
                     81:        struct addq {
                     82:                uint dest_reg : 3;
                     83:                uint dest_mode : 3;
                     84:                uint size : 2;
                     85:                uint issub : 1;
                     86:                uint data : 3;
                     87:                uint op : 4;
                     88:        } addq;
                     89:        struct jmp {
                     90:                uint dest_reg : 3;
                     91:                uint dest_mode : 3;
                     92:                uint op : 10;
                     93:        } jmp;
                     94:        struct addi {
                     95:                uint dest_reg : 3;
                     96:                uint dest_mode : 3;
                     97:                uint size : 2;
                     98:                uint OP6 : 8;
                     99:        } addi;
                    100:        /* size and effective address */
                    101:        struct type1 {
                    102:                uint ea_reg : 3;
                    103:                uint ea_mode : 3;
                    104:                uint size : 2;
                    105:                uint op : 8;
                    106:        } type1;
                    107:        /* reg, opmode, ea */
                    108:        struct type2 {
                    109:                uint ea_reg : 3;
                    110:                uint ea_mode : 3;
                    111:                uint op_mode : 3;
                    112:                uint reg : 3;
                    113:                uint op : 4;
                    114:        } type2;
                    115:        struct MemShift {
                    116:                uint ea_reg : 3;
                    117:                uint ea_mode : 3;
                    118:                uint OP3 : 2;
                    119:                uint dr : 1;
                    120:                uint type : 2;
                    121:                uint OP0x1c : 5;
                    122:        } MemShift;
                    123:        struct ASx {
                    124:                uint reg : 3;
                    125:                uint OP0 : 2;
                    126:                uint ir : 1;
                    127:                uint size : 2;
                    128:                uint dr : 1;
                    129:                uint count_reg : 3;
                    130:                uint OP0xe : 4;
                    131:        } ASx;
                    132:        struct abcd {
                    133:                uint src_reg : 3;
                    134:                uint rm : 1;
                    135:                uint OP16 : 5;
                    136:                uint dest_reg : 3;
                    137:                uint OP12 : 4;
                    138:        } abcd;
                    139:        struct addx {
                    140:                uint src_reg : 3;
                    141:                uint rm : 1;
                    142:                uint OP0 : 2;
                    143:                uint size : 2;
                    144:                uint OP1 : 1;
                    145:                uint dest_reg : 3;
                    146:                uint op : 4;
                    147:        } addx;
                    148:        struct cmpm {
                    149:                uint src_reg : 3;
                    150:                uint OP1_1 : 3;
                    151:                uint size : 2;
                    152:                uint OP2_1 : 1;
                    153:                uint dest_reg : 3;
                    154:                uint OP0xb : 4;
                    155:        } cmpm;
                    156:        /* branches */
                    157:        struct DBcc {
                    158:                uint reg : 3;
                    159:                uint OP25 : 5;
                    160:                uint cond : 4;
                    161:                uint OP5 : 4;
                    162:        } DBcc;
                    163:        struct Bcc {
                    164:                int displacement : 8;
                    165:                uint cond : 4;
                    166:                uint op : 4;
                    167:        } Bcc;
                    168:        struct bra {
                    169:                int displacement : 8;
                    170:                uint op : 8;
                    171:        } bra;
                    172:        struct movem {
                    173:                uint dest_reg : 3;
                    174:                uint dest_mode : 3;
                    175:                uint sz : 1;
                    176:                uint ONE : 3;
                    177:                uint dr : 1;
                    178:                uint NINE : 5;
                    179:        } movem;
                    180:        struct lea {
                    181:                uint dest_reg : 3;
                    182:                uint dest_mode : 3;
                    183:                uint SEVEN : 3;
                    184:                uint reg : 3;
                    185:                uint FOUR : 4;
                    186:        } lea;
                    187:        struct moveq {
                    188:                int data : 8;
                    189:                uint ZERO : 1;
                    190:                uint reg : 3;
                    191:                uint SEVEN : 4;
                    192:        } moveq;
                    193:        struct exg {
                    194:                uint dest_reg : 3;
                    195:                uint op_mode : 5;
                    196:                uint OP1 : 1;
                    197:                uint src_reg : 3;
                    198:                uint OP0xc : 4;
                    199:        } exg;
                    200: } Opcode;
                    201: 
                    202: struct Fixup {
                    203:        int rel_to;
                    204:        int line_no;
                    205:        int size;
                    206:        int adr;
                    207:        char label[LAB_LEN];
                    208:        struct Fixup *next;
                    209: };
                    210: 
                    211: struct Label {
                    212:        const char *name;
                    213:        int val;
                    214:        enum LAB_TYPE {
                    215:                L_ADDR,
                    216:                L_CONST
                    217:        } type;
                    218: };
                    219: 
                    220: struct ImmVal {
                    221:        int has_label;
                    222:        char label[LAB_LEN];
                    223:        int val;
                    224: };
                    225: 
                    226: struct Fixup *fix_first = NULL;
                    227: struct Fixup *fix_last = NULL;
                    228: void add_fixup (int adr, int size, const char *label)
                    229: {
                    230:        struct Fixup *fix = malloc (sizeof (struct Fixup));
                    231:        fix->adr = adr;
                    232:        fix->size = size;
                    233:        fix->next = NULL;
                    234:        fix->rel_to = (last_op_addr + 2) - BASE;
                    235:        fix->line_no = line_no;
                    236:        strcpy (fix->label, label);
                    237:        if (fix_first == NULL)  fix_first = fix;
                    238:        if (fix_last == NULL) fix_last = fix;
                    239:        else {
                    240:                fix_last->next = fix;
                    241:                fix_last = fix;
                    242:        }
                    243: }
                    244: 
                    245: void error (const char *format, ...)
                    246: {
                    247:        va_list argptr;
                    248: 
                    249:        printf ("Error at line %d: ", line_no);
                    250:        va_start (argptr, format);
                    251:        vprintf (format, argptr);
                    252:        va_end (argptr);
                    253:        printf ("\n");
                    254:        
                    255:        fclose (fout);
                    256:        remove ("aout.prg");
                    257:        exit (0);
                    258: }
                    259:        
                    260: void add_label (const char *name, int type, int val)
                    261: {
                    262:        struct Label *lab = malloc (sizeof (struct Label));
                    263:        if (dict_get (&labels, name)) error ("Label %s redefined.", name);
                    264:        lab->val = val;
                    265:        lab->type = type;
                    266:        dict_set (&labels, name, lab);
                    267: }
                    268: 
                    269: struct Label *get_label (const char *name)
                    270: {
                    271:        struct Label *lab;
                    272:        struct Node *n = dict_get (&labels, name);
                    273:        
                    274:        if (n == NULL) return NULL;
                    275:        lab = n->obj;
                    276:        lab->name = n->key;
                    277:        return lab;
                    278: }
                    279: 
                    280: void wr_byte(unsigned char x)
                    281: {
                    282:        fputc (x, fout);
                    283: }
                    284: 
                    285: void wr_short(short x)
                    286: {
                    287:        wr_byte((unsigned char)((x>>8) & 0xff));
                    288:        wr_byte((unsigned char)(x & 0xff));
                    289: }
                    290: 
                    291: void wr_int(int x)
                    292: {
                    293:        wr_byte((unsigned char)((x>>24) & 0xff));
                    294:        wr_byte((unsigned char)((x>>16) & 0xff));
                    295:        wr_byte((unsigned char)((x>>8) & 0xff));
                    296:        wr_byte((unsigned char)(x & 0xff));
                    297: }
                    298: 
                    299: 
                    300: static inline int get_size (int ch)
                    301: {
                    302:        switch (ch) {
                    303:                case 'b': return BYTE;
                    304:                case 'w': return WORD;
                    305:                case 'l': return LONG;
                    306:                default: error ("Invalid size '.%c'.", ch); return 0;
                    307:        }
                    308: }
                    309: 
                    310: char *rd_label (char *buf, char *lab_buf)
                    311: {
                    312:        char snipped;
                    313:        char *pos = buf;
                    314:        
                    315:        if (!isalpha (*buf)) error ("Label expected.");
                    316:        /* label */
                    317:        do {
                    318:                pos++;
                    319:        } while (isalnum (*pos) || (*pos == '_'));
                    320:        /* snip */
                    321:        snipped = *pos;
                    322:        *pos = '\0';
                    323: 
                    324:        if (strlen (buf) > LAB_LEN-1) error ("Label too long.");
                    325:        strncpy (lab_buf, buf, LAB_LEN);
                    326:        lab_buf[LAB_LEN-1] = '\0';
                    327:        *pos = snipped;
                    328:        return pos;
                    329: }
                    330: 
                    331: 
                    332: void check_range (int *val, enum SIZE size)
                    333: {
                    334:        switch (size) {
                    335:                case BYTE: if ((*val < -128) || (*val > 255)) goto err;
                    336:                        if (*val > 127) *val -= 256;
                    337:                        break;
                    338:                case WORD: if ((*val < -32768) || (*val > 65535)) goto err;
                    339:                        if (*val > 32767) *val -= 65536;
                    340:                        break;
                    341:                default: break;
                    342:        }
                    343:        return;
                    344: err:
                    345:        error ("Data too large.");
                    346: }
                    347:                        
                    348: 
                    349: char *get_imm (char *buf, struct ImmVal *imm, int flags)
                    350: {
                    351:        struct Label *lab;
                    352: 
                    353:        imm->has_label = 0;
                    354:        while (isspace (*buf)) buf++;
                    355:        if (flags & F_IMM) {
                    356:                if (*buf != '#') goto err;
                    357:                buf++;
                    358:        }
                    359:        if (*buf == '$') {
                    360:                /* hex value */
                    361:                buf++;
                    362:                if (sscanf (&buf[0], "%x", &imm->val) != 1) goto err;
                    363:                while (isxdigit (*buf)) buf++;
                    364:        } else if (isdigit (*buf) || (*buf == '-')) {
                    365:                /* dec value */
                    366:                if (sscanf (&buf[0], "%d", &imm->val) != 1) goto err;
                    367:                if (*buf == '-') buf++;
                    368:                while (isdigit (*buf)) buf++;
                    369:        } else if (isalpha (*buf)) {
                    370:                /* label */
                    371:                buf = rd_label (buf, imm->label);
                    372:                lab = get_label (imm->label);
                    373:                imm->val = 0;
                    374:                if (lab) {
                    375:                        if (lab->type == L_CONST) imm->val = lab->val;
                    376:                        else imm->has_label = 1;
                    377:                } else {
                    378:                        imm->has_label = 1;
                    379:                }
                    380:                if ((flags & F_NOLABELS) && (imm->has_label)) {
                    381:                        error ("Label not allowed.");
                    382:                }
                    383:        } else {
                    384:                goto err;
                    385:        }
                    386:        return buf;
                    387: err:
                    388:        error ("Malformed immediate value.");
                    389:        return NULL;
                    390: }
                    391: 
                    392: void check_end (const char *buf)
                    393: {
                    394:        while (isspace (*buf)) buf++;
                    395:        if (*buf) error ("Garbage at end of line.");
                    396: }
                    397: 
                    398: typedef struct ea_t {
                    399:        int mode;
                    400:        int reg;
                    401:        int op_size;
                    402:        struct ImmVal imm;
                    403:        union Ext {
                    404:                short ext;
                    405:                struct {
                    406:                        int displacement : 8;
                    407:                        int ZERO : 3;
                    408:                        uint size : 1;
                    409:                        uint reg : 3;
                    410:                        uint d_or_a : 1;
                    411:                } _;
                    412:        } ext;
                    413: } ea_t;
                    414: 
                    415: void wr_ea (ea_t *ea)
                    416: {
                    417:        if (ea->mode == 5) {
                    418:                if (ea->imm.has_label) error ("Relative not allowed.");
                    419:                wr_short (ea->imm.val);
                    420:                return;
                    421:        }
                    422:        if (ea->mode == 6) {
                    423:                if (ea->imm.has_label) error ("Relative not allowed.");
                    424:                wr_short (ea->ext.ext);
                    425:                return;
                    426:        }
                    427:        if (ea->mode == 7) {
                    428:                /* $xxx.w */
                    429:                if (ea->reg == 0) {
                    430:                        wr_short (ea->imm.val);
                    431:                        return;
                    432:                }
                    433:                /* $xxx.l */
                    434:                else if (ea->reg == 1) {
                    435:                        if (ea->imm.has_label) goto abs_lab32;
                    436:                        wr_int (ea->imm.val);
                    437:                        return;
                    438:                }
                    439:                /* immediate */
                    440:                else if (ea->reg == 4) {
                    441:                        if (ea->imm.has_label) {
                    442:                                if (ea->op_size != LONG)
                    443:                                        error ("Relative not allowed.");
                    444:                                goto abs_lab32;
                    445:                        }
                    446:                        if (ea->op_size == LONG) {
                    447:                                wr_int (ea->imm.val);
                    448:                        } else if (ea->op_size == WORD) {
                    449:                                wr_short (ea->imm.val);
                    450:                        } else {
                    451:                                wr_short (ea->imm.val & 0xff);
                    452:                        }
                    453:                        return;
                    454:                }
                    455:                /* PC + offset */
                    456:                else if (ea->reg == 2) {
                    457:                        if (ea->imm.has_label) goto rel_lab16;
                    458:                        error ("Absolute value not allowed.");
                    459:                        return;
                    460:                }
                    461:                /* PC + INDEX + OFFSET */
                    462:                else if (ea->reg == 3) {
                    463:                        if (!ea->imm.has_label) error ("Absolute value not allowed.");
                    464:                        wr_short (ea->ext.ext);
                    465:                        add_fixup (get_bitpos()-1, BYTE, ea->imm.label);
                    466:                        return;
                    467:                }
                    468:        }
                    469:        return;
                    470: rel_lab16:
                    471:        /* resolve a relative 16-bit label (offset) */
                    472:        wr_short (0);
                    473:        add_fixup (get_bitpos()-2, WORD, ea->imm.label);
                    474:        return;
                    475: abs_lab32:
                    476:        /* resolve an absolute 32-bit label */
                    477:        wr_int (0);
                    478:        add_fixup (get_bitpos ()-4, LONG_FIXUP, ea->imm.label);
                    479: }
                    480: 
                    481: char *get_reg (char *buf, int *reg_num, int flags)
                    482: {
                    483:        int type;
                    484:        while (isspace (*buf)) buf++;
                    485:        if ((flags & F_AREG) && (buf[0] == 'a')) type = 8;
                    486:        else if ((flags & F_DREG) && (buf[0] == 'd')) type = 0;
                    487:        else goto err;
                    488:        buf++;
                    489:        if (sscanf (&buf[0], "%d", reg_num) != 1) goto err;
                    490:        
                    491:        *reg_num += type;
                    492:        while (isdigit (*buf)) buf++;
                    493:        return buf;
                    494: err:
                    495:        error ("Expected a register.");
                    496:        return NULL;
                    497: }
                    498: 
                    499: char *get_ea (char *pos, ea_t *ea, int op_size, int flags)
                    500: {
                    501:        int reg;
                    502:        int size;
                    503:        char *orig;
                    504:        ea->imm.has_label = 0;  
                    505:        ea->op_size = op_size;
                    506:        while (isspace (*pos)) pos++;
                    507:        orig = pos;
                    508:        if ((pos[0] == 'd') && isdigit (pos[1])) {
                    509:                pos++;
                    510:                if (sscanf (&pos[0], "%d", &ea->reg) != 1) goto poopdog;
                    511:                ea->mode = 0;
                    512:                if ((ea->reg < 0) || (ea->reg > 7)) goto poopdog;
                    513:                while (isdigit (*pos)) pos++;
                    514:                if (!(flags & F_DREG)) goto err;
                    515:                return pos;
                    516:        }
                    517:        if ((pos[0] == 'a') && isdigit (pos[1])) {
                    518:                pos++;
                    519:                if (sscanf (&pos[0], "%d", &ea->reg) != 1) goto poopdog;
                    520:                ea->mode = 1;
                    521:                if ((ea->reg < 0) || (ea->reg > 7)) goto poopdog;
                    522:                while (isdigit (*pos)) pos++;
                    523:                if (!(flags & F_AREG)) goto err;
                    524:                return pos;
                    525:        }
                    526: poopdog:
                    527:        pos = orig;
                    528:        if ((*pos == '#') && (flags & F_IMM)) {
                    529:                pos = get_imm (pos, &ea->imm, F_IMM);
                    530:                check_range (&ea->imm.val, op_size);
                    531:                ea->mode = 7;
                    532:                ea->reg = 4;
                    533:                return pos;
                    534:        }
                    535:        if ((flags & F_PRE) && (pos[0] == '-') && (pos[1] == '(')) {
                    536:                pos += 2;
                    537:                pos = get_reg (pos, &ea->reg, F_AREG);
                    538:                check (')');
                    539:                ea->mode = 0x4;
                    540:                return pos;
                    541:        }
                    542:        if ((flags & (F_IND | F_POST)) && (pos[0] == '(')) {
                    543:                check ('(');
                    544:                pos = get_reg (pos, &ea->reg, F_AREG);
                    545:                check (')');
                    546:                if ((flags & F_POST) && (pos[0] == '+')) {
                    547:                        ea->mode = 3;
                    548:                        return ++pos;
                    549:                } else if (flags & F_IND) {
                    550:                        ea->mode = 2;
                    551:                        return pos;
                    552:                } else goto err;
                    553:        }
                    554:        if ((*pos == '$') || isdigit (*pos) || (*pos == '-') || isalpha (*pos)) {
                    555:                if (isalpha (*pos)) {
                    556:                        pos = get_imm (pos, &ea->imm, 0);
                    557:                } else if (*pos == '$') {
                    558:                        pos++;
                    559:                        if (sscanf (pos, "%x", &ea->imm.val) != 1) goto err;
                    560:                        while (isxdigit (*pos)) pos++;
                    561:                } else {
                    562:                        if (sscanf (pos, "%d", &ea->imm.val) != 1) goto err;
                    563:                        if (*pos == '-') pos++;
                    564:                        while (isdigit (*pos)) pos++;
                    565:                }
                    566:                /* Immediate memory (not label) */
                    567:                if ((*pos == '.') && (flags & (F_MEM_W | F_MEM_L))) {
                    568:                        pos++;
                    569:                        size = get_size (*pos);
                    570:                        pos++;
                    571:                        ea->mode = 0x7;
                    572:                        if (size == WORD) {
                    573:                                ea->reg = 0;
                    574:                                if ((ea->imm.val < 0) || (ea->imm.val > 65535)) error ("Immediate value too large.");
                    575:                        }
                    576:                        else if (size == LONG) ea->reg = 1;
                    577:                        else error ("Bad size.");
                    578:                        return pos;
                    579:                }
                    580:                while (isspace (*pos)) pos++;
                    581:                if (((*pos == ',') || (*pos == '\0')) && (flags & F_MEM_L)) {
                    582:                        /* Immed memory with label */
                    583:                        ea->mode = 0x7;
                    584:                        ea->reg = 1;
                    585:                        return pos;
                    586:                }
                    587:                if (*pos != '(') goto err;
                    588:                /* adr reg or pc indexed or offset */
                    589:                pos++;
                    590:                if ((pos[0] == 'p') && (pos[1] == 'c')) {
                    591:                        /* pc relative */
                    592:                        pos += 2;
                    593:                        if ((pos [0] == ')') && (flags & F_PC_OFFSET)) {
                    594:                                if ((ea->imm.val < -32768) || (ea->imm.val > 32767)) error ("Immediate value too large.");
                    595:                                ea->mode = 7;
                    596:                                ea->reg = 2;
                    597:                                return ++pos;
                    598:                        }
                    599:                        if (!(flags & F_PC_INDEX)) goto err;
                    600:                        check (',');
                    601:                        pos = get_reg (pos, &reg, F_AREG | F_DREG);
                    602:                        ea->ext.ext = 0;
                    603:                        if (reg > 7) {
                    604:                                ea->ext._.reg = reg-8;
                    605:                                ea->ext._.d_or_a = 1;
                    606:                        } else {
                    607:                                ea->ext._.reg = reg;
                    608:                                ea->ext._.d_or_a = 0;
                    609:                        }
                    610:                        check ('.');
                    611:                        if (pos[0] == 'l') {
                    612:                                ea->ext._.size = 1;
                    613:                        } else if (pos[0] == 'w') {
                    614:                                ea->ext._.size = 0;
                    615:                        } else error ("Index register must have size.");
                    616:                        pos++;
                    617:                        check (')');
                    618:                        ea->mode = 7;
                    619:                        ea->reg = 3;
                    620:                        return pos;
                    621:                } else {
                    622:                        /* adr with index/offset */
                    623:                        pos = get_reg (pos, &ea->reg, F_AREG);
                    624:                        if ((flags & F_OFFSET) && (pos[0] == ')')) {
                    625:                                /* with offset only */
                    626:                                if ((ea->imm.val < -32768) || (ea->imm.val > 32767)) error ("Immediate value too large.");
                    627:                                ea->mode = 5;
                    628:                                return ++pos;
                    629:                        }
                    630:                        if (!(flags & F_INDEX)) goto err;
                    631:                        check (',');
                    632:                        pos = get_reg (pos, &reg, F_AREG | F_DREG);
                    633:                        if ((ea->imm.val < -128) || (ea->imm.val > 127)) error ("Immediate value too large.");
                    634:                        ea->ext.ext = 0;
                    635:                        ea->ext._.displacement = ea->imm.val;
                    636:                        if (reg > 7) {
                    637:                                ea->ext._.reg = reg-8;
                    638:                                ea->ext._.d_or_a = 1;
                    639:                        } else {
                    640:                                ea->ext._.reg = reg;
                    641:                                ea->ext._.d_or_a = 0;
                    642:                        }
                    643:                        check ('.');
                    644:                        if (pos[0] == 'l') {
                    645:                                ea->ext._.size = 1;
                    646:                        } else if (pos[0] == 'w') {
                    647:                                ea->ext._.size = 0;
                    648:                        } else error ("Index register must have size.");
                    649:                        pos++;
                    650:                        check (')');
                    651:                        ea->mode = 6;
                    652:                        return pos;
                    653:                }       
                    654:        }
                    655:        error ("Illegal effective address.");
                    656: err:
                    657:        error ("Malformed effective address. Valid modes are: %s%s%s%s%s%s%s%s%s%s%s%s",
                    658:                        (flags & F_DREG ? "dreg " : ""),
                    659:                        (flags & F_AREG ? "areg " : ""),
                    660:                        (flags & F_IND ? "indirect " : ""),
                    661:                        (flags & F_POST ? "postincrement ": ""),
                    662:                        (flags & F_PRE ? "predecrement ": ""),
                    663:                        (flags & F_OFFSET ? "areg-offset ": ""),
                    664:                        (flags & F_OFFSET ? "areg-offset-index ": ""),
                    665:                        (flags & F_MEM_W ? "absolute.w ": ""),
                    666:                        (flags & F_MEM_L ? "absolute.l ": ""),
                    667:                        (flags & F_IMM ? "immediate ": ""),
                    668:                        (flags & F_PC_OFFSET ? "pc-relative ": ""),
                    669:                        (flags & F_PC_INDEX ? "pc-rel-index ": ""));
                    670:        return NULL;
                    671: }
                    672: 
                    673: int _reg_num (char *cunt)
                    674: {
                    675:        int is_areg;
                    676:        int num;
                    677:        
                    678:        if (cunt[0] == 'a') is_areg = 8;
                    679:        else is_areg = 0;
                    680:        cunt++;
                    681: 
                    682:        if (sscanf (cunt, "%d", &num) != 1) return -1;
                    683:        num += is_areg;
                    684: 
                    685:        while (isdigit (*cunt)) cunt++;
                    686:        if (isalpha (*cunt)) return -1;
                    687:        return num;
                    688: }
                    689: 
                    690: /* movem is a wanking cunt of doom */
                    691: /* this is such a sinful mess :-) */
                    692: char *parse_movem (char *pos, int size)
                    693: {
                    694:        union Opcode op;
                    695:        char *start = pos;
                    696:        char lab1[LAB_LEN];
                    697:        int lo, hi;
                    698:        /* d0-7,a0-7 */
                    699:        int regs[16];
                    700:        int dr = 0; /* reg to mem */
                    701:        ea_t ea;
                    702:        memset (regs, 0, 16*sizeof(int));
                    703: try_again:
                    704:        if ((pos[0] == 'a') || (pos[0] == 'd')) {
                    705: more_to_come:
                    706:                pos = rd_label (pos, lab1);
                    707:                lo = _reg_num (lab1);
                    708:                if (lo == -1) {
                    709: mess:
                    710:                        /* mem to reg */
                    711:                        dr = 1; 
                    712:                        pos = start;
                    713:                        pos = get_ea (pos, &ea, size, F_IND | F_POST | F_INDEX | F_OFFSET | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
                    714:                        if (pos[0] != ',') goto err;
                    715:                        pos++;
                    716:                        goto try_again;
                    717:                }
                    718:                
                    719:                if (*pos == '-') {
                    720:                        /* range of fucking registers */
                    721:                        pos++;
                    722:                        if (sscanf (pos, "%d", &hi) != 1) goto err;
                    723:                        pos++;
                    724:                        if ((hi < 0) || (hi > 7)) goto err;
                    725:                        if (lo > 7) hi += 8;
                    726:                } else {
                    727:                        hi = lo;
                    728:                }
                    729:                for (; lo<=hi; lo++) regs[lo] = 1;
                    730:                if (pos[0] == '/') {
                    731:                        pos++;
                    732:                        goto more_to_come;
                    733:                }
                    734:        } else {
                    735:                goto mess;
                    736:        }
                    737:        if (!dr) {
                    738:                /* reg to mem */
                    739:                if (pos[0] != ',') goto err;
                    740:                pos++;
                    741:                pos = get_ea (pos, &ea, size, F_IND | F_PRE | F_INDEX | F_OFFSET | F_MEM_W | F_MEM_L);
                    742:        }
                    743:        op.code = 0x4880;
                    744:        op.movem.sz = (size == WORD ? 0 : 1);
                    745:        op.movem.dr = dr;
                    746:        op.movem.dest_reg = ea.reg;
                    747:        op.movem.dest_mode = ea.mode;
                    748:        wr_short (op.code);
                    749: 
                    750:        hi = 0;
                    751:        if (ea.mode == 0x4) {
                    752:                /* predecrement mode */
                    753:                for (lo=0; lo < 16; lo++) {
                    754:                        if (regs[15-lo]) hi |= (1<<lo);
                    755:                }
                    756:        } else {
                    757:                for (lo=0; lo < 16; lo++) {
                    758:                        if (regs[lo]) hi |= (1<<lo);
                    759:                }
                    760:        }
                    761:        wr_short (hi);
                    762:        /* movem seems to count offsets relative to the
                    763:         * register bitfield... */
                    764:        last_op_addr += 2;
                    765:        wr_ea (&ea);
                    766:        return pos;
                    767: err:
                    768:        error ("your movem is all wanked up.");
                    769:        return NULL;
                    770: }
                    771: 
                    772: int asm_pass1 ()
                    773: {
                    774:        int i, reg, size;
                    775:        union Opcode op;
                    776:        struct ImmVal imm;
                    777:        char lab1[LAB_LEN];
                    778:        char *equ_lab;
                    779:        char *pos;
                    780:        ea_t ea;
                    781:        ea_t ea2;
                    782: 
                    783:        wr_short (0x601a);
                    784:        wr_int (0);
                    785:        wr_int (0);
                    786:        wr_int (0);
                    787:        wr_int (0);
                    788:        wr_int (0);
                    789:        wr_int (0);
                    790:        wr_short (0);
                    791: 
                    792:        dict_init (&labels);
                    793:        
                    794:        while (fgets (buf, sizeof (buf), fin)) {
                    795:                last_op_addr = get_bitpos ();
                    796:                line_no++;
                    797:                pos = &buf[0];
                    798:                /* comments */
                    799:                equ_lab = NULL;
                    800:                while (isspace (*pos)) pos++;
                    801:                if (*pos == '\0') continue;
                    802:                if (*pos == '*') continue;
                    803:                else if (isalpha (*pos)) {
                    804:                        equ_lab = pos;
                    805:                        pos = rd_label (pos, lab1);
                    806:                        if (*pos == ':') {
                    807:                                /* add label */
                    808:                                add_label (lab1, L_ADDR, get_bitpos () - BASE);
                    809:                                if (dump_labels) {
                    810:                                        printf ("0x%x: %s\n", get_bitpos () - BASE, lab1);
                    811:                                }
                    812:                                equ_lab = NULL;
                    813:                                pos++;
                    814:                                check_whitespace ();
                    815:                                if (*pos == '\0') continue;
                    816:                        }
                    817:                        while (isspace (*pos)) pos++;
                    818:                }
                    819:                /* EQU */
                    820:                if (strncmp (pos, "equ", 3) == 0) {
                    821:                        pos += 3;
                    822:                        check_whitespace();
                    823:                        if (!equ_lab) error ("EQU without label.");
                    824:                        pos = get_imm (pos, &imm, F_NOLABELS);
                    825:                        add_label (lab1, L_CONST, imm.val);
                    826:                        continue;
                    827:                }
                    828:                if (equ_lab) {
                    829:                        pos = equ_lab;
                    830:                        equ_lab = NULL;
                    831:                }
                    832:                        
                    833:                /* DC.X */
                    834:                if (strncmp (pos, "dc.", 3) == 0) {
                    835:                        size = get_size (pos[3]);
                    836:                        pos += 4;
                    837:                        check_whitespace();
                    838:                        if ((size == BYTE) && (*pos == '"')) {
                    839:                                thing:
                    840:                                pos++;
                    841:                                while (*pos != '"') {
                    842:                                        wr_byte (*pos);
                    843:                                        pos++;
                    844:                                }
                    845:                                /* double '""' escapes */
                    846:                                pos++;
                    847:                                if (*pos == '"') {
                    848:                                        wr_byte ('"');
                    849:                                        goto thing;
                    850:                                }
                    851:                                while (isspace (*pos)) pos++;
                    852:                                if (*pos != ',') {
                    853:                                        check_end (pos);
                    854:                                        continue;
                    855:                                }
                    856:                                pos++;
                    857:                        }
                    858:                        while (isdigit (*pos) || isalpha (*pos) || (*pos == '$')) {
                    859:                                pos = get_imm (pos, &imm, 0);
                    860:                                if (imm.has_label) {
                    861:                                        switch (size) {
                    862:                                                case BYTE: case WORD: error ("Labels may only be used with dc.l.");
                    863:                                                case LONG: default:
                    864:                                                        wr_int (0);
                    865:                                                        add_fixup (get_bitpos()-4, LONG_FIXUP, imm.label);
                    866:                                                        break;
                    867:                                        }
                    868:                                } else {
                    869:                                        switch (size) {
                    870:                                                case BYTE: wr_byte (imm.val); break;
                    871:                                                case WORD: wr_short (imm.val); break;
                    872:                                                case LONG: default: wr_int (imm.val); break;
                    873:                                        }
                    874:                                }
                    875:                                while (isspace (*pos)) pos++;
                    876:                                if (*pos != ',') break;
                    877:                                pos++;
                    878:                                while (isspace (*pos)) pos++;
                    879:                        }
                    880:                        check_end (pos);
                    881:                        continue;
                    882:                }
                    883:                /* DS.X */
                    884:                if (strncmp (pos, "ds.", 3) == 0) {
                    885:                        size = get_size (pos[3]);
                    886:                        pos += 4;
                    887:                        check_whitespace();
                    888:                        pos = get_imm (pos, &imm, F_NOLABELS);
                    889:                        check_end (pos);
                    890:                        for (i=0; i<imm.val; i++) {
                    891:                                if (size == BYTE) wr_byte (0);
                    892:                                else if (size == WORD) wr_short (0);
                    893:                                else wr_int (0);
                    894:                        }
                    895:                        continue;       
                    896:                }
                    897:                /* odd address checking */
                    898:                if (last_op_addr & 0x1) error ("Odd address.");
                    899:                /* ADDQ/SUBQ */
                    900:                if ((strncmp (pos, "addq", 4)==0) ||
                    901:                    (strncmp (pos, "subq", 4)==0)) {
                    902:                        op.code = 0x5000;
                    903:                        op.addq.issub = (pos[0] == 's');
                    904:                        pos += 4;
                    905:                        check ('.');
                    906:                        size = get_size (pos[0]);
                    907:                        pos++;
                    908:                        check_whitespace();
                    909:                        pos = get_imm (pos, &imm, F_NOLABELS | F_IMM);
                    910:                        if ((imm.val < 1) || (imm.val > 8)) error ("Immediate value too large.");
                    911:                        if (imm.val == 8) imm.val = 0;
                    912:                        check (',');
                    913:                        pos = get_ea (pos, &ea, LONG, F_DREG | F_AREG | F_IND | F_POST | F_PRE | F_INDEX | F_OFFSET | F_MEM_W | F_MEM_L);
                    914:                        if ((size == BYTE) && (ea.mode == 1)) error ("Bad size for address reg direct.");
                    915:                        check_end (pos);
                    916:                        op.addq.dest_reg = ea.reg;
                    917:                        op.addq.dest_mode = ea.mode;
                    918:                        op.addq.size = size;
                    919:                        op.addq.data = imm.val;
                    920:                        wr_short (op.code);
                    921:                        wr_ea (&ea);
                    922:                        continue;
                    923:                }
                    924:                /* NOP */
                    925:                if (strncmp (pos, "nop", 3) == 0) {
                    926:                        pos += 3;
                    927:                        check_end (pos);
                    928:                        wr_short (0x4e71);
                    929:                        continue;
                    930:                }
                    931:                /* NOT/NEGX/NEG */
                    932:                if (strncmp (pos, "not", 3) == 0) {
                    933:                        pos += 3;
                    934:                        check ('.');
                    935:                        size = get_size (pos[0]);
                    936:                        pos++;
                    937:                        check_whitespace();
                    938:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                    939:                        check_end (pos);
                    940:                        op.code = 0x4600;
                    941:                        op.type1.size = size;
                    942:                        op.type1.ea_reg = ea.reg;
                    943:                        op.type1.ea_mode = ea.mode;
                    944:                        wr_short (op.code);
                    945:                        wr_ea (&ea);
                    946:                        continue;
                    947:                }
                    948:                if (strncmp (pos, "negx", 4) == 0) {
                    949:                        pos += 4;
                    950:                        check ('.');
                    951:                        size = get_size (pos[0]);
                    952:                        pos++;
                    953:                        check_whitespace();
                    954:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                    955:                        check_end (pos);
                    956:                        op.code = 0x4000;
                    957:                        op.type1.size = size;
                    958:                        op.type1.ea_reg = ea.reg;
                    959:                        op.type1.ea_mode = ea.mode;
                    960:                        wr_short (op.code);
                    961:                        wr_ea (&ea);
                    962:                        continue;
                    963:                }
                    964:                if (strncmp (pos, "neg", 3) == 0) {
                    965:                        pos += 3;
                    966:                        check ('.');
                    967:                        size = get_size (pos[0]);
                    968:                        pos++;
                    969:                        check_whitespace();
                    970:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                    971:                        check_end (pos);
                    972:                        op.code = 0x4400;
                    973:                        op.type1.size = size;
                    974:                        op.type1.ea_reg = ea.reg;
                    975:                        op.type1.ea_mode = ea.mode;
                    976:                        wr_short (op.code);
                    977:                        wr_ea (&ea);
                    978:                        continue;
                    979:                }
                    980:                /* DIVS/DIVU */
                    981:                if (strncmp (pos, "div", 3) == 0) {
                    982:                        pos += 3;
                    983:                        if (pos[0] == 's') op.code = 0x81c0;
                    984:                        else op.code = 0x80c0;
                    985:                        pos++;
                    986:                        check_whitespace();
                    987:                        pos = get_ea (pos, &ea, WORD, F_ALL_NOAREG);
                    988:                        check (',');
                    989:                        pos = get_reg (pos, &i, F_DREG);
                    990:                        check_end (pos);
                    991:                        op.type2.reg = i;
                    992:                        op.type2.ea_mode = ea.mode;
                    993:                        op.type2.ea_reg = ea.reg;
                    994:                        wr_short (op.code);
                    995:                        wr_ea (&ea);
                    996:                        continue;
                    997:                }
                    998:                /* MULS/MULU */
                    999:                if (strncmp (pos, "mul", 3) == 0) {
                   1000:                        pos += 3;
                   1001:                        if (pos[0] == 's') op.code = 0xc1c0;
                   1002:                        else op.code = 0xc0c0;
                   1003:                        pos++;
                   1004:                        check_whitespace();
                   1005:                        pos = get_ea (pos, &ea, WORD, F_ALL_NOAREG);
                   1006:                        check (',');
                   1007:                        pos = get_reg (pos, &i, F_DREG);
                   1008:                        check_end (pos);
                   1009:                        op.type2.reg = i;
                   1010:                        op.type2.ea_mode = ea.mode;
                   1011:                        op.type2.ea_reg = ea.reg;
                   1012:                        wr_short (op.code);
                   1013:                        wr_ea (&ea);
                   1014:                        continue;
                   1015:                }
                   1016:                /* ADDI/SUBI */
                   1017:                if ((strncmp (pos, "addi", 4) == 0) ||
                   1018:                    (strncmp (pos, "subi", 4) == 0)) {
                   1019:                        if (pos[0] == 'a') op.code = 0x0600;
                   1020:                        else op.code = 0x0400;
                   1021:                        pos += 4;
                   1022:                        check ('.');
                   1023:                        size = get_size (pos[0]);
                   1024:                        pos++;
                   1025:                        check_whitespace();
                   1026:                        pos = get_ea (pos, &ea2, size, F_IMM);
                   1027:                        check (',');
                   1028:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                   1029:                        check_end (pos);
                   1030:                        op.type1.size = size;
                   1031:                        op.type1.ea_reg = ea.reg;
                   1032:                        op.type1.ea_mode = ea.mode;
                   1033:                        wr_short (op.code);
                   1034:                        if (size == BYTE) {
                   1035:                                wr_short (ea2.imm.val & 0xff);
                   1036:                        } else if (size == WORD) {
                   1037:                                wr_short (ea2.imm.val);
                   1038:                        } else {
                   1039:                                wr_int (ea2.imm.val);
                   1040:                        }
                   1041:                        wr_ea (&ea);
                   1042:                        continue;
                   1043:                }
                   1044:                /* ADDA/SUBA */
                   1045:                if ((strncmp (pos, "adda", 4) == 0) ||
                   1046:                    (strncmp (pos, "suba", 4) == 0)) {
                   1047:                        if (pos[0] == 'a') op.code = 0xd000;
                   1048:                        else op.code = 0x9000;
                   1049:                        pos += 4;
                   1050:                        check ('.');
                   1051:                        size = get_size (pos[0]);
                   1052:                        if (size == BYTE) error ("Crap size for adda.");
                   1053:                        pos++;
                   1054:                        check_whitespace();
                   1055:                        pos = get_ea (pos, &ea, size, F_ALL);
                   1056:                        check (',');
                   1057:                        pos = get_reg (pos, &reg, F_AREG);
                   1058:                        check_end (pos);
                   1059:                        op.type2.reg = reg;
                   1060:                        if (size == WORD) size = 3;
                   1061:                        else size = 7;
                   1062:                        op.type2.op_mode = size;
                   1063:                        op.type2.ea_reg = ea.reg;
                   1064:                        op.type2.ea_mode = ea.mode;
                   1065:                        wr_short (op.code);
                   1066:                        wr_ea (&ea);
                   1067:                        continue;
                   1068:                }
                   1069:                /* ADDX/SUBX */
                   1070:                if ((strncmp (pos, "addx", 4) == 0) ||
                   1071:                    (strncmp (pos, "subx", 4) == 0)) {
                   1072:                        if (pos[0] == 'a') op.code = 0xd100;
                   1073:                        else op.code = 0x9100;
                   1074:                        pos  += 4;
                   1075:                        check ('.');
                   1076:                        size = get_size (pos[0]);
                   1077:                        op.addx.size = size;
                   1078:                        pos++;
                   1079:                        check_whitespace();
                   1080:                        pos = get_ea (pos, &ea, size, F_DREG | F_PRE);
                   1081:                        if (ea.mode == 0) {
                   1082:                                /* Dn,Dn mode */
                   1083:                                check (',');
                   1084:                                op.addx.src_reg = ea.reg;
                   1085:                                op.addx.rm = 0;
                   1086:                                pos = get_reg (pos, &i, F_DREG);
                   1087:                                check_end (pos);
                   1088:                                op.addx.dest_reg = i;
                   1089:                                wr_short (op.code);
                   1090:                        } else {
                   1091:                                /* -(An),-(An) mode */
                   1092:                                check (',');
                   1093:                                op.addx.src_reg = ea.reg;
                   1094:                                op.addx.rm = 1;
                   1095:                                pos = get_ea (pos, &ea, size, F_PRE);
                   1096:                                op.addx.dest_reg = ea.reg;
                   1097:                                wr_short (op.code);
                   1098:                        }
                   1099:                        check_end (pos);
                   1100:                        continue;
                   1101:                }
                   1102:                /* ADD/SUB */
                   1103:                if ((strncmp (pos, "add", 3) == 0) ||
                   1104:                    (strncmp (pos, "sub", 3) == 0)) {
                   1105:                        if (pos[0] == 'a') op.code = 0xd000;
                   1106:                        else op.code = 0x9000;
                   1107:                        pos += 3;
                   1108:                        check ('.');
                   1109:                        size = get_size (pos[0]);
                   1110:                        pos++;
                   1111:                        check_whitespace();
                   1112:                        pos = get_ea (pos, &ea, size, F_ALL);
                   1113:                        check (',');
                   1114:                        pos = get_ea (pos, &ea2, size, F_DREG | F_IND | F_POST | F_PRE | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L);
                   1115:                        if (ea2.mode == 0) {
                   1116:                                /* data reg dest */
                   1117:                                op.type2.reg = ea2.reg;
                   1118:                                op.type2.op_mode = size;
                   1119:                                op.type2.ea_reg = ea.reg;
                   1120:                                op.type2.ea_mode = ea.mode;
                   1121:                                wr_short (op.code);
                   1122:                                wr_ea (&ea);
                   1123:                        } else {
                   1124:                                /* ea dest */
                   1125:                                if (ea.mode != 0) error ("One operand must be a data register.");
                   1126:                                op.type2.reg = ea.reg;
                   1127:                                op.type2.op_mode = size+4;
                   1128:                                op.type2.ea_reg = ea2.reg;
                   1129:                                op.type2.ea_mode = ea2.mode;
                   1130:                                wr_short (op.code);
                   1131:                                wr_ea (&ea2);
                   1132:                        }
                   1133:                        check_end (pos);
                   1134:                        continue;
                   1135:                }
                   1136:                /* BCHG/BCLR/BSET/BTST */
                   1137:                if ((strncmp (pos, "bchg", 4)==0) ||
                   1138:                    (strncmp (pos, "bclr", 4)==0) ||
                   1139:                    (strncmp (pos, "bset", 4)==0) ||
                   1140:                    (strncmp (pos, "btst", 4)==0)) {
                   1141:                        int type;
                   1142:                        switch (pos[2]) {
                   1143:                                /* bchg */
                   1144:                                case 'h': type = 0; break;
                   1145:                                /* bclr */
                   1146:                                case 'l': type = 1; break;
                   1147:                                /* bset */
                   1148:                                case 'e': type = 2; break;
                   1149:                                /* btst */
                   1150:                                default: case 's': type = 3; break;
                   1151:                        }
                   1152:                        pos += 4;
                   1153:                        check_whitespace();
                   1154:                        pos = get_ea (pos, &ea, BYTE, F_IMM | F_DREG);
                   1155:                        if (ea.mode == 0) {
                   1156:                                /* Dn,<ea> mode */
                   1157:                                switch (type) {
                   1158:                                        case 0: op.code = 0x0140; break;
                   1159:                                        case 1: op.code = 0x0180; break;
                   1160:                                        case 2: op.code = 0x01c0; break;
                   1161:                                        case 3: op.code = 0x0100; break;
                   1162:                                }
                   1163:                                op.type2.reg = ea.reg;
                   1164:                                check (',');
                   1165:                                pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                   1166:                                op.type2.ea_reg = ea.reg;
                   1167:                                op.type2.ea_mode = ea.mode;
                   1168:                                wr_short (op.code);
                   1169:                                wr_ea (&ea);
                   1170:                                continue;
                   1171:                        } else {
                   1172:                                /* IMM,<ea> mode */
                   1173:                                check_range (&ea.imm.val, BYTE);
                   1174:                                imm.val = ea.imm.val;
                   1175:                                switch (type) {
                   1176:                                        case 0: op.code = 0x0840; break;
                   1177:                                        case 1: op.code = 0x0880; break;
                   1178:                                        case 2: op.code = 0x08c0; break;
                   1179:                                        case 3: op.code = 0x0800; break;
                   1180:                                }
                   1181:                                check (',');
                   1182:                                if (type == 3) {
                   1183:                                        pos = get_ea (pos, &ea, size, F_DREG | F_IND | F_POST | F_PRE | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
                   1184:                                } else {
                   1185:                                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                   1186:                                }
                   1187:                                op.type2.ea_mode = ea.mode;
                   1188:                                op.type2.ea_reg = ea.reg;
                   1189:                                wr_short (op.code);
                   1190:                                wr_short (imm.val & 0xff);
                   1191:                                wr_ea (&ea);
                   1192:                                continue;
                   1193:                        }
                   1194:                        check_end (pos);
                   1195:                        continue;
                   1196:                }
                   1197:                /* ASx/LSx/ROx ROXx */
                   1198:                if ((strncmp (pos, "ls", 2) == 0) ||
                   1199:                    (strncmp (pos, "as", 2) == 0) ||
                   1200:                    (strncmp (pos, "ro", 2) == 0)) {
                   1201:                        char dir;
                   1202:                        int type;
                   1203:                        dir = pos[2];
                   1204:                        if (pos[0] == 'a') type = 0;
                   1205:                        else if (pos[0] == 'l') type = 1;
                   1206:                        else if (pos[0] == 'r') {
                   1207:                                if (pos[2] == 'x') {
                   1208:                                        type = 2;
                   1209:                                        dir = pos[3];
                   1210:                                }
                   1211:                                else type = 3;
                   1212:                        } else {
                   1213:                                goto blork;
                   1214:                        }
                   1215:                        if ((dir != 'l') && (dir != 'r')) goto blork;
                   1216:                        dir = (dir == 'l' ? 1 : 0);
                   1217:                        while (isalpha (*pos)) pos++;
                   1218:                        check ('.');
                   1219:                        size = get_size (pos[0]);
                   1220:                        pos++;
                   1221:                        check_whitespace();
                   1222:                        pos = get_ea (pos, &ea, size, F_DREG | F_IND | F_POST | F_PRE | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L | F_IMM);
                   1223:                        if (ea.mode == 0) {
                   1224:                                /* data reg type */
                   1225:                                check (',');
                   1226:                                pos = get_reg (pos, &reg, F_DREG);
                   1227:                                check_end (pos);
                   1228:                                if (type == 1) op.code = 0xe008;
                   1229:                                else if (type == 0) op.code = 0xe000;
                   1230:                                else if (type == 2) op.code = 0xe010;
                   1231:                                else op.code = 0xe018;
                   1232:                                op.ASx.count_reg = ea.reg;
                   1233:                                op.ASx.dr = dir;
                   1234:                                op.ASx.size = size;
                   1235:                                op.ASx.ir = 1;
                   1236:                                op.ASx.reg = reg;
                   1237:                                wr_short (op.code);
                   1238:                                continue;
                   1239:                        } else if ((ea.mode == 7) && (ea.reg == 4)) {
                   1240:                                /* imm,Dn type */
                   1241:                                check (',');
                   1242:                                pos = get_reg (pos, &reg, F_DREG);
                   1243:                                check_end (pos);
                   1244:                                if (type == 1) op.code = 0xe008;
                   1245:                                else if (type == 0) op.code = 0xe000;
                   1246:                                else if (type == 2) op.code = 0xe010;
                   1247:                                else op.code = 0xe018;
                   1248:                                if ((ea.imm.val < 1) || (ea.imm.val > 8)) error ("Bad immediate value.");
                   1249:                                if (ea.imm.val == 8) ea.imm.val = 0;
                   1250:                                op.ASx.count_reg = ea.imm.val;
                   1251:                                op.ASx.dr = dir;
                   1252:                                op.ASx.size = size;
                   1253:                                op.ASx.ir = 0;
                   1254:                                op.ASx.reg = reg;
                   1255:                                wr_short (op.code);
                   1256:                                continue;
                   1257:                        } else {
                   1258:                                /* ea mode */
                   1259:                                if (size != WORD) error ("Illegal size.");
                   1260:                                check_end (pos);
                   1261:                                if (type == 1) op.code = 0xe2c0;
                   1262:                                else if (type == 0) op.code = 0xe0c0;
                   1263:                                else if (type == 2) op.code = 0xe4c0;
                   1264:                                else op.code = 0xe6c0;
                   1265:                                op.ASx.dr = dir;
                   1266:                                op.type1.ea_reg = ea.reg;
                   1267:                                op.type1.ea_mode = ea.mode;
                   1268:                                wr_short (op.code);
                   1269:                                wr_ea (&ea);
                   1270:                                continue;
                   1271:                        }
                   1272:                        continue;
                   1273:                }
                   1274: blork:
                   1275:                /* ANDI/EORI/ORI */
                   1276:                if ((strncmp (pos, "andi", 4) == 0) ||
                   1277:                    (strncmp (pos, "eori", 4) == 0) ||
                   1278:                    (strncmp (pos, "ori", 3) == 0)) {
                   1279:                        if (pos[0] == 'a') {
                   1280:                                op.code = 0x0200;
                   1281:                        } else if (pos[0] == 'e') {
                   1282:                                op.code = 0x0a00;
                   1283:                        } else {
                   1284:                                op.code = 0x0000;
                   1285:                        }
                   1286:                        while (isalpha (*pos)) pos++;
                   1287:                        check ('.');
                   1288:                        size = get_size (pos[0]);
                   1289:                        pos++;
                   1290:                        check_whitespace();
                   1291:                        pos = get_imm (pos, &imm, F_NOLABELS | F_IMM);
                   1292:                        check_range (&imm.val, size);
                   1293:                        check (',');
                   1294:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                   1295:                        check_end (pos);
                   1296:                        op.type1.ea_reg = ea.reg;
                   1297:                        op.type1.ea_mode = ea.mode;
                   1298:                        op.type1.size = size;
                   1299:                        wr_short (op.code);
                   1300:                        if (size == BYTE) {
                   1301:                                wr_short (imm.val & 0xff);
                   1302:                        } else if (size == WORD) {
                   1303:                                wr_short (imm.val);
                   1304:                        } else {
                   1305:                                wr_int (imm.val);
                   1306:                        }
                   1307:                        wr_ea (&ea);
                   1308:                        continue;
                   1309:                }
                   1310:                /* AND/OR */
                   1311:                if ((strncmp (pos, "and", 3) == 0) ||
                   1312:                    (strncmp (pos, "or", 2) == 0)) {
                   1313:                        if (pos[0] == 'a') op.code = 0xc000;
                   1314:                        else op.code = 0x8000;
                   1315:                        while (isalpha (*pos)) pos++;
                   1316:                        check ('.');
                   1317:                        size = get_size (pos[0]);
                   1318:                        pos++;
                   1319:                        check_whitespace();
                   1320:                        pos = get_ea (pos, &ea, size, F_ALL_NOAREG);
                   1321:                        check (',');
                   1322:                        pos = get_ea (pos, &ea2, size, F_NOIMM_NOPC_NOAREG);
                   1323:                        check_end (pos);
                   1324:                        if (ea2.mode == 0) {
                   1325:                                /* data reg dest */
                   1326:                                op.type2.reg = ea2.reg;
                   1327:                                op.type2.op_mode = size;
                   1328:                                op.type2.ea_reg = ea.reg;
                   1329:                                op.type2.ea_mode = ea.mode;
                   1330:                                wr_short (op.code);
                   1331:                                wr_ea (&ea);
                   1332:                        } else {
                   1333:                                /* ea dest */
                   1334:                                if (ea.mode != 0) error ("One operand must be a data register.");
                   1335:                                op.type2.reg = ea.reg;
                   1336:                                op.type2.op_mode = size+4;
                   1337:                                op.type2.ea_reg = ea2.reg;
                   1338:                                op.type2.ea_mode = ea2.mode;
                   1339:                                wr_short (op.code);
                   1340:                                wr_ea (&ea2);
                   1341:                        }
                   1342:                        continue;
                   1343:                }
                   1344:                /* EOR */
                   1345:                if (strncmp (pos, "eor", 3) == 0) {
                   1346:                        op.code = 0xb000;
                   1347:                        pos += 3;
                   1348:                        check ('.');
                   1349:                        size = get_size (pos[0]);
                   1350:                        pos++;
                   1351:                        check_whitespace();
                   1352:                        pos = get_reg (pos, &reg, F_DREG);
                   1353:                        check (',');
                   1354:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                   1355:                        check_end (pos);
                   1356:                        op.type2.reg = reg;
                   1357:                        size += 4;
                   1358:                        op.type2.op_mode = size;
                   1359:                        op.type2.ea_reg = ea.reg;
                   1360:                        op.type2.ea_mode = ea.mode;
                   1361:                        wr_short (op.code);
                   1362:                        wr_ea (&ea);
                   1363:                        continue;
                   1364:                }
                   1365:                /* SWAP */
                   1366:                if (strncmp (pos, "swap", 4) == 0) {
                   1367:                        pos += 4;
                   1368:                        pos = get_reg (pos, &reg, F_DREG);
                   1369:                        op.code = 0x4840;
                   1370:                        op.type2.ea_reg = reg;
                   1371:                        check_end (pos);
                   1372:                        wr_short (op.code);
                   1373:                        continue;
                   1374:                }
                   1375:                /* BSR */
                   1376:                if (strncmp (pos, "bsr", 3) == 0) {
                   1377:                        pos += 3;
                   1378:                        check ('.');
                   1379:                        size = pos[0];
                   1380:                        pos++;
                   1381:                        check_whitespace();
                   1382:                        pos = rd_label (pos, lab1);
                   1383:                        check_end (pos);
                   1384:                        op.code = 0x6100;
                   1385:                        wr_short (op.code);
                   1386:                        if (size == 's') {
                   1387:                                add_fixup (get_bitpos()-1, BYTE, lab1);
                   1388:                        } else if (size == 'w') {
                   1389:                                wr_short (0);
                   1390:                                add_fixup (get_bitpos()-2, WORD, lab1);
                   1391:                        } else {
                   1392:                                error ("Invalid size '.%c'.", size);
                   1393:                        }
                   1394:                        continue;
                   1395:                }
                   1396:                /* Bcc.S */
                   1397:                if (pos[0] == 'b') {
                   1398:                        for (i=0; i<16; i++) {
                   1399:                                if (Bcc_str [i] == NULL) continue;
                   1400:                                if (strncmp (&pos[1], Bcc_str[i], 2)==0) break;
                   1401:                        }
                   1402:                        if (i==16) goto fuckit;
                   1403:                        pos += 3;
                   1404:                        check ('.');
                   1405:                        size = pos[0];
                   1406:                        pos++;
                   1407:                        check_whitespace();
                   1408:                        pos = rd_label (pos, lab1);
                   1409:                        check_end (pos);
                   1410:                        op.code = 0x6000 | (i<<8);
                   1411:                        wr_short (op.code);
                   1412:                        if (size == 's') {
                   1413:                                add_fixup (get_bitpos()-1, BYTE, lab1);
                   1414:                        } else if (size == 'w') {
                   1415:                                wr_short (0);
                   1416:                                add_fixup (get_bitpos()-2, WORD, lab1);
                   1417:                        } else {
                   1418:                                error ("Invalid size '.%c'.", size);
                   1419:                        }
                   1420:                        continue;
                   1421:                }
                   1422:                /* DBcc */
                   1423:                if ((pos[0] == 'd') && (pos[1] == 'b')) {
                   1424:                        pos = rd_label (&pos[2], lab1);
                   1425:                        for (i=0; i<16; i++) {
                   1426:                                if (strncmp (lab1, DBcc_str[i], 2)==0) break;
                   1427:                        }
                   1428:                        if (i==16) {
                   1429:                                if (strncmp (lab1, "ra", 2)==0) {
                   1430:                                        i = 1;
                   1431:                                } else {
                   1432:                                        goto fuckit;
                   1433:                                }
                   1434:                        }
                   1435:                        while (isalpha (*pos)) pos++;
                   1436:                        check_whitespace();
                   1437:                        pos = get_reg (pos, &reg, F_DREG);
                   1438:                        check (',');
                   1439:                        pos = rd_label (pos, lab1);
                   1440:                        check_end (pos);
                   1441:                        op.code = 0x50c8;
                   1442:                        op.DBcc.reg = reg;
                   1443:                        op.DBcc.cond = i;
                   1444:                        wr_short (op.code);
                   1445:                        wr_short (0);
                   1446:                        add_fixup (get_bitpos()-2, WORD, lab1);
                   1447:                        continue;
                   1448:                }
                   1449: fuckit:
                   1450:                /* CLR */
                   1451:                if (strncmp (pos, "clr", 3) == 0) {
                   1452:                        pos += 3;
                   1453:                        check ('.');
                   1454:                        size = get_size (pos[0]);
                   1455:                        pos++;
                   1456:                        check_whitespace();
                   1457:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                   1458:                        check_end (pos);
                   1459:                        op.code = 0x4200;
                   1460:                        op.type1.size = size;
                   1461:                        op.type1.ea_reg = ea.reg;
                   1462:                        op.type1.ea_mode = ea.mode;
                   1463:                        wr_short (op.code);
                   1464:                        wr_ea (&ea);
                   1465:                        continue;
                   1466:                }
                   1467:                /* CMPI */
                   1468:                if (strncmp (pos, "cmpi", 4) == 0) {
                   1469:                        pos += 4;
                   1470:                        check ('.');
                   1471:                        size = get_size (*pos);
                   1472:                        pos++;
                   1473:                        check_whitespace();
                   1474:                        pos = get_imm (pos, &imm, F_NOLABELS | F_IMM);
                   1475:                        check_range (&imm.val, size);
                   1476:                        check (',');
                   1477:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                   1478:                        check_end (pos);
                   1479:                        op.code = 0x0c00;
                   1480:                        op.type1.ea_reg = ea.reg;
                   1481:                        op.type1.ea_mode = ea.mode;
                   1482:                        op.type1.size = size;
                   1483:                        wr_short (op.code);
                   1484:                        if (size == BYTE) {
                   1485:                                wr_short (imm.val & 0xff);
                   1486:                        } else if (size == WORD) {
                   1487:                                wr_short (imm.val);
                   1488:                        } else {
                   1489:                                wr_int (imm.val);
                   1490:                        }
                   1491:                        wr_ea (&ea);
                   1492:                        continue;
                   1493:                }
                   1494:                /* CMPA */
                   1495:                if (strncmp (pos, "cmpa", 4) == 0) {
                   1496:                        pos += 4;
                   1497:                        check ('.');
                   1498:                        size = get_size (*pos);
                   1499:                        pos++;
                   1500:                        if (size == BYTE) error ("Size must be word or long.");
                   1501:                        check_whitespace();
                   1502:                        pos = get_ea (pos, &ea, size, F_ALL);
                   1503:                        check (',');
                   1504:                        pos = get_reg (pos, &i, F_AREG);
                   1505:                        check_end (pos);
                   1506: 
                   1507:                        op.code = 0xb000;
                   1508:                        op.type2.reg = i;
                   1509:                        op.type2.op_mode = (size == WORD ? 3 : 7);
                   1510:                        op.type2.ea_mode = ea.mode;
                   1511:                        op.type2.ea_reg = ea.reg;
                   1512:                        wr_short (op.code);
                   1513:                        wr_ea (&ea);
                   1514:                        continue;
                   1515:                }
                   1516:                /* CMPM */
                   1517:                if (strncmp (pos, "cmpm", 4) == 0) {
                   1518:                        pos += 4;
                   1519:                        check ('.');
                   1520:                        size = get_size (*pos);
                   1521:                        pos++;
                   1522:                        check_whitespace ();
                   1523:                        pos = get_ea (pos, &ea, size, F_POST);
                   1524:                        op.code = 0xb108;
                   1525:                        op.cmpm.src_reg = ea.reg;
                   1526:                        op.cmpm.size = size;
                   1527:                        check (',');
                   1528:                        pos = get_ea (pos, &ea, size, F_POST);
                   1529:                        op.cmpm.dest_reg = ea.reg;
                   1530:                        wr_short (op.code);
                   1531:                        continue;
                   1532:                }
                   1533:                /* CMP */
                   1534:                if (strncmp (pos, "cmp", 3) == 0) {
                   1535:                        pos += 3;
                   1536:                        check ('.');
                   1537:                        size = get_size (*pos);
                   1538:                        pos++;
                   1539:                        check_whitespace();
                   1540:                        pos = get_ea (pos, &ea, size, F_ALL);
                   1541:                        check (',');
                   1542:                        if ((size == BYTE) && (ea.mode == 0x1))
                   1543:                                error ("Bad size for address register gropery.");
                   1544:                        pos = get_reg (pos, &i, F_DREG);
                   1545:                        check_end (pos);
                   1546: 
                   1547:                        op.code = 0xb000;
                   1548:                        op.type2.reg = i;
                   1549:                        op.type2.op_mode = size;
                   1550:                        op.type2.ea_mode = ea.mode;
                   1551:                        op.type2.ea_reg = ea.reg;
                   1552:                        wr_short (op.code);
                   1553:                        wr_ea (&ea);
                   1554:                        continue;
                   1555:                }
                   1556:                /* EXG */
                   1557:                if (strncmp (pos, "exg", 3) == 0) {
                   1558:                        pos += 3;
                   1559:                        op.code = 0xc100;
                   1560:                        check_whitespace();
                   1561:                        pos = get_reg (pos, &reg, F_DREG | F_AREG);
                   1562:                        check (',');
                   1563:                        if (reg > 7) {
                   1564:                                /* Ax,Ay mode */
                   1565:                                op.exg.op_mode = 0x9;
                   1566:                                op.exg.src_reg = reg;
                   1567:                                pos = get_reg (pos, &reg, F_AREG);
                   1568:                                op.exg.dest_reg = reg;
                   1569:                        } else {
                   1570:                                /* Dx,Xn mode */
                   1571:                                op.exg.src_reg = reg;
                   1572:                                pos = get_reg (pos, &reg, F_AREG | F_DREG);
                   1573:                                if (reg > 7) {
                   1574:                                        op.exg.op_mode = 0x11;
                   1575:                                } else {
                   1576:                                        op.exg.op_mode = 0x8;
                   1577:                                }
                   1578:                                op.exg.dest_reg = reg;
                   1579:                        }
                   1580:                        check_end (pos);
                   1581:                        wr_short (op.code);
                   1582:                        continue;
                   1583:                }
                   1584:                /* EXT */
                   1585:                if (strncmp (pos, "ext", 3) == 0) {
                   1586:                        pos += 3;
                   1587:                        check ('.');
                   1588:                        size = get_size (pos[0]);
                   1589:                        pos++;
                   1590:                        check_whitespace();
                   1591:                        if (size == BYTE) error ("Ext dislikes bytes.");
                   1592:                        pos = get_reg (pos, &reg, F_DREG);
                   1593:                        check_end (pos);
                   1594:                        op.code = 0x4800;
                   1595:                        op.type2.ea_reg = reg;
                   1596:                        op.type2.op_mode = size+1;
                   1597:                        wr_short (op.code);
                   1598:                        continue;
                   1599:                }
                   1600:                        
                   1601:                        
                   1602:                /* MOVEM */
                   1603:                if (strncmp (pos, "movem.", 6)==0) {
                   1604:                        pos += 6;
                   1605:                        size = get_size (pos[0]);
                   1606:                        pos++;
                   1607:                        if (size == BYTE) error  ("Movem dislikes bytes.");
                   1608:                        check_whitespace();
                   1609:                        /* register to memory */
                   1610:                        pos = parse_movem (pos, size);
                   1611:                        check_end (pos);
                   1612:                        continue;
                   1613:                }
                   1614:                /* RTE */
                   1615:                if (strncmp (pos, "rte", 3) == 0) {
                   1616:                        check_end (&pos[3]);
                   1617:                        wr_short (0x4e73);
                   1618:                        continue;
                   1619:                }
                   1620:                /* RTS */
                   1621:                if (strncmp (pos, "rts", 3) == 0) {
                   1622:                        check_end (&pos[3]);
                   1623:                        wr_short (0x4e75);
                   1624:                        continue;
                   1625:                }
                   1626:                /* ILLEGAL */
                   1627:                if (strncmp (pos, "illegal", 7) == 0) {
                   1628:                        check_end (&pos[7]);
                   1629:                        wr_short (0x4afc);
                   1630:                        continue;
                   1631:                }
                   1632:                /* HOSTCALL -- Not 68000 */
                   1633:                if (strncmp (pos, "hostcall", 8) == 0) {
                   1634:                        pos += 8;
                   1635:                        check_end (pos);
                   1636:                        wr_short (0x000a);
                   1637:                        continue;
                   1638:                }
                   1639:                if (strncmp (pos, "hcall", 5) == 0) {
                   1640:                        pos += 5;
                   1641:                        check_whitespace();
                   1642:                        pos = get_imm (pos, &imm, F_IMM | F_NOLABELS);
                   1643:                        check_end (pos);
                   1644:                        check_range (&imm.val, WORD);
                   1645:                        wr_short (0x000b);
                   1646:                        wr_short (imm.val);
                   1647:                        continue;
                   1648:                }
                   1649:                /* RESET */
                   1650:                if (strncmp (pos, "reset", 5) == 0) {
                   1651:                        check_end (&pos[5]);
                   1652:                        wr_short (0x4e70);
                   1653:                        continue;
                   1654:                }
                   1655:                /* TRAP */
                   1656:                if (strncmp (pos, "trap", 4) == 0) {
                   1657:                        /* TRAPV */
                   1658:                        if (pos[4] == 'v') {
                   1659:                                check_end (&pos[5]);
                   1660:                                wr_short (0x4e76);
                   1661:                                continue;
                   1662:                        }
                   1663:                        pos += 4;
                   1664:                        check_whitespace();
                   1665:                        pos = get_imm (pos, &imm, F_IMM | F_NOLABELS);
                   1666:                        check_end (pos);
                   1667:                        if ((imm.val < 0) || (imm.val > 15)) {
                   1668:                                error ("Trap vector out of range.");
                   1669:                                continue;
                   1670:                        }
                   1671:                        wr_short (0x4e40 | imm.val);
                   1672:                        continue;
                   1673:                }
                   1674:                /* LINK */
                   1675:                if (strncmp (pos, "link", 4) == 0) {
                   1676:                        pos += 4;
                   1677:                        check_whitespace();
                   1678:                        pos = get_reg (pos, &reg, F_AREG);
                   1679:                        check (',');
                   1680:                        pos = get_imm (pos, &imm, F_IMM | F_NOLABELS);
                   1681:                        check_end (pos);
                   1682:                        check_range (&imm.val, WORD);
                   1683:                        op.code = 0x4e50;
                   1684:                        op.type1.ea_reg = reg;
                   1685:                        wr_short (op.code);
                   1686:                        wr_short (imm.val);
                   1687:                        continue;
                   1688:                }
                   1689:                /* UNLK */
                   1690:                if (strncmp (pos, "unlk", 4) == 0) {
                   1691:                        pos += 4;
                   1692:                        check_whitespace();
                   1693:                        pos = get_reg (pos, &reg, F_AREG);
                   1694:                        check_end (pos);
                   1695:                        op.code = 0x4e58;
                   1696:                        op.type1.ea_reg = reg;
                   1697:                        wr_short (op.code);
                   1698:                        continue;
                   1699:                }
                   1700:                /* MOVEQ */
                   1701:                if (strncmp (pos, "moveq", 5) == 0){
                   1702:                        pos += 5;
                   1703:                        check_whitespace();
                   1704:                        pos = get_imm (pos, &imm, F_NOLABELS | F_IMM);
                   1705:                        check_range (&imm.val, BYTE);
                   1706:                        check (',');
                   1707:                        pos = get_ea (pos, &ea, LONG, F_DREG);
                   1708:                        check_end (pos);
                   1709:                        op.code = 0x7000;
                   1710:                        op.moveq.reg = ea.reg;
                   1711:                        op.moveq.data = imm.val;
                   1712:                        wr_short (op.code);
                   1713:                        continue;
                   1714:                }
                   1715:                /* MOVEA */
                   1716:                if (strncmp (pos, "movea.", 6) == 0) {
                   1717:                        pos += 6;
                   1718:                        size = get_size (pos[0]);
                   1719:                        pos++;
                   1720:                        check_whitespace();
                   1721:                        pos = get_ea (pos, &ea, size, F_ALL);
                   1722:                        check (',');
                   1723:                        pos = get_reg (pos, &i, F_AREG);
                   1724:                        check_end (pos);
                   1725: is_movea:              
                   1726:                        if (size == BYTE) error ("Illegal size.");
                   1727:                        size = move_size[size];
                   1728:                        op.code = 0;
                   1729:                        op.move.size = size;
                   1730:                        op.move.dest_reg = i;
                   1731:                        op.move.dest_mode = 1;
                   1732:                        op.move.src_reg = ea.reg;
                   1733:                        op.move.src_mode = ea.mode;
                   1734:                        wr_short (op.code);
                   1735:                        wr_ea (&ea);
                   1736:                        continue;
                   1737:                }
                   1738:                /* MOVE */
                   1739:                if (strncmp (pos, "move.", 5) == 0) {
                   1740:                        pos += 5;
                   1741:                        size = get_size (pos[0]);
                   1742:                        pos++;
                   1743:                        check_whitespace();
                   1744:                        pos = get_ea (pos, &ea, size, F_ALL);
                   1745:                        check (',');
                   1746:                        pos = get_ea (pos, &ea2, size, F_AREG | F_DREG | F_IND | F_PRE | F_POST | F_INDEX | F_OFFSET | F_MEM_W | F_MEM_L);
                   1747:                        check_end (pos);
                   1748:                        
                   1749:                        if ((ea.mode == 7) && (ea.reg == 1) && (ea.imm.has_label)) {
                   1750:                                if (strcmp (ea.imm.label, "sr")==0) {
                   1751:                                        /* move from sr */
                   1752:                                        if (size != WORD) error ("Illegal size.");
                   1753:                                        op.code = 0x40c0;
                   1754:                                        op.type1.ea_reg = ea2.reg;
                   1755:                                        op.type1.ea_mode = ea2.mode;
                   1756:                                        wr_short (op.code);
                   1757:                                        wr_ea (&ea2);
                   1758:                                        continue;
                   1759:                                }
                   1760:                        }
                   1761:                        if (ea2.mode == 1) {
                   1762:                                i = ea2.reg;
                   1763:                                goto is_movea;
                   1764:                        }
                   1765:                        if ((ea2.mode == 7) && (ea2.reg == 1) && (ea2.imm.has_label)) {
                   1766:                                if (strcmp (ea2.imm.label, "sr")==0) {
                   1767:                                        /* move to status reg */
                   1768:                                        if (size != WORD) error ("Illegal size.");
                   1769:                                        op.code = 0x46c0;
                   1770:                                        op.type1.ea_reg = ea.reg;
                   1771:                                        op.type1.ea_mode = ea.mode;
                   1772:                                        wr_short (op.code);
                   1773:                                        wr_ea (&ea);
                   1774:                                        continue;
                   1775:                                }
                   1776:                        }
                   1777:                        size = move_size[size];
                   1778:                        op.code = 0;
                   1779:                        op.move.size = size;
                   1780:                        op.move.dest_reg = ea2.reg;
                   1781:                        op.move.dest_mode = ea2.mode;
                   1782:                        op.move.src_reg = ea.reg;
                   1783:                        op.move.src_mode = ea.mode;
                   1784:                        wr_short (op.code);
                   1785:                        wr_ea (&ea);
                   1786:                        wr_ea (&ea2);
                   1787:                        continue;
                   1788:                }
                   1789:                /* TST */
                   1790:                if (strncmp (pos, "tst.", 4) == 0) {
                   1791:                        pos += 4;
                   1792:                        size = get_size (pos[0]);
                   1793:                        pos++;
                   1794:                        check_whitespace();
                   1795:                        pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
                   1796:                        check_end (pos);
                   1797:                        op.code = 0x4a00;
                   1798:                        op.type1.size = size;
                   1799:                        op.type1.ea_reg = ea.reg;
                   1800:                        op.type1.ea_mode = ea.mode;
                   1801:                        wr_short (op.code);
                   1802:                        wr_ea (&ea);
                   1803:                        continue;
                   1804:                }
                   1805:                /* PEA */
                   1806:                if (strncmp (pos, "pea", 3) == 0) {
                   1807:                        pos += 3;
                   1808:                        check_whitespace();
                   1809:                        pos = get_ea (pos, &ea, LONG, F_IND | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
                   1810:                        check_end (pos);
                   1811:                        op.code = 0x4840;
                   1812:                        op.type2.ea_reg = ea.reg;
                   1813:                        op.type2.ea_mode = ea.mode;
                   1814:                        wr_short (op.code);
                   1815:                        wr_ea (&ea);
                   1816:                        continue;
                   1817:                }
                   1818:                /* LEA */
                   1819:                if (strncmp (pos, "lea", 3) == 0) {
                   1820:                        pos += 3;
                   1821:                        check_whitespace();
                   1822:                        pos = get_ea (pos, &ea, LONG, F_IND | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
                   1823:                        check (',');
                   1824:                        pos = get_reg (pos, &size, F_AREG);
                   1825:                        check_end (pos);
                   1826:                        op.code = 0x41e0;
                   1827:                        op.type2.ea_reg = ea.reg;
                   1828:                        op.type2.ea_mode = ea.mode;
                   1829:                        op.type2.reg = size-8;
                   1830:                        wr_short (op.code);
                   1831:                        wr_ea (&ea);
                   1832:                        continue;
                   1833:                }
                   1834: 
                   1835:                /* JSR */
                   1836:                if (strncmp (pos, "jsr", 3) == 0) {
                   1837:                        pos += 3;
                   1838:                        check_whitespace();
                   1839:                        pos = get_ea (pos, &ea, LONG, F_IND | F_OFFSET |
                   1840:                                        F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
                   1841:                        check_end (pos);
                   1842:                        op.code = 0x4e80;
                   1843:                        op.type1.ea_reg = ea.reg;
                   1844:                        op.type1.ea_mode = ea.mode;
                   1845:                        wr_short (op.code);
                   1846:                        wr_ea (&ea);
                   1847:                        continue;
                   1848:                }
                   1849:                /* JMP */
                   1850:                if (strncmp (pos, "jmp", 3) == 0) {
                   1851:                        pos += 3;
                   1852:                        check_whitespace();
                   1853:                        pos = get_ea (pos, &ea, LONG, F_IND | F_OFFSET |
                   1854:                                        F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
                   1855:                        check_end (pos);
                   1856:                        op.code = 0x4ec0;
                   1857:                        op.type1.ea_reg = ea.reg;
                   1858:                        op.type1.ea_mode = ea.mode;
                   1859:                        wr_short (op.code);
                   1860:                        wr_ea (&ea);
                   1861:                        continue;
                   1862:                }
                   1863:                /* Scc */
                   1864:                if (pos[0] == 's') {
                   1865:                        pos = rd_label (&pos[1], lab1);
                   1866:                        for (i=0; i<16; i++) {
                   1867:                                if (strncmp (lab1, DBcc_str[i], 2)==0) break;
                   1868:                        }
                   1869:                        if (i==16) goto fuckit2;
                   1870:                        while (isalpha (*pos)) pos++;
                   1871:                        check_whitespace();
                   1872:                        pos = get_ea (pos, &ea, BYTE, F_NOIMM_NOPC_NOAREG);
                   1873:                        check_end (pos);
                   1874:                        op.code = 0x50c0;
                   1875:                        op.DBcc.cond = i;
                   1876:                        op.type1.ea_reg = ea.reg;
                   1877:                        op.type1.ea_mode = ea.mode;
                   1878:                        wr_short (op.code);
                   1879:                        wr_ea (&ea);
                   1880:                        continue;
                   1881:                }
                   1882: fuckit2:
                   1883:                error ("Unknown opcode %s.", pos);
                   1884:        }
                   1885:        /* write text section length */
                   1886:        size = get_bitpos () - BASE;
                   1887:        set_bitpos (2);
                   1888:        wr_int (size);
                   1889:        /* empty reloc table for the moment */
                   1890:        set_bitpos (size + BASE);
                   1891:        wr_int (0);
                   1892:        return size + BASE;
                   1893: }
                   1894: 
                   1895: int asm_pass2 (int fixup_pos)
                   1896: {
                   1897:        struct Label *lab;
                   1898:        struct Fixup *fix;
                   1899:        int last_adr = BASE;
                   1900:        int _first = 1;
                   1901:        int dist;
                   1902:        int num_relocs = 0;
                   1903: 
                   1904:        fix = fix_first;
                   1905: 
                   1906:        while (fix) {
                   1907:                line_no = fix->line_no;
                   1908:                lab = get_label (fix->label);
                   1909:                if (!lab) {
                   1910:                        error ("Undefined label '%s'.", fix->label);
                   1911:                }
                   1912:                if (lab->type == L_CONST) {
                   1913:                        error ("Illegal absolute value.");
                   1914:                }
                   1915:                set_bitpos (fix->adr);
                   1916:                if (fix->size == BYTE) {
                   1917:                        dist = lab->val - fix->rel_to;
                   1918:                        if ((dist < -128) || (dist > 127)) {
                   1919:                                error ("Offset too big (%d).", dist);
                   1920:                        }
                   1921:                        wr_byte (dist);
                   1922:                } else if (fix->size == WORD) {
                   1923:                        dist = lab->val - fix->rel_to;
                   1924:                        if ((dist < -32768) || (dist > 32767)) {
                   1925:                                error ("Offset too big (%d).", dist);
                   1926:                        }
                   1927:                        wr_short (dist);
                   1928:                } else if (fix->size >= LONG) {
                   1929:                        num_relocs++;
                   1930:                        wr_int (lab->val);
                   1931:                        set_bitpos (fixup_pos);
                   1932:                        if (_first) {
                   1933:                                wr_int (fix->adr - BASE);
                   1934:                                last_adr = fix->adr;
                   1935:                                fixup_pos+=4;
                   1936:                                _first = 0;
                   1937:                        } else {
                   1938:                                dist = fix->adr - last_adr;
                   1939:                                while (dist > 254) {
                   1940:                                        wr_byte (1);
                   1941:                                        dist -= 254;
                   1942:                                        fixup_pos++;
                   1943:                                }
                   1944:                                wr_byte (dist);
                   1945:                                last_adr = fix->adr;
                   1946:                                fixup_pos++;
                   1947:                        }
                   1948:                }  else {error ("Unknown size in fixup tab.");}
                   1949:                fix = fix->next;
                   1950:        }
                   1951:        set_bitpos (fixup_pos);
                   1952:        if (_first) wr_int (0);
                   1953:        else wr_byte (0);
                   1954: 
                   1955:        return num_relocs;
                   1956: }
                   1957: 
                   1958: int main (int argc, char **argv)
                   1959: {
                   1960:        int size, num;
                   1961:        if (argc == 1) {
                   1962:                printf ("Usage: ./as68k [--dump-labels] file.s\n");
                   1963:                exit (0);
                   1964:        }
                   1965:        
                   1966:        argv++;
                   1967: 
                   1968:        if (strcmp (*argv, "--dump-labels") == 0) {
                   1969:                argv++;
                   1970:                dump_labels = 1;
                   1971:        }
                   1972:        if ((fin = fopen (*argv, "r"))==NULL) {
                   1973:                printf ("Error. Cannot open %s.\n", *argv);
                   1974:                exit (0);
                   1975:        }
                   1976: 
                   1977:        fout = fopen ("aout.prg", "w");
                   1978: 
                   1979:        printf ("Pass 1\n");
                   1980:        size = asm_pass1 ();
                   1981:        printf ("Pass 2\n");
                   1982:        num = asm_pass2 (size);
                   1983:        fseek (fout, 0, SEEK_END);
                   1984:        size = ftell (fout);
                   1985: 
                   1986:        printf ("Done! %d bytes and %d relocations.\n", size, num);
                   1987:        return 0;
                   1988: }
                   1989: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.