|
|
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;
1.1.1.2 ! root 1736: } else {
1.1 root 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: }
1.1.1.2 ! root 2416:
1.1 root 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.