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