Annotation of nono/util/iasm/iasm.cpp, revision 1.1.1.3

1.1       root        1: //
                      2: // XM6i
                      3: // Copyright (C) 2012-2016 [email protected]
                      4: //
                      5: // 簡易アセンブラ
                      6: //
                      7: 
1.1.1.3 ! root        8: #include "header.h"
        !             9: #include <iconv.h>
1.1       root       10: #include <stdarg.h>
                     11: #include <map>
                     12: #include <stack>
                     13: #include <vector>
                     14: #include "iasm.h"
                     15: 
                     16: #define BUFSIZE        (1024)
                     17: 
                     18: #define D_INOUT        (0x0001)        /* 入出力のみ */
                     19: #define D_EA   (0x0002)        /* EA のみ */
                     20: #define D_LABEL        (0x0004)        /* ラベル関係 */
                     21: #define D_PARSE        (0x0008)        /* パーサ */
                     22: #define D_EXPR (0x0010)        /* 式 */
                     23: #define D_SCAN (0x0020)        /* スキャナ */
                     24: #define D_STAGE        (0x8000)        /* ステージ */
                     25: 
                     26: typedef std::vector<String> ArrayString;
                     27: typedef std::map<String, String> LabelHash;
                     28: typedef void (opfunc_t)(uint16_t);
                     29: typedef std::vector<Token> ArrayToken;
                     30: 
                     31: /* オペランド形式 */
                     32: enum oprand_type_t {
                     33:        OPR_EA = 0,                     /* 最大2つのEA (命令用) */
                     34:        OPR_LIST,                       /* カンマ区切りリスト */
                     35:        OPR_LITERAL,            /* 1つのリテラル */
                     36: };
                     37: 
                     38: /* 命令処理分岐テーブル */
                     39: struct optable_t {
                     40:        const char *opname;             /* 命令語(完全一致) */
                     41:        opfunc_t *func;                 /* 処理関数 */
                     42:        uint16_t opword;                /* 命令ワード */
                     43:        oprand_type_t oprand_type;      /* オペランド形式 */
                     44: };
                     45: 
                     46: /* EA タイプ */
                     47: enum eatype_t {
                     48:        EAT_Dn          = 0x0001,
                     49:        EAT_An          = 0x0002,
                     50:        EAT_AI          = 0x0004,
                     51:        EAT_API         = 0x0008,
                     52:        EAT_APD         = 0x0010,
                     53:        EAT_AREL        = 0x0020,
                     54:        EAT_ABS         = 0x0040,
                     55:        EAT_PCREL       = 0x0080,
                     56:        EAT_IMM         = 0x0100,
                     57: 
                     58:        EAT_ALL         = 0x01ff,
                     59:        EAT_DATA        = (EAT_ALL & ~EAT_An),
                     60:        EAT_CNTL        = (EAT_An | EAT_AREL | EAT_ABS | EAT_PCREL),
                     61: };
                     62: 
                     63: /* EA */
                     64: enum eamode_t {
                     65:        EA_Dn           = 0x00,
                     66:        EA_An           = 0x08,
                     67:        EA_An_I         = 0x10,
                     68:        EA_An_PI        = 0x18,
                     69:        EA_An_PD        = 0x20,
                     70:        EA_d16An        = 0x28,
                     71:        EA_d8AnIX       = 0x30,
                     72:        EA_ABS_W        = 0x38,
                     73:        EA_ABS_L        = 0x39,
                     74:        EA_d16PC        = 0x3a,
                     75:        EA_d8PCIX       = 0x3b,
                     76:        EA_IMMEDIATE = 0x3c,
                     77: };
                     78: 
                     79: class EA {
                     80:  public:
                     81:        int mode;               /* 種別 */
                     82:        uint32_t val;   /* 値。ABS か #imm の場合に使用 */
                     83:        int size;               /* サイズ(バイト数)。#imm の場合に使用 */
                     84:        String label;   /* あれば未解決ラベル。空文字列なら val を使用のこと */
                     85: 
                     86:        EA() {
                     87:                mode = 0;
                     88:                val = 0;
                     89:                size = 0;
                     90:        }
                     91:        int type() const { return (mode >> 3) & 7; };
                     92:        int num()  const { return (mode & 7); };
                     93: };
                     94: 
                     95: /* 参照種別 */
                     96: enum reftype_t {
                     97:        REFTYPE_BYTE,
                     98:        REFTYPE_WORD,
                     99:        REFTYPE_LONG,
                    100: };
                    101: 
                    102: /* 後から参照(式)を解決するための構造体 */
                    103: struct REF {
                    104:        int pos;                        /* 出力位置 */
                    105:        int line;                       /* 現在の行数 */
                    106:        reftype_t type;         /* 種別(サイズ) */
                    107:        ArrayString expr;       /* 中間式 */
                    108: };
                    109: typedef std::vector<REF*> ArrayRef;
                    110: 
                    111: /* サイズサフィックスから bit7-6 がサイズを示すやつ用に変換 */
                    112: const uint16_t size6[] = {
                    113:        0,
                    114:        0x0000, /* 1=.B */
                    115:        0x0040, /* 2=.W */
                    116:        0,
                    117:        0x0080, /* 4=.L */
                    118: };
                    119: 
                    120: /* 出力形式 */
                    121: enum format_t {
                    122:        FORMAT_C,                       /* C ソース */
                    123:        FORMAT_BINARY,          /* バイナリ */
                    124: };
                    125: 
                    126: const char *outfile;           /* 出力ファイル名 */
                    127: FILE *outfp;                           /* 出力ファイル */
                    128: int debug;                                     /* デバッグモード */
                    129: const char *current_infile;    /* 現在の入力ファイル名 */
                    130: int line;                                      /* 現在のファイル中の行数(エラー表示用) */
                    131: format_t format;                       /* 出力形式 */
                    132: uint32_t origin;                       /* 現在のブロックの開始アドレス */
                    133: uint32_t pc;                           /* 現在の PC */
                    134: String label0;                         /* 現在行のラベル */
                    135: String op0;                                    /* 現在の命令語 */
                    136: String size0;                          /* 現在のサイズサフィックス (文字) */
                    137: int size_sfx;                          /* 現在のサイズサフィックス (B=1/W=2/L=4) */
                    138: ArrayString oprand;                    /* 現在のオペランド */
                    139: String current_name;           /* .start で指示された変数名 */
                    140: String outbin;                         /* 現在出力しているバイナリ列 */
                    141: LabelHash label_list;          /* ラベルのリスト */
                    142: ArrayRef ref_list;                     /* ラベルを参照する側のリスト */
                    143: int rept_start;                                /* .rept 開始位置 */
                    144: int rept_count;                                /* .rept 回数 */
                    145: 
                    146: void usage(const char *) __attribute__((__noreturn__));
                    147: int asm_main(const char *);
                    148: void parse_asm(String&);
                    149: void scan_asm(String&, ArrayToken&);
                    150: void parse_token(ArrayToken&);
                    151: void parse_arg_literal(ArrayToken&, ArrayToken::iterator&);
                    152: void parse_arg_list(ArrayToken&, ArrayToken::iterator&);
                    153: void parse_arg_ea(ArrayToken&, ArrayToken::iterator&);
                    154: void include_iocs();
                    155: void add_label(String&);
                    156: bool find_label(String&, uint32_t&);
                    157: optable_t *lookup(String&);
                    158: void format_c();
                    159: void format_binary();
                    160: bool try_ea(String&, EA&, String&, int);
                    161: EA get_ea(String&);
                    162: EA get_ea(String&, int);
                    163: bool get_reglist(String&, uint16_t&);
                    164: int get_cc(String&);
                    165: void output_ea(EA&);
                    166: void add_ref(reftype_t, String&);
                    167: void output_bin(uint32_t, int);
                    168: void output_b(uint32_t);
                    169: void output_w(uint32_t);
                    170: void output_l(uint32_t);
                    171: void output_ds(int);
                    172: String num2str(int);
                    173: String num2hex(int);
                    174: bool parse_number(String&, int*);
                    175: int tonumber(String&);
                    176: bool parse_expr(String&, ArrayString&);
                    177: bool scan_expr(String&, ArrayString&);
                    178: void add_expr(int pos, reftype_t, ArrayString&);
                    179: String parse_string(String&);
                    180: String convert_charset(String&);
                    181: void DPRINTN_ref(int, REF *);
                    182: void DPRINTN_expr(int, ArrayString&);
                    183: bool calc_expr(ArrayString&, uint32_t&, bool);
                    184: void DPRINTV(int, const char *, va_list);
                    185: void DPRINTN(int, const char *, ...);
                    186: void DPRINTF(int, const char *, ...);
                    187: void error(const char *, ...) __attribute__((__noreturn__)); /* エラー出力 */
                    188: void trim(String&);                                    /* 前後の空白を取り除く */
                    189: void ltrim(String&);                           /* 先頭の空白を取り除く */
                    190: void rtrim(String&);                           /* 末尾の空白を取り除く */
                    191: 
                    192: opfunc_t op_cinclude;
                    193: opfunc_t op_org;
                    194: opfunc_t op_start;
                    195: opfunc_t op_end;
                    196: opfunc_t op_dc;
                    197: opfunc_t op_ds;
                    198: opfunc_t op_even;
                    199: opfunc_t op_equ;
                    200: opfunc_t op_rept;
                    201: opfunc_t op_endrept;
                    202: opfunc_t op_iocs;
                    203: opfunc_t op_bcc;
                    204: opfunc_t op_bra;
                    205: opfunc_t op_clr;
                    206: opfunc_t op_dbra;
                    207: opfunc_t op_jmp;
                    208: opfunc_t op_lea;
                    209: opfunc_t op_move;
                    210: opfunc_t op_movem;
                    211: opfunc_t op_moveq;
                    212: opfunc_t op_sub;
                    213: opfunc_t op_suba;
                    214: opfunc_t op_trap;
                    215: opfunc_t op_noarg;
                    216: 
                    217: optable_t optable[] = {
                    218:        { ".cinclude",  op_cinclude,    0,      OPR_LITERAL, },
                    219:        { ".org",               op_org,                 0,      OPR_LIST, },
                    220:        { ".start",             op_start,               0,      OPR_LITERAL, },
                    221:        { ".end",               op_end,                 0,      OPR_LIST, },
                    222:        { ".dc",                op_dc,                  0,      OPR_LIST, },
                    223:        { ".ds",                op_ds,                  0,      OPR_LIST, },
                    224:        { ".even",              op_even,                0,      OPR_LIST, },
                    225:        { ".equ",               op_equ,                 0,      OPR_LIST, },
                    226:        { ".rept",              op_rept,                0,      OPR_LIST, },
                    227:        { ".endrept",   op_endrept,             0,      OPR_LIST, },
                    228: 
                    229:        /* マクロが定義できないのでここでやっちまう */
                    230:        { "IOCS",               op_iocs, },
                    231: 
                    232:        /* XXX BCC.B <cond>,<label> */
                    233:        { "bcc",                op_bcc,         0x6000, },
                    234: 
                    235:        { "bra",                op_bra,         0x6000, },
                    236:        { "clr",                op_clr,         0x4200, },
                    237:        { "dbra",               op_dbra,        0x51c8, },
                    238:        { "jmp",                op_jmp,         0x4ec0, },
                    239:        { "lea",                op_lea,         0x41c0, },
                    240:        { "move",               op_move,        0x0000, },
                    241:        { "movem",              op_movem,       0x4880, },
                    242:        { "moveq",              op_moveq,       0x7000, },
                    243:        { "sub",                op_sub,         0x9000, },
                    244:        { "suba",               op_suba,        0x90c0, },
                    245:        { "trap",               op_trap,        0x4e40, },
                    246: 
                    247:        /* オペランドのないやつ */
                    248:        { "reset",              op_noarg,       0x4e70, },
                    249:        { "nop",                op_noarg,       0x4e71, },
                    250:        { "rte",                op_noarg,       0x4e73, },
                    251:        { "rtd",                op_noarg,       0x4e74, },
                    252:        { "rts",                op_noarg,       0x4e75, },
                    253:        { "trapv",              op_noarg,       0x4e76, },
                    254:        { "rtr",                op_noarg,       0x4e77, },
                    255: 
                    256:        { NULL, NULL, },
                    257: };
                    258: 
                    259: const char *regname[] = {
                    260:        "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
                    261:        "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
                    262:        "(A0)",  "(A1)",  "(A2)",  "(A3)",  "(A4)",  "(A5)",  "(A6)",  "(A7)",
                    263:        "(A0)+", "(A1)+", "(A2)+", "(A3)+", "(A4)+", "(A5)+", "(A6)+", "(A7)+",
                    264:        "-(A0)", "-(A1)", "-(A2)", "-(A3)", "-(A4)", "-(A5)", "-(A6)", "-(A7)",
                    265: };
                    266: 
                    267: const char *ccname[] = {
                    268:        "t",  "f",  "hi", "ls", "cc", "cs", "ne", "eq",
                    269:        "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le",
                    270: };
                    271: 
                    272: const char *iocscall[] = {
                    273:        "_B_KEYINP",    // $00
                    274:        "_B_KEYSNS",    // $01
                    275:        "_B_SFTSNS",    // $02
                    276:        "_KEY_INIT",    // $03
                    277:        "_BITSNS",              // $04
                    278:        "_SKEYSET",             // $05
                    279:        "_LEDCTRL",             // $06
                    280:        "_LEDSET",              // $07
                    281:        "_KEYDLY",              // $08
                    282:        "_KEYREP",              // $09
                    283:        "$0a",                  // $0a
                    284:        "$0b",                  // $0b
                    285:        "_TVCTRL",              // $0c
                    286:        "_LEDMOD",              // $0d
                    287:        "_TGUSEMD",             // $0e
                    288:        "_DEFCHR",              // $0f
                    289:        "_CRTMOD",              // $10
                    290:        "_CONTRAST",    // $11
                    291:        "_HSVTORGB",    // $12
                    292:        "_TPALET",              // $13
                    293:        "_TPALET2",             // $14
                    294:        "_TCOLOR",              // $15
                    295:        "_FNTADR",              // $16
                    296:        "_VRAMGET",             // $17
                    297:        "_VRAMPUT",             // $18
                    298:        "_FNTGET",              // $19
                    299:        "_TEXTGET",             // $1a
                    300:        "_TEXTPUT",             // $1b
                    301:        "_CLIPPUT",             // $1c
                    302:        "_SCROLL",              // $1d
                    303:        "_B_CURON",             // $1e
                    304:        "_B_CUROFF",    // $1f
                    305:        "_B_PUTC",              // $20
                    306:        "_B_PRINT",             // $21
                    307:        "_B_COLOR",             // $22
                    308:        "_B_LOCATE",    // $23
                    309:        "_B_DOWN_S",    // $24
                    310:        "_B_UP_S",              // $25
                    311:        "_B_UP",                // $26
                    312:        "_B_DOWN",              // $27
                    313:        "_B_RIGHT",             // $28
                    314:        "_B_LEFT",              // $29
                    315:        "_B_CLR_ST",    // $2a
                    316:        "_B_ERA_ST",    // $2b
                    317:        "_B_INS",               // $2c
                    318:        "_B_DEL",               // $2d
                    319:        "_B_CONSOL",    // $2e
                    320:        "_B_PUTMES",    // $2f
                    321:        "_SET232C",             // $30
                    322:        "_LOF232C",             // $31
                    323:        "_INP232C",             // $32
                    324:        "_ISNS232C",    // $33
                    325:        "_OSNS232C",    // $34
                    326:        "_OUT232C",             // $35
                    327:        "$36",                  // $36
                    328:        "$37",                  // $37
                    329:        "_SETFNTADR",   // $38
                    330:        "$39",                  // $39
                    331:        "$3a",                  // $3a
                    332:        "_JOYGET",              // $3b
                    333:        "_INIT_PRN",    // $3c
                    334:        "_SNSPRN",              // $3d
                    335:        "_OUTLPT",              // $3e
                    336:        "_OUTPRN",              // $3f
                    337:        "_B_SEEK",              // $40
                    338:        "_B_VERIFY",    // $41
                    339:        "_B_READDI",    // $42
                    340:        "_B_DSKINI",    // $43
                    341:        "_B_DRVSNS",    // $44
                    342:        "_B_WRITE",             // $45
                    343:        "_B_READ",              // $46
                    344:        "_B_RECALI",    // $47
                    345:        "_B_ASSIGN",    // $48
                    346:        "_B_WRITED",    // $49
                    347:        "_B_READID",    // $4a
                    348:        "_B_BADFMT",    // $4b
                    349:        "_B_READDL",    // $4c
                    350:        "_B_FORMAT",    // $4d
                    351:        "_B_DRVCHK",    // $4e
                    352:        "_B_EJECT",             // $4f
                    353:        "_DATEBCD",             // $50
                    354:        "_DATESET",             // $51
                    355:        "_TIMEBCD",             // $52
                    356:        "_TIMESET",             // $53
                    357:        "_DATEGET",             // $54
                    358:        "_DATEBIN",             // $55
                    359:        "_TIMEGET",             // $56
                    360:        "_TIMEBIN",             // $57
                    361:        "_DATECNV",             // $58
                    362:        "_TIMECNV",             // $59
                    363:        "_DATEASC",             // $5a
                    364:        "_TIMEASC",             // $5b
                    365:        "_DAYASC",              // $5c
                    366:        "_ALARMMOD",    // $5d
                    367:        "_ALARMSET",    // $5e
                    368:        "_ALARMGET",    // $5f
                    369:        "_ADPCMOUT",    // $60
                    370:        "_ADPCMINP",    // $61
                    371:        "_ADPCMAOT",    // $62
                    372:        "_ADPCMAIN",    // $63
                    373:        "_ADPCMLOT",    // $64
                    374:        "_ADPCMLIN",    // $65
                    375:        "_ADPCMSNS",    // $66
                    376:        "_ADPCMMOD",    // $67
                    377:        "_OPMSET",              // $68
                    378:        "_OPMSNS",              // $69
                    379:        "_OPMINTST",    // $6a
                    380:        "_TIMERDST",    // $6b
                    381:        "_VDISPST",             // $6c
                    382:        "_CRTCRAS",             // $6d
                    383:        "_HSYNCST",             // $6e
                    384:        "_PRNINTST",    // $6f
                    385:        "_MS_INIT",             // $70
                    386:        "_MS_CURON",    // $71
                    387:        "_MS_CUROF",    // $72
                    388:        "_MS_STAT",             // $73
                    389:        "_MS_GETDT",    // $74
                    390:        "_MS_CURGT",    // $75
                    391:        "_MS_CURST",    // $76
                    392:        "_MS_LIMIT",    // $77
                    393:        "_MS_OFFTM",    // $78
                    394:        "_MS_ONTM",             // $79
                    395:        "_MS_PATST",    // $7a
                    396:        "_MS_SEL",              // $7b
                    397:        "_MS_SEL2",             // $7c
                    398:        "_SKEY_MOD",    // $7d
                    399:        "_DENSNS",              // $7e
                    400:        "_ONTIME",              // $7f
                    401:        "_B_INTVCS",    // $80
                    402:        "_B_SUPER",             // $81
                    403:        "_B_BPEEK",             // $82
                    404:        "_B_WPEEK",             // $83
                    405:        "_B_LPEEK",             // $84
                    406:        "_B_MEMSTR",    // $85
                    407:        "_B_BPOKE",             // $86
                    408:        "_B_WPOKE",             // $87
                    409:        "_B_LPOKE",             // $88
                    410:        "_B_MEMSET",    // $89
                    411:        "_DMAMOVE",             // $8a
                    412:        "_DMAMOV_A",    // $8b
                    413:        "_DMAMOV_L",    // $8c
                    414:        "_DMAMODE",             // $8d
                    415:        "_BOOTINF",             // $8e
                    416:        "_ROMVER",              // $8f
                    417:        "_G_CLR_ON",    // $90
                    418:        "$91",                  // $91
                    419:        "$92",                  // $92
                    420:        "$93",                  // $93
                    421:        "_GPALET",              // $94
                    422:        "$95",                  // $95
                    423:        "$96",                  // $96
                    424:        "$97",                  // $97
                    425:        "$98",                  // $98
                    426:        "$99",                  // $99
                    427:        "$9a",                  // $9a
                    428:        "$9b",                  // $9b
                    429:        "$9c",                  // $9c
                    430:        "", "", "",
                    431:        "_SFTJIS",              // $a0
                    432:        "_JISSFT",              // $a1
                    433:        "_AKCONV",              // $a2
                    434:        "_RMACNV",              // $a3
                    435:        "_DAKJOB",              // $a4
                    436:        "_HANJOB",              // $a5
                    437:        "", "", "",
                    438:        "", "", "",
                    439:        "_SYS_STAT",    // $ac
                    440:        "_B_CONMOD",    // $ad
                    441:        "_OS_CURON",    // $ae
                    442:        "_OS_CUROF",    // $af
                    443:        "_DRAWMODE",    // $b0
                    444:        "_APAGE",               // $b1
                    445:        "_VPAGE",               // $b2
                    446:        "_HOME",                // $b3
                    447:        "_WINDOW",              // $b4
                    448:        "_WIPE",                // $b5
                    449:        "_PSET",                // $b6
                    450:        "_POINT",               // $b7
                    451:        "_LINE",                // $b8
                    452:        "_BOX",                 // $b9
                    453:        "_FILL",                // $ba
                    454:        "_CIRCLE",              // $bb
                    455:        "_PAINT",               // $bc
                    456:        "_SYMBOL",              // $bd
                    457:        "_GETGRM",              // $be
                    458:        "_PUTGRM",              // $bf
                    459:        "_SP_INIT",             // $c0
                    460:        "_SP_ON",               // $c1
                    461:        "_SP_OFF",              // $c2
                    462:        "_SP_CGCLR",    // $c3
                    463:        "_SP_DEFCG",    // $c4
                    464:        "_SP_GTPCG",    // $c5
                    465:        "_SP_REGST",    // $c6
                    466:        "_SP_REGGT",    // $c7
                    467:        "_BGSCRLST",    // $c8
                    468:        "_BGSCRLGT",    // $c9
                    469:        "_BGCTRLST",    // $ca
                    470:        "_BGCTRLGT",    // $cb
                    471:        "_BGTEXTCL",    // $cc
                    472:        "_BGTEXTST",    // $cd
                    473:        "_BGTEXTGT",    // $ce
                    474:        "_SPALET",              // $cf
                    475:        "", "", "",
                    476:        "_TXXLINE",             // $d3
                    477:        "_TXYLINE",             // $d4
                    478:        "_TXLINE",              // $d5
                    479:        "_TXBOX",               // $d6
                    480:        "_TXFILL",              // $d7
                    481:        "_TXREV",               // $d8
                    482:        "", "", "",
                    483:        "", "", "",
                    484:        "_TXRASCPY",    // $df
                    485:        "", "", "", "",
                    486:        "", "", "", "",
                    487:        "", "", "", "",
                    488:        "", "", "", "",
                    489:        "_OPMDRV",              // $f0
                    490:        "_RSDRV",               // $f1
                    491:        "_A_JOYGET",    // $f2
                    492:        "_MUSICDRV",    // $f3
                    493:        "",
                    494:        "_SCSIDRV",             // $f5
                    495:        "", "", "", "",
                    496:        "", "", "",
                    497:        "_ABORTRST",    // $fd
                    498:        "_IPLERR",              // $fe
                    499:        "_ABORTJOB",    // $ff
                    500: };
                    501: 
                    502: void
                    503: usage(const char *progname)
                    504: {
                    505:        fprintf(stderr, "usage: %s [-d] [-f <fmt>] <infile> [<outfile>]\n",
                    506:                progname);
                    507:        fprintf(stderr, "  -f <fmt>   output format: c, binary\n");
                    508:        exit(1);
                    509: }
                    510: 
                    511: int
                    512: main(int ac, char *av[])
                    513: {
                    514:        const char *progname;
                    515:        const char *infile;
                    516:        int c;
                    517: 
                    518:        progname = av[0];
                    519:        while ((c = getopt(ac, av, "d:f:")) != -1) {
                    520:                switch (c) {
                    521:                 case 'd':
                    522:                        debug = strtol(optarg, NULL, 16);
                    523:                        break;
                    524:                 case 'f':
                    525:                        if (strcasecmp(optarg, "c") == 0) {
                    526:                                format = FORMAT_C;
                    527:                        } else if (strcasecmp(optarg, "binary") == 0) {
                    528:                                format = FORMAT_BINARY;
                    529:                        } else {
                    530:                                usage(progname);
                    531:                        }
                    532:                        break;
                    533:                 default:
                    534:                        usage(progname);
                    535:                        break;
                    536:                }
                    537:        }
                    538:        ac -= optind;
                    539:        av += optind;
                    540: 
                    541:        /* デバッグ指定が1つでもあれば STAGE を必ず有効にする */
                    542:        if (debug > 0) {
                    543:                debug |= D_STAGE;
                    544:        }
                    545: 
                    546:        if (ac < 1) {
                    547:                usage(progname);
                    548:        }
                    549:        infile = av[0];
                    550: 
                    551:        if (ac > 1) {
                    552:                outfile = av[1];
                    553:                outfp = fopen(outfile, "wb");
                    554:                if (outfp == NULL) {
                    555:                        fprintf(stderr, "cannot open outfile: %s\n", outfile);
                    556:                        exit(1);
                    557:                }
                    558:        } else {
                    559:                outfile = NULL;
                    560:                outfp = stdout;
                    561:        }
                    562: 
                    563:        /* IOCS コールマクロを定義 */
                    564:        include_iocs();
                    565: 
                    566:        /* メイン処理 */
                    567:        asm_main(infile);
                    568: 
                    569:        if (outfp != stdout) {
                    570:                fclose(outfp);
                    571:        }
                    572: }
                    573: 
                    574: int
                    575: asm_main(const char *infile)
                    576: {
                    577:        FILE *fp;
                    578:        char cbuf[1024];
                    579: 
                    580:        /* ファイルオープン */
                    581:        fp = fopen(infile, "r");
                    582:        if (fp == NULL) {
                    583:                fprintf(stderr, "cannot open %s", infile);
                    584:                exit(1);
                    585:        }
                    586:        current_infile = infile;
                    587: 
                    588:        /* 1st ステージ: 読み込みながら処理 */
                    589:        line = 0;
                    590:        while (fgets(cbuf, sizeof(cbuf), fp)) {
                    591:                String buf(cbuf);
                    592:                line++;
                    593: 
                    594:                rtrim(buf);
                    595:                DPRINTF(D_INOUT, "line %3d |%s|\n", ::line, buf.c_str());
                    596: 
                    597:                /* 1命令処理 */
                    598:                parse_asm(buf);
                    599:        }
                    600: 
                    601:        fclose(fp);
                    602:        return 0;
                    603: }
                    604: 
                    605: /* 1命令処理 */
                    606: void
                    607: parse_asm(String& buf)
                    608: {
                    609:        ArrayToken token_list;
                    610: 
                    611:        /* 字句解析 */
                    612:        scan_asm(buf, token_list);
                    613: 
                    614:        /* 構文解析(?)して分岐 */
                    615:        parse_token(token_list);
                    616: }
                    617: 
                    618: /* 入力の1行 src を字句解析して結果を token_list に返す */
                    619: void
                    620: scan_asm(String& src, ArrayToken& token_list)
                    621: {
                    622:        Scanner s(src);
                    623: 
                    624:        for (;;) {
                    625:                Token t;
                    626: 
                    627:                if (!s.get_token(t)) {
                    628:                        error("syntax error: %s", s.errmsg.c_str());
                    629:                }
                    630: 
                    631:                token_list.push_back(t);
                    632: 
                    633:                if (t.type == T_END) {
                    634:                        break;
                    635:                }
                    636:        }
                    637: 
                    638:        /* 行末(T_ENDの前)が空白なら削除 */
                    639:        if (token_list.size() > 1) {
                    640:                ArrayToken::iterator it = token_list.end();
                    641:                advance(it, -2);
                    642:                if ((*it).type == T_SPACE) {
                    643:                        token_list.erase(it);
                    644:                }
                    645:        }
                    646: 
                    647:        if ((debug & D_SCAN)) {
                    648:                for (int i = 0; i < token_list.size(); i++) {
                    649:                        Token t = token_list[i];
                    650: 
                    651:                        DPRINTF(D_SCAN, " %-7s |%s|", t.type_name(), t.word.c_str());
                    652:                        if (t.type == T_NUMBER || t.type == T_SIZE || t.type == T_CHAR) {
                    653:                                DPRINTN(D_SCAN, " num=$%x", t.number);
                    654:                        }
                    655:                        DPRINTN(D_SCAN, "\n");
                    656:                }
                    657:        }
                    658: }
                    659: 
                    660: /* トークン列をパースして処理する */
                    661: void
                    662: parse_token(ArrayToken& list)
                    663: {
                    664:        ArrayToken::iterator t;
                    665: 
                    666:        /* 命令処理前にグローバル変数をクリア */
                    667:        label0.erase();
                    668:        op0.erase();
                    669:        size0.erase();
                    670:        size_sfx = -1;
                    671:        oprand.clear();
                    672: 
                    673:        /* 先頭がリテラルならラベル */
                    674:        t = list.begin();
                    675:        if ((*t).type == T_LITERAL) {
                    676:                /* ラベルをリストに記憶 */
                    677:                DPRINTF(D_PARSE, "label='%s'\n", (*t).word.c_str());
                    678:                label0 = (*t).word;
                    679:                add_label(label0);
                    680:                t++;
                    681: 
                    682:                /* 直後がコロンならスペースに置き換えてから */
                    683:                if ((*t).type == T_COLON) {
                    684:                        (*t).type = T_SPACE;
                    685:                        t++;
                    686:                }
                    687:        }
                    688: 
                    689:        /* ラベルのみならここで終わり */
                    690:        if ((*t).type == T_END) {
                    691:                return;
                    692:        }
                    693:        /* そうでなければスペースのはずなので読み飛ばす */
                    694:        if ((*t).type == T_SPACE) {
                    695:                t++;
                    696:        }
                    697: 
                    698:        /* 命令語は必ずリテラルから始まっている */
                    699:        if ((*t).type != T_LITERAL) {
                    700:                error("syntax error: invalid opword: %s\n", (*t).word.c_str());
                    701:        }
                    702:        /* 命令語を取り出す */
                    703:        op0 = (*t).word;
                    704:        t++;
                    705: 
                    706:        /* 直後がサイズサフィックスなら記憶 */
                    707:        if ((*t).type == T_SIZE) {
                    708:                size0 = (*t).word;
                    709:                size_sfx = (*t).number;
                    710:                t++;
                    711:        }
                    712:        DPRINTF(D_PARSE, "op0='%s' %s(%d)\n",
                    713:                op0.c_str(), size0.c_str(), size_sfx);
                    714: 
                    715:        /* オペランドなしならここで終わり。ありなら空白のはず */
                    716:        if ((*t).type == T_END) {
                    717:                /* XXX 分岐は実行しないといけないのでこのまま進む */
                    718:                //return;
                    719:        } else if ((*t).type != T_SPACE) {
                    720:                error("syntax error: after opword: %s\n", (*t).word.c_str());
                    721:        }
                    722:        t++;
                    723: 
                    724:        /* 命令語からオペランド種別を取り出す */
                    725:        optable_t *opt = lookup(op0);
                    726:        if (opt == NULL) {
                    727:                error("unknown opcode: %s\n", op0.c_str());
                    728:        }
                    729:        switch (opt->oprand_type) {
                    730:         case OPR_EA:           /* 通常命令用の EA */
                    731:                parse_arg_ea(list, t);
                    732:                break;
                    733:         case OPR_LIST:         /* カンマ区切りリスト */
                    734:                parse_arg_list(list, t);
                    735:                break;
                    736:         case OPR_LITERAL:      /* 書式なし1つの引数 */
                    737:                parse_arg_literal(list, t);
                    738:                break;
                    739:         default:
                    740:                error("unknown oprand_type=%d (op=%s)\n",
                    741:                        opt->oprand_type, op0.c_str());
                    742:                break;
                    743:        }
                    744:        DPRINTF(D_PARSE, "oprand.size=%d", oprand.size());
                    745:        for (int i = 0; i < oprand.size(); i++) {
                    746:                DPRINTN(D_PARSE, " '%s'", oprand[i].c_str());
                    747:        }
                    748:        DPRINTN(D_PARSE, "\n");
                    749: 
                    750:        /* 命令語によって分岐 */
                    751:        opt->func(opt->opword);
                    752: }
                    753: 
                    754: /* オペランドを書式なしとしてパース。全部結合するだけ */
                    755: void
                    756: parse_arg_literal(ArrayToken& list, ArrayToken::iterator& t)
                    757: {
                    758:        String arg;
                    759: 
                    760:        DPRINTF(D_PARSE, "parse_arg_literal\n");
                    761: 
                    762:        for (; t != list.end(); t++) {
                    763:                if ((*t).type == T_END) {
                    764:                        break;
                    765:                }
                    766:                arg += (*t).word;
                    767:        }
                    768:        oprand.push_back(arg);
                    769: }
                    770: 
                    771: /* 疑似命令用のオペランド(カンマ区切りリスト)をパース */
                    772: void
                    773: parse_arg_list(ArrayToken& list, ArrayToken::iterator& t)
                    774: {
                    775:        String arg;
                    776: 
                    777:        DPRINTF(D_PARSE, "parse_arg_list\n");
                    778: 
                    779:        for (; t != list.end(); t++) {
                    780:                if ((*t).type == T_COMMA || (*t).type == T_END) {
                    781:                        oprand.push_back(arg);
                    782:                        arg.clear();
                    783:                } else if ((*t).type != T_SPACE) {
                    784:                        arg += (*t).word;
                    785:                }
                    786:        }
                    787: }
                    788: 
                    789: /* 命令のオペランド (EA) をパース */
                    790: void
                    791: parse_arg_ea(ArrayToken& list, ArrayToken::iterator& t)
                    792: {
                    793:        DPRINTF(D_PARSE, "parse_arg_ea\n");
                    794: #if 1
                    795:        /* XXX オペランドはとりあえず旧パーサの動作をシミュレートしておく */
                    796:        String arg;
                    797:        for (; t != list.end(); t++) {
                    798:                if ((*t).type == T_COMMA || (*t).type == T_END) {
                    799:                        oprand.push_back(arg);
                    800:                        arg.clear();
                    801:                } else if ((*t).type != T_SPACE) {
                    802:                        arg += (*t).word;
                    803:                }
                    804:        }
                    805: #endif
                    806: }
                    807: 
                    808: /* IOCS コールマクロを定義 */
                    809: void
                    810: include_iocs()
                    811: {
                    812:        std::pair<LabelHash::iterator, bool> r;
                    813: 
                    814:        for (int i = 0; i < countof(iocscall); i++) {
                    815:                String name(iocscall[i]);
                    816:                if (name.size() == 0 || name[0] == '$') {
                    817:                        continue;
                    818:                }
                    819:                String var = num2hex(i);
                    820: 
                    821:                r = label_list.insert(std::make_pair(name, var));
                    822:                if (r.second == 0) {
                    823:                        error("iocscall macro '%s' is duplicated\n", name.c_str());
                    824:                }
                    825:                //DPRINTF(D_LABEL, "LABEL '%s' <= '%s'\n", name.c_str(), var.c_str());
                    826:        }
                    827: }
                    828: 
                    829: /* ラベルをリストに記憶 */
                    830: void
                    831: add_label(String& label)
                    832: {
                    833:        std::pair<LabelHash::iterator, bool> r;
                    834:        String addr;
                    835: 
                    836:        addr = num2hex(::pc);
                    837:        r = label_list.insert(std::make_pair(label, addr));
                    838:        if (r.second == 0) {
                    839:                error("label '%s' is duplicated\n", label.c_str());
                    840:        }
                    841:        DPRINTF(D_LABEL, "LABEL '%s' <= '%s'\n", label.c_str(), addr.c_str());
                    842: }
                    843: 
                    844: /*
                    845:  * リストからラベルを探索。
                    846:  * 見付かれば var に置換後の文字列を格納して true を返す。
                    847:  * 見付からなければ false を返す。
                    848:  */
                    849: bool
                    850: find_label(String& label, String& var)
                    851: {
                    852:        LabelHash::iterator i;
                    853: 
                    854:        i = label_list.find(label);
                    855:        if (i == label_list.end()) {
                    856:                DPRINTF(D_LABEL, "'%s' => NOT FOUND\n", label.c_str());
                    857:                return false;
                    858:        }
                    859:        var = (*i).second;
                    860:        DPRINTF(D_LABEL, "'%s' => '%s'\n", label.c_str(), var.c_str());
                    861:        return true;
                    862: }
                    863: 
                    864: /* 命令をテーブルから検索 */
                    865: optable_t *
                    866: lookup(String& op)
                    867: {
                    868:        optable_t *t;
                    869: 
                    870:        for (t = optable; t->opname; t++) {
                    871:                if (strcasecmp(op.c_str(), t->opname) == 0) {
                    872:                        return t;
                    873:                }
                    874:        }
                    875:        return NULL;
                    876: }
                    877: 
                    878: /* .cinclude 擬似命令 */
                    879: void
                    880: op_cinclude(uint16_t opword)
                    881: {
                    882:        if (format == FORMAT_C) {
                    883:                fprintf(outfp, "#include %s\n", oprand[0].c_str());
                    884:        }
                    885: }
                    886: 
                    887: /* .org 擬似命令 */
                    888: void
                    889: op_org(uint16_t opword)
                    890: {
                    891:        if (oprand.size() != 1) {
                    892:                error(".org must have 1 oprand\n");
                    893:        }
                    894:        origin = tonumber(oprand[0]);
                    895:        pc = origin;
                    896:        DPRINTF(D_INOUT, "set origin=%06X\n", origin);
                    897: }
                    898: 
                    899: /* .start 擬似命令 */
                    900: void
                    901: op_start(uint16_t opword)
                    902: {
                    903:        /* C出力なら引数が必要。書式が変か… */
                    904:        if (format == FORMAT_C) {
                    905:                if (oprand.size() < 1) {
                    906:                        error(".start needs 1 oprand for C output\n");
                    907:                }
                    908:                current_name = oprand[0];
                    909:        }
                    910: 
                    911:        outbin.erase();
                    912:        rept_start = -1;
                    913:        rept_count = 0;
                    914: }
                    915: 
                    916: /* .end 擬似命令 */
                    917: void
                    918: op_end(uint16_t opword)
                    919: {
                    920:        /* 出力は必ずワード単位にする */
                    921:        op_even(0);
                    922: 
                    923:        /* 2nd ステージ (ラベルの解決) */
                    924:        DPRINTN(D_STAGE, "\n2nd stage\n");
                    925:        for (ArrayRef::iterator i = ref_list.begin(); i != ref_list.end(); ) {
                    926:                uint32_t uval;
                    927:                int val;
                    928: 
                    929:                /* 構造体を取り出す */
                    930:                REF *ref = *i;
                    931:                DPRINTN_ref(D_INOUT, ref);
                    932: 
                    933:                line = ref->line;
                    934: 
                    935:                /* 値を計算。ラベルが解決できなければ向こうでエラーにする */
                    936:                calc_expr(ref->expr, uval, true);
                    937:                val = uval;
                    938: 
                    939:                /* 種別ごとに範囲チェックして出力 */
                    940: DPRINTF(D_INOUT, "val=%d\n", val);
                    941:                switch (ref->type) {
                    942:                 case REFTYPE_BYTE:
                    943:                        if (val > 127 || val < -128) {
                    944:                                ::line = ref->line;
                    945:                                error("%d is insufficient in byte data\n", val);
                    946:                        }
                    947:                        DPRINTF(D_INOUT, "pos=%d => $%02x\n", ref->pos, val & 0xff);
                    948:                        outbin[ref->pos] = val;
                    949:                        break;
                    950: 
                    951:                 case REFTYPE_WORD:
                    952:                        if (val > 32767 || val < -32768) {
                    953:                                ::line = ref->line;
                    954:                                error("%d is insufficient in word data\n\n", val);
                    955:                        }
                    956:                        DPRINTF(D_INOUT, "pos=%d => $%04x\n", ref->pos, val & 0xffff);
                    957:                        outbin[ref->pos    ] = (val >> 8);
                    958:                        outbin[ref->pos + 1] = (val & 0xff);
                    959:                        break;
                    960: 
                    961:                 case REFTYPE_LONG:
                    962:                        DPRINTF(D_INOUT, "pos=%d => $%08x\n", ref->pos, val);
                    963:                        outbin[ref->pos    ] = (val >> 24) & 0xff;
                    964:                        outbin[ref->pos + 1] = (val >> 16) & 0xff;
                    965:                        outbin[ref->pos + 2] = (val >> 8)  & 0xff;
                    966:                        outbin[ref->pos + 3] =  val & 0xff;
                    967:                        break;
                    968: 
                    969:                 default:
                    970:                        error("unsupported reftype: %d\n", (int)ref->type);
                    971:                        break;
                    972:                }
                    973: 
                    974:                /* 解決したので削除 */
                    975:                ref_list.erase(i);
                    976:                delete ref;
                    977:        }
                    978: 
                    979:        /* 3rd ステージというか出力 */
                    980:        DPRINTN(D_STAGE, "\n3rd stage\n");
                    981:        switch (format) {
                    982:         case FORMAT_C:
                    983:                format_c();
                    984:                break;
                    985:         case FORMAT_BINARY:
                    986:                format_binary();
                    987:                break;
                    988:        }
                    989: 
                    990:        DPRINTN(D_STAGE, "\n3rd stage end\n\n");
                    991: }
                    992: 
                    993: /* Cソース形式で出力 */
                    994: void
                    995: format_c()
                    996: {
                    997:        fprintf(outfp, "\n");
                    998:        fprintf(outfp, "const BYTE %s[] = {", current_name.c_str());
                    999:        for (int i = 0; i < outbin.size(); i++) {
                   1000:                if ((i % 8) == 0) {
                   1001:                        fprintf(outfp, "\n\t");
                   1002:                }
                   1003:                fprintf(outfp, "0x%02x,", (uint8_t)outbin[i]);
                   1004:        }
                   1005:        fprintf(outfp, "\n};\n");
                   1006:        fprintf(outfp, "const int %s_size = %d;\n",
                   1007:                current_name.c_str(), (int)outbin.size());
                   1008: }
                   1009: 
                   1010: /* バイナリ形式で出力 */
                   1011: void
                   1012: format_binary()
                   1013: {
                   1014:        String buf;
                   1015:        int n;
                   1016: 
                   1017:        n = 0;
                   1018:        for (;;) {
                   1019:                buf = outbin.substr(n, 4096);
                   1020:                if (buf.size() == 0) {
                   1021:                        break;
                   1022:                }
                   1023: 
                   1024:                fwrite(buf.c_str(), 1, buf.size(), outfp);
                   1025:                n += buf.size();
                   1026:        }
                   1027: }
                   1028: 
                   1029: /* .dc 擬似命令 */
                   1030: void
                   1031: op_dc(uint16_t opword)
                   1032: {
                   1033:        ArrayString::iterator i;
                   1034:        for (i = oprand.begin(); i != oprand.end(); i++) {
                   1035:                String arg = *i;
                   1036: 
                   1037:                /* .b でダブルクォートから始まってたら文字列 */
                   1038:                if (size_sfx == 1 && arg[0] == '\x22') {
                   1039:                        /* 文字列を解析 */
                   1040:                        String str = parse_string(arg);
                   1041: 
                   1042:                        /* 日本語文字コードを変換 */
                   1043:                        str = convert_charset(str);
                   1044: 
                   1045:                        for (int j = 0; j < str.size(); j++) {
                   1046:                                output_b(str[j]);
                   1047:                        }
                   1048: 
                   1049:                } else if (size_sfx == 1 && arg[0] == '\'') {
                   1050:                        /* XXX まだこれには対応できないので旧方式で対応 */
                   1051:                        output_b(tonumber(arg));
                   1052: 
                   1053:                } else {
                   1054:                        /* そうでなければ式として評価 */
                   1055:                        ArrayString expr;
                   1056:                        uint32_t val;
                   1057:                        parse_expr(*i, expr);
                   1058:                        if (calc_expr(expr, val, false)) {
                   1059:                                /* 解決できたので出力 */
                   1060:                                output_bin(val, size_sfx);
                   1061:                        } else {
                   1062:                                /* 解決できなかった */
                   1063:                                switch (size_sfx) {
                   1064:                                 case 1:
                   1065:                                        add_expr(::outbin.size(), REFTYPE_BYTE, expr);
                   1066:                                        break;
                   1067:                                 case 2:
                   1068:                                        add_expr(::outbin.size(), REFTYPE_WORD, expr);
                   1069:                                        break;
                   1070:                                 case 4:
                   1071:                                        add_expr(::outbin.size(), REFTYPE_LONG, expr);
                   1072:                                        break;
                   1073:                                 default:
                   1074:                                        abort();
                   1075:                                }
                   1076:                                output_bin(0, size_sfx);
                   1077:                        }
                   1078:                }
                   1079:        }
                   1080: }
                   1081: 
                   1082: /* .ds 擬似命令 */
                   1083: void
                   1084: op_ds(uint16_t opword)
                   1085: {
                   1086:        ArrayString::iterator i;
                   1087:        for (i = oprand.begin(); i != oprand.end(); i++) {
                   1088:                int size = tonumber(*i);
                   1089:                output_ds(size * size_sfx);
                   1090:        }
                   1091: }
                   1092: 
                   1093: /* .even 擬似命令 */
                   1094: void
                   1095: op_even(uint16_t opword)
                   1096: {
                   1097:        /* 奇数なら偶数に合わせる */
                   1098:        if ((outbin.size() & 1)) {
                   1099:                output_b(0);
                   1100:        }
                   1101: }
                   1102: 
                   1103: /* .equ 擬似命令 */
                   1104: void
                   1105: op_equ(uint16_t opword)
                   1106: {
                   1107:        if (label0.empty()) {
                   1108:                error(".equ must have a label\n");
                   1109:        }
                   1110:        if (oprand.size() != 1) {
                   1111:                error(".equ must have 1 oprand\n");
                   1112:        }
                   1113: 
                   1114:        /* ラベルの値を PC ではなくオペランド指定の値に差し替える */
                   1115:        LabelHash::iterator i;
                   1116:        /* 見付からないはずはないのでエラー処理省略? */
                   1117:        i = label_list.find(label0);
                   1118:        (*i).second = oprand[0];
                   1119:        DPRINTF(D_LABEL, "LABEL '%s' EQU '%s'\n",
                   1120:                (*i).first.c_str(), (*i).second.c_str());
                   1121: }
                   1122: 
                   1123: /* .rept 擬似命令 */
                   1124: void
                   1125: op_rept(uint16_t opword)
                   1126: {
                   1127:        ArrayString expr;
                   1128:        uint32_t cnt;
                   1129: 
                   1130:        if (rept_start != -1) {
                   1131:                error(".rept duplicated\n");
                   1132:        }
                   1133: 
                   1134:        /* ここを記憶しておくだけ */
                   1135:        rept_start = outbin.size();
                   1136:        /* 回数は <式> で、この時点で解決できなければいけない */
                   1137:        parse_expr(oprand[0], expr);
                   1138:        calc_expr(expr, cnt, true);
                   1139:        rept_count = cnt;
                   1140: 
                   1141:        DPRINTF(D_INOUT, ".rept start=$%x count=$%x\n",
                   1142:                rept_start, rept_count);
                   1143: }
                   1144: 
                   1145: /* .endrept 擬似命令 */
                   1146: /* XXX 最終的には HAS に合わせて endm にしたい */
                   1147: void
                   1148: op_endrept(uint16_t opword)
                   1149: {
                   1150:        String target;
                   1151:        int rept_size;
                   1152:        int total_size;
                   1153: 
                   1154:        if (rept_start == -1) {
                   1155:                error(".endrept without .rept\n");
                   1156:        }
                   1157: 
                   1158:        /* .rept の位置からここまでの内容を取得 */
                   1159:        rept_size = outbin.size() - rept_start;
                   1160:        target = outbin.substr(rept_start, rept_size);
                   1161: 
                   1162:        /* それを (rept_count-1) 回出力。1回目はすでに出力してあるから */
                   1163:        rept_count--;
                   1164:        for (int i = 0; i < rept_count; i++) {
                   1165:                outbin += target;
                   1166:        }
                   1167: 
                   1168:        total_size = rept_size * rept_count;
                   1169:        pc += total_size;
                   1170:        DPRINTF(D_INOUT, "output $%x(%d) bytes x $%x(%d) = $%x(%d) bytes\n",
                   1171:                rept_size, rept_size,
                   1172:                rept_count, rept_count,
                   1173:                total_size, total_size);
                   1174: 
                   1175:        /* パラメータをクリア */
                   1176:        rept_count = 0;
                   1177:        rept_start = -1;
                   1178: }
                   1179: 
                   1180: /* IOCS マクロ命令 */
                   1181: void
                   1182: op_iocs(uint16_t opword)
                   1183: {
                   1184:        char moveqbuf[32];
                   1185:        int num;
                   1186: 
                   1187:        num = tonumber(oprand[0]) & 0xff;
                   1188:        snprintf(moveqbuf, sizeof(moveqbuf), " moveq.l #$%x,d0", num);
                   1189:        String moveq(moveqbuf);
                   1190:        String trap(" trap #15");
                   1191: 
                   1192:        parse_asm(moveq);
                   1193:        parse_asm(trap);
                   1194: }
                   1195: 
                   1196: /* bcc */
                   1197: /* XXX Bcc.b <cond>,<label> というニーモニックにする */
                   1198: void
                   1199: op_bcc(uint16_t opword)
                   1200: {
                   1201:        int cc;
                   1202: 
                   1203:        /* bra/bcc だけ .s を .b に読み替えて認める */
                   1204:        if (size_sfx == 0 && tolower(size0[1]) == 's') {
                   1205:                size_sfx = 1;
                   1206:        }
                   1207: 
                   1208:        if (size_sfx == 1) {
                   1209:                cc = get_cc(oprand[0]);
                   1210:                add_ref(REFTYPE_BYTE, oprand[1]);
                   1211: 
                   1212:                opword |= cc << 8;
                   1213:                output_w(opword);
                   1214:        } else {
                   1215:                error("unsupported size: %s%s\n", op0.c_str(), size0.c_str());
                   1216:        }
                   1217: }
                   1218: 
                   1219: /* bra */
                   1220: void
                   1221: op_bra(uint16_t opword)
                   1222: {
                   1223:        /* bra/bcc だけ .s を .b に読み替えて認める */
                   1224:        if (size_sfx == 0 && tolower(size0[1]) == 's') {
                   1225:                size_sfx = 1;
                   1226:        }
                   1227: 
                   1228:        if (size_sfx == 1) {
                   1229:                add_ref(REFTYPE_BYTE, oprand[0]);
                   1230:                output_w(opword);
                   1231:        } else {
                   1232:                error("unsupported size: %s%s\n", op0.c_str(), size0.c_str());
                   1233:        }
                   1234: }
                   1235: 
                   1236: /* clr */
                   1237: void
                   1238: op_clr(uint16_t opword)
                   1239: {
                   1240:        EA dst;
                   1241: 
                   1242:        dst = get_ea(oprand[0]);
                   1243: 
                   1244:        opword |= dst.mode | size6[size_sfx];
                   1245: 
                   1246:        output_w(opword);
                   1247:        output_ea(dst);
                   1248: }
                   1249: 
                   1250: /* dbra */
                   1251: void
                   1252: op_dbra(uint16_t opword)
                   1253: {
                   1254:        EA src;
                   1255: 
                   1256:        src = get_ea(oprand[0]);
                   1257:        add_ref(REFTYPE_WORD, oprand[1]);
                   1258: 
                   1259:        opword |= src.num();
                   1260: 
                   1261:        output_w(opword);
                   1262:        output_w(0);
                   1263: }
                   1264: 
                   1265: /* jmp */
                   1266: void
                   1267: op_jmp(uint16_t opword)
                   1268: {
                   1269:        EA dst;
                   1270: 
                   1271:        dst = get_ea(oprand[0]);
                   1272: 
                   1273:        output_w(opword | dst.mode);
                   1274:        output_ea(dst);
                   1275: }
                   1276: 
                   1277: /* lea.l */
                   1278: void
                   1279: op_lea(uint16_t opword)
                   1280: {
                   1281:        EA src, dst;
                   1282: 
                   1283:        if (size_sfx == -1) {
                   1284:                size_sfx = 4;
                   1285:        }
                   1286:        if (size_sfx != 4) {
                   1287:                error("invalid opcode: %s%s\n", op0.c_str(), size0.c_str());
                   1288:        }
                   1289: 
                   1290:        src = get_ea(oprand[0]);
                   1291:        dst = get_ea(oprand[1]);
                   1292: 
                   1293:        if (dst.type() != 0x01) {
                   1294:                error("syntax error: LEA dst must be An\n");
                   1295:        }
                   1296: 
                   1297:        opword |= src.mode;
                   1298:        opword |= dst.num() << 9;
                   1299: 
                   1300:        output_w(opword);
                   1301:        output_ea(src);
                   1302: }
                   1303: 
                   1304: /* move */
                   1305: void
                   1306: op_move(uint16_t opword)
                   1307: {
                   1308:        EA src, dst;
                   1309: 
                   1310:        /* move an,usp */
                   1311:        if (oprand[1] == "usp") {
                   1312:                if (size_sfx == -1) {
                   1313:                        size_sfx = 4;
                   1314:                }
                   1315:                if (size_sfx != 4) {
                   1316:                        error("syntax error: MOVE An,USP must .L");
                   1317:                }
                   1318:                src = get_ea(oprand[0], EAT_An);
                   1319:                opword = 0x4e60 + src.num();
                   1320:                output_w(opword);
                   1321:                return;
                   1322:        }
                   1323:        /* move usp,an */
                   1324:        if (oprand[0] == "usp") {
                   1325:                dst = get_ea(oprand[1]);
                   1326:                if (size_sfx == -1) {
                   1327:                        size_sfx = 4;
                   1328:                }
                   1329:                if (size_sfx != 4) {
                   1330:                        error("syntax error: MOVE USP,An must .L");
                   1331:                }
                   1332:                opword = 0x4e68 + dst.num();
                   1333:                output_w(opword);
                   1334:                return;
                   1335:        }
                   1336: 
                   1337:        src = get_ea(oprand[0]);
                   1338:        dst = get_ea(oprand[1]);
                   1339: 
                   1340:        switch (size_sfx) {
                   1341:         case 1:        opword = 0x1000;        src.size = 1;   break;
                   1342:         case 2:        opword = 0x3000;        src.size = 2;   break;
                   1343:         case 4:        opword = 0x2000;        src.size = 4;   break;
                   1344:        }
                   1345:        opword |= src.mode;
                   1346:        opword |= (dst.type() | (dst.num() << 3)) << 6;
                   1347: 
                   1348:        output_w(opword);
                   1349:        output_ea(src);
                   1350:        output_ea(dst);
                   1351: }
                   1352: 
                   1353: /* movem.l */
                   1354: void
                   1355: op_movem(uint16_t opword)
                   1356: {
                   1357:        uint16_t list;
                   1358:        EA ea;
                   1359:        String errmsg;
                   1360: 
                   1361:        if (size_sfx == 4) {    /* .L */
                   1362:                opword |= 0x0040;
                   1363:        }
                   1364: 
                   1365:        if (get_reglist(oprand[0], list)
                   1366:         && try_ea(oprand[1], ea, errmsg, EAT_AI | EAT_APD | EAT_AREL | EAT_ABS))
                   1367:        {
                   1368:                /* movem.l list,ea */
                   1369:                opword |= ea.mode;
                   1370: 
                   1371:                /* -(An) の時だけビット並び順を反転 */
                   1372:                if ((ea.mode & 0x38) == EA_An_PD) {
                   1373:                        uint16_t rev = 0;
                   1374:                        for (int i = 0; i < 16; i++) {
                   1375:                                if ((list & (1 << i)) != 0) {
                   1376:                                        rev |= 0x8000 >> i;
                   1377:                                }
                   1378:                        }
                   1379:                        list = rev;
                   1380:                }
                   1381: 
                   1382:                output_w(opword);
                   1383:                output_w(list);
                   1384:                output_ea(ea);
                   1385:                return;
                   1386:        }
                   1387:        if (try_ea(oprand[0], ea, errmsg, EAT_AI | EAT_API | EAT_AREL | EAT_ABS)
                   1388:         && get_reglist(oprand[1], list))
                   1389:        {
                   1390:                /* movem.l ea,list */
                   1391:                opword |= ea.mode;
                   1392:                opword |= 0x0400;       /* ea->list */
                   1393: 
                   1394:                output_w(opword);
                   1395:                output_w(list);
                   1396:                output_ea(ea);
                   1397:                return;
                   1398:        }
                   1399: 
                   1400:        error("invalid movem oprand\n");
                   1401: }
                   1402: 
                   1403: /* moveq.l */
                   1404: void
                   1405: op_moveq(uint16_t opword)
                   1406: {
                   1407:        EA src, dst;
                   1408: 
                   1409:        if (size_sfx == -1) {
                   1410:                size_sfx = 4;
                   1411:        }
                   1412:        if (size_sfx != 4) {
                   1413:                error("invalid opcode: %s%s\n", op0.c_str(), size0.c_str());
                   1414:        }
                   1415: 
                   1416:        src = get_ea(oprand[0]);
                   1417:        dst = get_ea(oprand[1]);
                   1418:        if (src.mode != EA_IMMEDIATE) {
                   1419:                error("invalid oprand\n");
                   1420:        }
                   1421:        if (src.val > 0xff) {
                   1422:                error("moveq.l #$%x too large\n", src.val);
                   1423:        }
                   1424: 
                   1425:        opword |= src.val & 0xff;
                   1426:        opword |= dst.num() << 9;
                   1427: 
                   1428:        output_w(opword);
                   1429: }
                   1430: 
                   1431: /* sub */
                   1432: void
                   1433: op_sub(uint16_t opword)
                   1434: {
                   1435:        EA src = get_ea(oprand[0]);
                   1436:        EA dst = get_ea(oprand[1]);
                   1437: 
                   1438:        switch (size_sfx) {
                   1439:         case 1:        opword |= 0x00; break;
                   1440:         case 2:        opword |= 0x40; break;
                   1441:         case 4:        opword |= 0x80; break;
                   1442:         default:
                   1443:                error("syntax error: size?");
                   1444:        }
                   1445: 
                   1446:        if (dst.type() == 0) {
                   1447:                // SUB.S <ea>,Dn
                   1448:                // XXX src の正当性チェック
                   1449:                opword |= src.mode;
                   1450:                opword |= dst.num() << 9;
                   1451:                output_w(opword);
                   1452:                output_ea(src);
                   1453:                return;
                   1454:        }
                   1455:        if (dst.type() == 0) {
                   1456:                // SUB.S Dn,<ea>
                   1457:                // XXX dst の正当性チェック
                   1458:                opword |= 0x0100;
                   1459:                opword |= src.num() << 9;
                   1460:                opword |= dst.mode;
                   1461:                output_w(opword);
                   1462:                output_ea(dst);
                   1463:                return;
                   1464:        }
                   1465:        error("syntax error");
                   1466: }
                   1467: 
                   1468: /* suba */
                   1469: void
                   1470: op_suba(uint16_t opword)
                   1471: {
                   1472:        EA src = get_ea(oprand[0]);
                   1473:        EA dst = get_ea(oprand[1]);
                   1474:        switch (size_sfx) {
                   1475:         case -1:
                   1476:         case 2:        opword |= 0x0000;       break;
                   1477:         case 4:        opword |= 0x0100;       break;
                   1478:         default:
                   1479:                error("syntax error: .B is invalid\n");
                   1480:        }
                   1481:        opword |= src.mode;
                   1482:        opword |= dst.num() << 9;
                   1483:        output_w(opword);
                   1484:        output_ea(src);
                   1485: }
                   1486: 
                   1487: /* trap */
                   1488: void
                   1489: op_trap(uint16_t opword)
                   1490: {
                   1491:        EA src;
                   1492: 
                   1493:        src = get_ea(oprand[0]);
                   1494:        if (src.mode != EA_IMMEDIATE) {
                   1495:                error("invalid oprand\n");
                   1496:        }
                   1497:        if (src.val > 15) {
                   1498:                error("trap #$%x too large\n", src.val);
                   1499:        }
                   1500: 
                   1501:        opword |= src.val;
                   1502:        output_w(opword);
                   1503: }
                   1504: 
                   1505: /* nop、rts などオペランドを持たないやつ */
                   1506: void
                   1507: op_noarg(uint16_t opword)
                   1508: {
                   1509:        output_w(opword);
                   1510: }
                   1511: 
                   1512: /*
                   1513:  * 指定されたeatype に bit が立ってなければ、
                   1514:  * この命令でこの EA は認められていない。
                   1515:  */
                   1516: #define check_eatype(bit)      \
                   1517:        if ((eatype & (bit)) == 0) {    \
                   1518:                DPRINTF(D_EA, "EAT 0x%x not match in eatype=0x%x\n", bit, eatype);      \
                   1519:                errmsg = "invalid ea";  \
                   1520:                return false;   \
                   1521:        }
                   1522: 
                   1523: /*
                   1524:  * EA がパースできるかどうかを返す。
                   1525:  * errmes が NULL でなければ、パースできなかった時のエラーメッセージを
                   1526:  * 格納する。
                   1527:  */
                   1528: bool
                   1529: try_ea(String& eabuf, EA& ea, String& errmsg, int eatype)
                   1530: {
                   1531: #if defined(_MSC_VER)
                   1532:        char buf[BUFSIZE];
                   1533: #else
                   1534:        char buf[eabuf.size() + 1];
                   1535: #endif
                   1536:        int i;
                   1537: 
                   1538: #if defined(_MSC_VER)
                   1539:        strncpy(buf, eabuf.c_str(), sizeof(buf) - 1);
                   1540:        buf[sizeof(buf) - 1] = '\0';
                   1541: #else
                   1542:        strcpy(buf, eabuf.c_str());
                   1543: #endif
                   1544: 
                   1545:        /* 固定文字列との比較。見つかればすぐ帰れる */
                   1546:        for (i = 0; i < countof(regname); i++) {
                   1547:                if (strcasecmp(buf, regname[i]) == 0) {
                   1548:                        ea.mode = i;
                   1549:                        DPRINTF(D_EA, "ea=reg,%s -> 0x%x\n", regname[ea.mode], ea.mode);
                   1550:                        check_eatype(1 << (i / 8));
                   1551:                        return true;
                   1552:                }
                   1553:        }
                   1554: 
                   1555:        /* d16(pc) */
                   1556:        i = strlen(buf) - 4;
                   1557:        if (i > 0 && strcasecmp(buf + i, "(pc)") == 0) {
                   1558:                String label = eabuf.substr(0, i);
                   1559:                add_ref(REFTYPE_WORD, label);
                   1560:                ea.mode = EA_d16PC;
                   1561:                DPRINTF(D_EA, "ea=d16(PC) label=%s\n", label.c_str());
                   1562:                check_eatype(EAT_PCREL);
                   1563:                return true;
                   1564:        }
                   1565: 
                   1566:        /* #imm */
                   1567:        /* XXX マクロ展開後が #imm だったら解決できないこれ */
                   1568:        if (buf[0] == '#') {
                   1569:                String label = eabuf.substr(1);
                   1570:                ea.mode = EA_IMMEDIATE;
                   1571:                ea.val = tonumber(label);
                   1572:                DPRINTF(D_EA, "ea=#imm,$%x\n", ea.val);
                   1573:                check_eatype(EAT_IMM);
                   1574:                return true;
                   1575:        }
                   1576: 
                   1577:        /* XXX An間接、PC間接系は未実装 */
                   1578: 
                   1579:        /* どれでもなさそうなら? */
                   1580:        /* Abs[.WL] */
                   1581:        ea.size = 0;
                   1582:        i = strlen(buf) - 2;
                   1583:        if (i > 0) {
                   1584:                if (strcasecmp(buf + i, ".W") == 0) {
                   1585:                        ea.size = 2;
                   1586:                } else if (strcasecmp(buf + i, ".L") == 0) {
                   1587:                        ea.size = 4;
                   1588:                }
                   1589:        }
                   1590:        ea.mode = EA_ABS_W;
                   1591:        int intval;
                   1592:        if (parse_number(eabuf, &intval)) {
                   1593:                ea.val = intval;
                   1594:                if (ea.size == 0) {
                   1595:                        ea.size = (ea.val > 0xffff) ? 4 : 2;
                   1596:                }
                   1597:                ea.mode = (ea.size == 4) ? EA_ABS_L : EA_ABS_W;
                   1598:                if (ea.val > 0xffff && ea.mode == EA_ABS_W) {
                   1599:                        errmsg = "Exceed Abs.W";
                   1600:                        return false;
                   1601:                }
                   1602:                DPRINTF(D_EA, "ea=ABS.%c,$%x\n",
                   1603:                        (ea.mode==EA_ABS_W)?'W':'L', ea.val);
                   1604:                check_eatype(EAT_ABS);
                   1605:                return true;
                   1606:        }
                   1607: 
                   1608:        DPRINTF(D_EA, "unknown EA: %s\n", buf);
                   1609:        errmsg = "unknown EA: ";
                   1610:        errmsg += eabuf;
                   1611:        return false;
                   1612: }
                   1613: 
                   1614: /*
                   1615:  * EA をパースして返す。
                   1616:  * 成功すれば EA を返す。失敗すればエラー終了する。
                   1617:  */
                   1618: EA
                   1619: get_ea(String& eabuf)
                   1620: {
                   1621:        return get_ea(eabuf, EAT_ALL);
                   1622: }
                   1623: 
                   1624: /*
                   1625:  * EA をパースして返す。
                   1626:  * eatype は許可する EA タイプ。
                   1627:  * 成功すれば EA を返す。失敗すればエラー終了する。
                   1628:  */
                   1629: EA
                   1630: get_ea(String& eabuf, int eatype)
                   1631: {
                   1632:        EA ea;
                   1633:        String errmsg;
                   1634: 
                   1635:        if (try_ea(eabuf, ea, errmsg, eatype) == false) {
                   1636:                error("%s", errmsg.c_str());
                   1637:        }
                   1638:        return ea;
                   1639: }
                   1640: 
                   1641: /*
                   1642:  * reglist をパースする。
                   1643:  * reglist でなさそうならエラーを表示せず false を返す。
                   1644:  * true を返した場合の list は常に b15-b0 の順で A7-A0/D7-D0。
                   1645:  */
                   1646: bool
                   1647: get_reglist(String& inbuf, uint16_t& list)
                   1648: {
                   1649: #if defined(_MSC_VER)
                   1650:        char buf[BUFSIZE];
                   1651: #else
                   1652:        char buf[inbuf.size() + 1];
                   1653: #endif
                   1654:        char *s;
                   1655:        int num;
                   1656:        int prevnum;
                   1657:        int Aoffset;
                   1658:        enum {
                   1659:                INIT,
                   1660:                REG,
                   1661:                NUM1,
                   1662:                NUM2,
                   1663:        } state;
                   1664: 
                   1665: #if defined(_MSC_VER)
                   1666:        strncpy(buf, inbuf.c_str(), sizeof(buf) - 1);
                   1667:        buf[sizeof(buf) - 1] = '\0';
                   1668: #else
                   1669:        strcpy(buf, inbuf.c_str());
                   1670: #endif
                   1671: 
                   1672:        state = INIT;
                   1673:        num = -1;
                   1674:        prevnum = -1;
                   1675:        Aoffset = 0;
                   1676:        for (s = buf; *s; s++) {
                   1677:                char c = (int)*s;
                   1678:                if (state == INIT) {
                   1679:                        if (tolower(c) == 'd') {
                   1680:                                state = REG;
                   1681:                                Aoffset = 0;
                   1682:                                continue;
                   1683:                        }
                   1684:                        if (tolower(c) == 'a') {
                   1685:                                state = REG;
                   1686:                                Aoffset = 8;
                   1687:                                continue;
                   1688:                        }
                   1689:                        return false;
                   1690:                } else if (state == REG) {
                   1691:                        if (!isdigit(c)) {
                   1692:                                return false;
                   1693:                        }
                   1694:                        num = c - '0';
                   1695:                        num += Aoffset;
                   1696:                        if (prevnum == -1) {
                   1697:                                // 単独もしくは範囲指定の1つ目のレジスタ指定
                   1698:                                list |= (1 << num);
                   1699:                                state = NUM1;
1.1.1.2   root     1700:                        } else {
1.1       root     1701:                                // 範囲指定の2つ目のレジスタ
                   1702:                                for (int i = prevnum; i <= num; i++) {
                   1703:                                        list |= (1 << i);
                   1704:                                }
                   1705:                                prevnum = -1;
                   1706:                                state = NUM2;
                   1707:                        }
                   1708:                        continue;
                   1709:                } else if (state == NUM1) {
                   1710:                        // 単独もしくは範囲指定の1つ目のレジスタの後
                   1711:                        if (c == '/') {
                   1712:                                prevnum = -1;
                   1713:                                state = INIT;
                   1714:                                continue;
                   1715:                        }
                   1716:                        if (c == '-') {
                   1717:                                prevnum = num;
                   1718:                                state = INIT;
                   1719:                                continue;
                   1720:                        }
                   1721:                        return false;
                   1722:                } else if (state == NUM2) {
                   1723:                        // 範囲指定の2つ目のレジスタの後に '-' はこない
                   1724:                        if (c == '/') {
                   1725:                                state = INIT;
                   1726:                                continue;
                   1727:                        }
                   1728:                        return false;
                   1729:                }
                   1730:                return false;
                   1731:        }
                   1732: 
                   1733:        DPRINTF(D_EA, "reglist = %04X\n", list);
                   1734:        return true;
                   1735: }
                   1736: 
                   1737: /* cc をパースして返す */
                   1738: int
                   1739: get_cc(String& ccbuf)
                   1740: {
                   1741:        int i;
                   1742: 
                   1743:        for (i = 0; i < countof(ccname); i++) {
                   1744:                if (strcasecmp(ccbuf.c_str(), ccname[i]) == 0) {
                   1745:                        DPRINTF(D_EA, "cc=%s -> 0x%x\n", ccname[i], i);
                   1746:                        return i;
                   1747:                }
                   1748:        }
                   1749: 
                   1750:        error("unknown CC: %s\n", ccbuf.c_str());
                   1751:        /* NOTREACHED */
                   1752:        return 0;
                   1753: }
                   1754: 
                   1755: /* 参照をリストに追加。おもに Bcc と d16(PC) 用? */
                   1756: void
                   1757: add_ref(reftype_t type, String& label)
                   1758: {
                   1759:        /* expr = label - (pc+2) */
                   1760:        ArrayString expr;
                   1761:        expr.push_back(label);
                   1762:        expr.push_back(num2hex(::pc + 2));
                   1763:        expr.push_back(String("-"));
                   1764: 
                   1765:        /* オフセット */
                   1766:        int offset;
                   1767:        switch (type) {
                   1768:         case REFTYPE_BYTE:
                   1769:                offset = 1;
                   1770:                break;
                   1771:         case REFTYPE_WORD:
                   1772:         case REFTYPE_LONG:
                   1773:                offset = 2;
                   1774:                break;
                   1775:         default:
                   1776:                error("unknown reftype %d\n", type);
                   1777:        }
                   1778: 
                   1779:        add_expr(::outbin.size() + offset, type, expr);
                   1780: }
                   1781: 
                   1782: /* EA を出力 */
                   1783: void
                   1784: output_ea(EA& ea)
                   1785: {
                   1786:        switch (ea.mode) {
                   1787:         case EA_d16PC:
                   1788:                output_w(0);
                   1789:                break;
                   1790:         case EA_ABS_W:
                   1791:                output_w(ea.val);
                   1792:                break;
                   1793:         case EA_ABS_L:
                   1794:                output_l(ea.val);
                   1795:                break;
                   1796:         case EA_IMMEDIATE:
1.1.1.3 ! root     1797:                if (ea.size == 4) {
        !          1798:                        output_l(ea.val);
        !          1799:                } else {
        !          1800:                        output_w(ea.val);
        !          1801:                }
1.1       root     1802:                break;
                   1803:         default:
                   1804:                /* それ以外は何もしない */
                   1805:                break;
                   1806:        }
                   1807: }
                   1808: 
                   1809: /* nバイトを出力 */
                   1810: void
                   1811: output_bin(uint32_t data, int size)
                   1812: {
                   1813:        switch (size) {
                   1814:         case 1:
                   1815:                output_b(data);
                   1816:                break;
                   1817:         case 2:
                   1818:                output_w(data);
                   1819:                break;
                   1820:         case 4:
                   1821:                output_l(data);
                   1822:                break;
                   1823:         default:
                   1824:                error("output_bin: invalid size %d\n", size);
                   1825:                break;
                   1826:        }
                   1827: }
                   1828: 
                   1829: /* 1バイトを出力 */
                   1830: void
                   1831: output_b(uint32_t data)
                   1832: {
                   1833:        data &= 0xff;
                   1834:        DPRINTF(D_INOUT, "output: $%06X => $%02X\n", pc, data);
                   1835:        outbin.push_back(data);
                   1836:        pc += 1;
                   1837: }
                   1838: 
                   1839: /* 1ワードを出力 */
                   1840: void
                   1841: output_w(uint32_t data)
                   1842: {
                   1843:        data &= 0xffff;
                   1844:        DPRINTF(D_INOUT, "output: $%06X => $%04X\n", pc, data);
                   1845:        outbin.push_back(data >> 8);
                   1846:        outbin.push_back(data & 0xff);
                   1847:        pc += 2;
                   1848: }
                   1849: 
                   1850: /* 1ロングワードを出力 */
                   1851: void
                   1852: output_l(uint32_t data)
                   1853: {
                   1854:        DPRINTF(D_INOUT, "output: $%06X => $%08X\n", pc, data);
                   1855:        outbin.push_back(data >> 24);
                   1856:        outbin.push_back((data >> 16) & 0xff);
                   1857:        outbin.push_back((data >>  8) & 0xff);
                   1858:        outbin.push_back(data & 0xff);
                   1859:        pc += 4;
                   1860: }
                   1861: 
                   1862: /* .ds 用に指定の長さを 0 で埋める */
                   1863: void
                   1864: output_ds(int size)
                   1865: {
                   1866:        DPRINTF(D_INOUT, "output: $%X(%d)bytes\n", size, size);
                   1867:        String ds(size, '\0');
                   1868:        outbin += ds;
                   1869:        pc += size;
                   1870: }
                   1871: 
                   1872: /* 数値を String に変換 */
                   1873: String
                   1874: num2str(int num)
                   1875: {
                   1876:        char buf[16];
                   1877:        snprintf(buf, sizeof(buf), "%d", num);
                   1878:        String ret(buf);
                   1879:        return ret;
                   1880: }
                   1881: 
                   1882: /* 数値を $HHHH 形式の String に変換 */
                   1883: String
                   1884: num2hex(int num)
                   1885: {
                   1886:        char buf[16];
                   1887:        snprintf(buf, sizeof(buf), "$%x", num);
                   1888:        String ret(buf);
                   1889:        return ret;
                   1890: }
                   1891: 
                   1892: /*
                   1893:  * 文字列を数値に変換。
                   1894:  * 変換できれば true、できなければ false を返す。
                   1895:  * 変換できた場合は、numptr が NULL でなければ結果を格納して返す。
                   1896:  */
                   1897: bool
                   1898: parse_number(String& str, int *numptr)
                   1899: {
                   1900:        try {
                   1901:                /* 先頭が数字なら10進数 */
                   1902:                if (isdigit((int)str[0])) {
                   1903:                        throw (int)strtol(str.c_str(), NULL, 10);
                   1904:                }
                   1905: 
                   1906:                /* $HH 形式なら16進数 */
                   1907:                if (str[0] == '$' && str.size() > 1) {
                   1908:                        String buf = str;
                   1909:                        buf.erase(0, 1);
                   1910:                        /* エラー処理無視 */
                   1911:                        throw (int)strtol(buf.c_str(), NULL, 16);
                   1912:                }
                   1913: 
                   1914:                /* 'X'形式なら1文字 */
                   1915:                if (str[0] == '\'' && str.size() == 3 && str[2] == '\'') {
                   1916:                        throw (int)str[1];
                   1917:                }
                   1918: 
                   1919:                /* (既出の)ラベルと一致するか */
                   1920:                String val;
                   1921:                if (find_label(str, val)) {
                   1922:                        int num;
                   1923:                        if (parse_number(val, &num)) {
                   1924:                                throw num;
                   1925:                        }
                   1926:                }
                   1927:        } catch (int num) {
                   1928:                /* 見つかった時に例外でここに飛んでくる */
                   1929:                if (numptr) {
                   1930:                        *numptr = num;
                   1931:                }
                   1932:                return true;
                   1933:        }
                   1934: 
                   1935:        /* 解決できなかった */
                   1936:        return false;
                   1937: }
                   1938: 
                   1939: /* 文字列を数値に変換。変換できなければアセンブルエラーで停止する */
                   1940: int
                   1941: tonumber(String& str)
                   1942: {
                   1943:        int num;
                   1944: 
                   1945:        if (!parse_number(str, &num)) {
                   1946:                error("invalid number: %s\n", str.c_str());
                   1947:        }
                   1948:        return num;
                   1949: }
                   1950: 
                   1951: /* 式を解析する */
                   1952: bool
                   1953: parse_expr(String& expr, ArrayString& out)
                   1954: {
                   1955:        ArrayString tokens;
                   1956:        std::stack<String> stack;
                   1957: 
                   1958:        DPRINTF(D_PARSE, "parse_expr.0 expr |%s|\n", expr.c_str());
                   1959: 
                   1960:        /* トークンに分解 */
                   1961:        if (!scan_expr(expr, tokens)) {
                   1962:                error("scan error: '%s'\n", expr.c_str());
                   1963:        }
                   1964: 
                   1965:        /* 中置記法を後置記法に変換 */
                   1966:        for (int i = 0; i < tokens.size(); i++) {
                   1967:                String token = tokens[i];
                   1968:                const char *tok = token.c_str();
                   1969: 
                   1970:                if (strcmp(tok, "+") == 0 || strcmp(tok, "-") == 0) {
                   1971:                        for (; stack.size() > 0 && stack.top()[0] != '('; ) {
                   1972:                                out.push_back(stack.top());
                   1973:                                stack.pop();
                   1974:                        }
                   1975:                        stack.push(token);
                   1976: 
                   1977:                } else if (strcmp(tok, "*") == 0 || strcmp(tok, "/") == 0) {
                   1978:                        if (stack.size() > 0) {
                   1979:                                if (stack.top()[0] == '*' || stack.top()[0] == '/') {
                   1980:                                        out.push_back(stack.top());
                   1981:                                        stack.pop();
                   1982:                                }
                   1983:                        }
                   1984:                        stack.push(token);
                   1985: 
                   1986:                } else if (strcmp(tok, "(") == 0) {
                   1987:                        stack.push(token);
                   1988: 
                   1989:                } else if (strcmp(tok, ")") == 0) {
                   1990:                        for (; stack.size() > 0 && stack.top()[0] != '('; ) {
                   1991:                                out.push_back(stack.top());
                   1992:                                stack.pop();
                   1993:                        }
                   1994:                        if (stack.size() == 0) {
                   1995:                                error("expression error\n");
                   1996:                        }
                   1997:                        stack.pop();
                   1998: 
                   1999:                } else {
                   2000:                        int num;
                   2001:                        if (parse_number(token, &num)) {
                   2002:                                /* 数値に変換できたら、数値(の文字列型)を格納 */
                   2003:                                out.push_back(num2hex(num));
                   2004:                        } else {
                   2005:                                /* 数値にできなければ(たぶん)ラベルのまま格納 */
                   2006:                                out.push_back(token);
                   2007:                        }
                   2008:                }
                   2009:        }
                   2010: 
                   2011:        for (; stack.size() > 0;) {
                   2012:                out.push_back(stack.top());
                   2013:                stack.pop();
                   2014:        }
                   2015: 
                   2016:        DPRINTF(D_PARSE, "parse_expr.3 expr");
                   2017:        for (int i = 0; i < out.size(); i++) {
                   2018:                DPRINTN(D_PARSE, "%c%s", (i==0)?'=':' ', out[i].c_str());
                   2019:        }
                   2020:        DPRINTN(D_PARSE, "\n");
                   2021: 
                   2022:        return true;
                   2023: }
                   2024: 
                   2025: /*
                   2026:  * 字句解析。expr をトークンごとに分解して tokens に入れて返す。
                   2027:  */
                   2028: bool
                   2029: scan_expr(String& expr, ArrayString& tokens)
                   2030: {
                   2031: #if defined(_MSC_VER)
                   2032:        char buf[BUFSIZE];
                   2033: #else
                   2034:        char buf[expr.size() + 1];
                   2035: #endif
                   2036:        char *s = NULL; /* shut up gcc */
                   2037:        char *p;
                   2038:        int c;
                   2039:        enum {
                   2040:                INIT,
                   2041:                LABEL,
                   2042:                DIGIT,
                   2043:                HEX,
                   2044:        } state;
                   2045: 
                   2046: #if defined(_MSC_VER)
                   2047:        strncpy(buf, expr.c_str(), sizeof(buf) - 1);
                   2048:        buf[sizeof(buf) - 1] = '\0';
                   2049: #else
                   2050:        strcpy(buf, expr.c_str());
                   2051: #endif
                   2052: 
                   2053:        state = INIT;
                   2054:        for (p = buf; *p; p++) {
                   2055:                c = (int)*p;
                   2056: 
                   2057:                switch (state) {
                   2058:                 case LABEL:    /* ラベルの2文字目以降 */
                   2059:                        if (isalpha(c) || isdigit(c) || c == '_') {
                   2060:                                continue;
                   2061:                        }
                   2062:                        break;
                   2063:                 case DIGIT:    /* 数字の2文字目以降 */
                   2064:                        if (isdigit(c)) {
                   2065:                                continue;
                   2066:                        }
                   2067:                        break;
                   2068:                 case HEX:              /* 16進の2文字目以降 */
                   2069:                        if (isxdigit(c)) {
                   2070:                                continue;
                   2071:                        }
                   2072:                        break;
                   2073: 
                   2074:                 case INIT:             /* 1文字目 */
                   2075:                 init:
                   2076:                        s = p;
                   2077:                        if (isspace(c)) {
                   2078:                                continue;
                   2079:                        } else if (isalpha(c) || c == '_') {
                   2080:                                state = LABEL;
                   2081:                        } else if (isdigit(c)) {
                   2082:                                state = DIGIT;
                   2083:                        } else if (c == '$') {
                   2084:                                state = HEX;
                   2085:                        } else if (strchr("+-*/()", c)) {
                   2086:                                /* 記号は1文字で確定する */
                   2087:                                String token(s, 1);
                   2088:                                tokens.push_back(token);
                   2089:                                /* INIT状態のまま次の文字へ */
                   2090:                                continue;
                   2091:                        } else {
                   2092:                                error("syntax error\n");
                   2093:                        }
                   2094:                        continue;
                   2095:                }
                   2096: 
                   2097:                /* 1文字前までが1語句だった */
                   2098:                String token(s, p - s);
                   2099:                tokens.push_back(token);
                   2100:                /* 今指してるのは次語句の先頭なので、この文字のまま INIT へ */
                   2101:                state = INIT;
                   2102:                goto init;
                   2103:        }
                   2104: 
                   2105:        /* 状態を残したまま最後の文字まで来たら最後の語句を切り出す */
                   2106:        if (state != INIT) {
                   2107:                String token(s);
                   2108:                tokens.push_back(token);
                   2109:        }
                   2110: 
                   2111:        return true;
                   2112: }
                   2113: 
                   2114: /* 計算途中の式をリストに追加 */
                   2115: void
                   2116: add_expr(int pos, reftype_t type, ArrayString& expr)
                   2117: {
                   2118:        REF *ref = new REF;
                   2119: 
                   2120:        ref->pos = pos;
                   2121:        ref->line = ::line;
                   2122:        ref->type = type;
                   2123:        ref->expr = expr;
                   2124:        DPRINTN_ref(D_EXPR, ref);
                   2125: 
                   2126:        ref_list.push_back(ref);
                   2127: }
                   2128: 
                   2129: /* デバッグ表示 */
                   2130: void
                   2131: DPRINTN_ref(int debugflag, REF *ref)
                   2132: {
                   2133:        DPRINTF(debugflag, "REF line=%d pos=%d($%06x) type=%d ",
                   2134:                ref->line, ref->pos, origin + ref->pos, (int)ref->type);
                   2135:        DPRINTN_expr(debugflag, ref->expr);
                   2136:        DPRINTN(debugflag, "\n");
                   2137: }
                   2138: 
                   2139: /* デバッグ表示 */
                   2140: void
                   2141: DPRINTN_expr(int debugflag, ArrayString& expr)
                   2142: {
                   2143:        DPRINTN(debugflag, "expr");
                   2144:        for (int i = 0; i < expr.size(); i++) {
                   2145:                DPRINTN(debugflag, "%c%s", (i == 0)?'=':' ', expr[i].c_str());
                   2146:        }
                   2147: }
                   2148: 
                   2149: /*
                   2150:  * 式を計算する。
                   2151:  * error_stop が真ならラベルが解決できないのをエラーにする。
                   2152:  * 1st stage では false、2nd stage では true にする。
                   2153:  * false でラベルが解決できなければ false を返すだけ。
                   2154:  */
                   2155: bool
                   2156: calc_expr(ArrayString& expr, uint32_t& retval, bool error_stop)
                   2157: {
                   2158:        uint32_t val;
                   2159:        uint32_t v1, v2;
                   2160:        int i;
                   2161: 
                   2162:        DPRINTF(D_EXPR, "calc_expr.0 ");
                   2163:        DPRINTN_expr(D_EXPR, expr);
                   2164:        DPRINTN(D_EXPR, "\n");
                   2165: 
                   2166:        /* まずラベルが解決できるか */
                   2167:        for (i = 0; i < expr.size(); i++) {
                   2168:                String token = expr[i];
                   2169:                if (isalpha((int)token[0])) {
                   2170:                        int intval;
                   2171:                        if (parse_number(token, &intval)) {
                   2172:                                /* 見付かったので数値に差し替える */
                   2173:                                expr[i] = num2hex(intval);
                   2174:                                DPRINTF(D_EXPR, "calc_expr.1 '%s' is %s\n",
                   2175:                                        token.c_str(), expr[i].c_str());
                   2176:                        } else {
                   2177:                                /* 見付からなかった */
                   2178:                                if (error_stop) {
                   2179:                                        error("undefined label: %s\n", token.c_str());
                   2180:                                } else {
                   2181:                                        DPRINTF(D_EXPR, "calc_expr.1 '%s' not resolved, quit\n",
                   2182:                                                token.c_str());
                   2183:                                        return false;
                   2184:                                }
                   2185:                        }
                   2186:                }
                   2187:        }
                   2188:        DPRINTF(D_EXPR, "calc_expr.2 ");
                   2189:        DPRINTN_expr(D_EXPR, expr);
                   2190:        DPRINTN(D_EXPR, "\n");
                   2191: 
                   2192:        /* ラベルが全部解決できたので計算する */
                   2193:        std::stack<uint32_t> stack;
                   2194:        for (i = 0; i < expr.size(); i++) {
                   2195:                String token = expr[i];
                   2196:                if (token[0] == '$') {
                   2197:                        /* 取り出したのが数値ならスタックに積む */
                   2198:                        val = (uint32_t)tonumber(token);
                   2199:                        stack.push(val);
                   2200: 
                   2201:                } else {
                   2202:                        /* 取り出したのが演算子ならスタックから2つ取って.. */
                   2203:                        v2 = stack.top();
                   2204:                        stack.pop();
                   2205:                        v1 = stack.top();
                   2206:                        stack.pop();
                   2207: 
                   2208:                        /* 計算 */
                   2209:                        if (token[0] == '+') {
                   2210:                                val = v1 + v2;
                   2211:                        } else if (token[0] == '-') {
                   2212:                                val = v1 - v2;
                   2213:                        } else if (token[0] == '*') {
                   2214:                                val = v1 * v2;
                   2215:                        } else if (token[0] == '/') {
                   2216:                                val = v1 / v2;
                   2217:                        } else {
                   2218:                                error("unknown operator: %s\n", token.c_str());
                   2219:                        }
                   2220: 
                   2221:                        /* それを再び積む */
                   2222:                        stack.push(val);
                   2223:                }
                   2224:        }
                   2225: 
                   2226:        retval = stack.top();
                   2227: DPRINTF(D_EXPR, "calc_expr.3 ret=$%x\n", retval);
                   2228:        return true;
                   2229: }
                   2230: 
                   2231: /* 文字列を解析 */
                   2232: String
                   2233: parse_string(String& src)
                   2234: {
                   2235:        String dst;
                   2236:        enum {
                   2237:                OUTER = 0,
                   2238:                PLAIN,
                   2239:                ESC,
                   2240:        } state;
                   2241: 
                   2242:        state = OUTER;
                   2243:        for (int i = 0; i < src.size(); i++) {
                   2244:                int c = (int)(src[i]);
                   2245:                switch (state) {
                   2246:                 case OUTER:
                   2247:                        if (isspace(c)) {
                   2248:                                ;
                   2249:                        } else if (c == '\x22') {
                   2250:                                state = PLAIN;
                   2251:                        } else {
                   2252:                                error("syntax error around string: %s", src.c_str());
                   2253:                        }
                   2254:                        break;
                   2255: 
                   2256:                 case PLAIN:
                   2257:                        if (c == '\x22') {
                   2258:                                state = OUTER;
                   2259:                        } else if (c == '\\') {
                   2260:                                state = ESC;
                   2261:                        } else {
                   2262:                                dst.push_back(c);
                   2263:                        }
                   2264:                        break;
                   2265: 
                   2266:                 case ESC:
                   2267:                        if (c == 'n') {
                   2268:                                dst.push_back('\n');
                   2269:                        } else if (c == 't') {
                   2270:                                dst.push_back('\t');
                   2271:                        } else {
                   2272:                                dst.push_back(c);
                   2273:                        }
                   2274:                        /* XXX \xHH 追加のこと */
                   2275:                        state = PLAIN;
                   2276:                        break;
                   2277:                }
                   2278:        }
                   2279:        if (state != OUTER) {
                   2280:                error("syntax error in string: %s\n", src.c_str());
                   2281:        }
                   2282: 
                   2283:        return dst;
                   2284: }
                   2285: 
                   2286: /* 文字コードを UTF-8 から Shift_JIS に変換 */
                   2287: String
                   2288: convert_charset(String& src)
                   2289: {
                   2290:        /*
                   2291:         * iconv(3) を使う
                   2292:         */
                   2293:        iconv_t cd;
                   2294:        char dstbuf[src.size() * 2];    /* 適当 */
                   2295:        const char *srcptr;
                   2296:        char *dstptr;
                   2297:        size_t srcsize;
                   2298:        size_t dstsize;
                   2299:        size_t r;
                   2300: 
                   2301:        cd = iconv_open("Shift_JIS", "UTF-8");
                   2302:        if (cd == NULL) {
                   2303:                return src;
                   2304:        }
                   2305: 
                   2306:        srcptr = src.c_str();
                   2307:        srcsize = src.size();
                   2308:        memset(dstbuf, 0, sizeof(dstbuf));
                   2309:        dstptr = dstbuf;
                   2310:        dstsize = sizeof(dstbuf);
1.1.1.3 ! root     2311:        r = ICONV(cd, &srcptr, &srcsize, &dstptr, &dstsize);
1.1       root     2312:        if (r == -1) {
                   2313:                error("cannot conversion string: %s\n", srcptr);
                   2314:        }
                   2315:        if (r > 0) {
                   2316:                error("invalid charactor found: %s\n", srcptr);
                   2317:        }
                   2318: 
                   2319:        iconv_close(cd);
                   2320: 
                   2321:        String dst(dstbuf);
                   2322:        return dst;
                   2323: }
                   2324: 
                   2325: /* デバッグ表示 (ap版) */
                   2326: void
                   2327: DPRINTV(int flag, const char *fmt, va_list ap)
                   2328: {
                   2329:        if ((debug & flag)) {
                   2330:                vprintf(fmt, ap);
                   2331:        }
                   2332: }
                   2333: 
                   2334: /* デバッグ表示 (行頭のマークなし) */
                   2335: void
                   2336: DPRINTN(int flag, const char *fmt, ...)
                   2337: {
                   2338:        va_list ap;
                   2339: 
                   2340:        va_start(ap, fmt);
                   2341:        DPRINTV(flag, fmt, ap);
                   2342:        va_end(ap);
                   2343: }
1.1.1.2   root     2344: 
1.1       root     2345: /* デバッグ表示 (行頭のマーク付き) */
                   2346: void
                   2347: DPRINTF(int flag, const char *fmt, ...)
                   2348: {
                   2349:        va_list ap;
                   2350:        int ch;
                   2351: 
                   2352:        switch (flag) {
                   2353:         case D_INOUT:
                   2354:                ch = '|';
                   2355:                break;
                   2356:         case D_EA:
                   2357:                ch = 'A';
                   2358:                break;
                   2359:         case D_LABEL:
                   2360:                ch = 'L';
                   2361:                break;
                   2362:         case D_PARSE:
                   2363:                ch = 'P';
                   2364:                break;
                   2365:         case D_STAGE:
                   2366:                ch = ' ';
                   2367:                break;
                   2368:         case D_EXPR:
                   2369:                ch = 'E';
                   2370:                break;
                   2371:         case D_SCAN:
                   2372:                ch = 'S';
                   2373:                break;
                   2374:         default:
                   2375:                ch = '?';
                   2376:                break;
                   2377:        }
                   2378:        DPRINTN(flag, "%c ", ch);
                   2379: 
                   2380:        va_start(ap, fmt);
                   2381:        DPRINTV(flag, fmt, ap);
                   2382:        va_end(ap);
                   2383: }
                   2384: 
                   2385: /* アセンブルエラー */
                   2386: void
                   2387: error(const char *fmt, ...)
                   2388: {
                   2389:        char buf[1024];
                   2390:        va_list ap;
                   2391: 
                   2392:        va_start(ap, fmt);
                   2393:        vsnprintf(buf, sizeof(buf), fmt, ap);
                   2394:        va_end(ap);
                   2395: 
                   2396:        /* デバッグモードなら stdout にも出力しないと分かりづらい */
                   2397:        DPRINTN(D_STAGE, "%s:%d:%s", current_infile, line, buf);
                   2398:        fprintf(stderr, "%s:%d:%s", current_infile, line, buf);
                   2399: 
                   2400:        /* 出力しかけのファイルは消しておく (次のビルドのため) */
                   2401:        if (outfile) {
                   2402:                fclose(outfp);
                   2403:                unlink(outfile);
                   2404:                fprintf(stderr, "output file '%s' removed\n", outfile);
                   2405:        }
                   2406: 
                   2407:        exit(1);
                   2408: }
                   2409: 
                   2410: /* String の前後の空白を取り除く */
                   2411: void
                   2412: trim(String& str)
                   2413: {
                   2414:        ltrim(str);
                   2415:        rtrim(str);
                   2416: }
                   2417: 
                   2418: /* String の先頭の空白を取り除く */
                   2419: void
                   2420: ltrim(String& str)
                   2421: {
                   2422:        while (isspace((int)str[0])) {
                   2423:                str.erase(0, 1);
                   2424:        }
                   2425: }
                   2426: 
                   2427: /* String の末尾の空白を取り除く */
                   2428: void
                   2429: rtrim(String& str)
                   2430: {
                   2431:        for (int r = str.length() - 1; r >= 0; r--) {
                   2432:                if (isspace((int)str[r])) {
                   2433:                        str.erase(r);
                   2434:                } else {
                   2435:                        break;
                   2436:                }
                   2437:        }
                   2438: }

unix.superglobalmegacorp.com

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