Annotation of frontvm/as68k/as68k.c, revision 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.