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