0
|
1 /*
|
|
2 * insn_gen.c
|
|
3 *
|
|
4 * parsing general addressing modes (IMM+DIR+EXT+IND)
|
|
5 */
|
|
6
|
|
7 #include <ctype.h>
|
|
8 #include "lwasm.h"
|
|
9 #include "instab.h"
|
|
10
|
|
11 extern void insn_indexed_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3);
|
|
12
|
|
13 void insn_gen_aux(asmstate_t *as, sourceline_t *cl, char **optr, int *b1, int *b2, int *b3, int *op)
|
|
14 {
|
|
15 *b1 = *b2 = *b3 = -1;
|
|
16 char *optr2;
|
|
17 int v1, tv, rval;
|
|
18
|
|
19 optr2 = *optr;
|
|
20 while (*optr2 && !isspace(*optr2) && *optr2 != ',') optr2++
|
|
21 ;
|
|
22 if (*optr2 != ',' && **optr != '[')
|
|
23 {
|
|
24 // not indexed
|
|
25 if (**optr == '<')
|
|
26 {
|
|
27 (*optr)++;
|
|
28 rval = eval_expr(as, cl, optr, &v1);
|
|
29 v1 = v1 & 0xffff;
|
|
30 tv = v1 - ((cl -> dpval) << 8);
|
|
31 if (tv < 0 || tv > 0xff)
|
|
32 {
|
|
33 errorp2(ERR_OVERFLOW);
|
|
34 }
|
|
35 v1 = v1 & 0xff;
|
|
36 goto ins_gen_dir;
|
|
37 }
|
|
38 else if (**optr == '>')
|
|
39 {
|
|
40 // extended mode
|
|
41 (*optr)++;
|
|
42 rval = eval_expr(as, cl, optr, &v1);
|
|
43 goto ins_gen_ext;
|
|
44 }
|
|
45 else
|
|
46 {
|
|
47 // eval expr and see how big it is
|
|
48 rval = eval_expr(as, cl, optr, &v1);
|
|
49 v1 = v1 & 0xFFFF;
|
|
50
|
|
51 if (cl -> undef && as -> passnum == 1)
|
|
52 {
|
|
53 cl -> p1f16 = 1;
|
|
54 goto ins_gen_ext;
|
|
55 }
|
|
56
|
|
57 tv = v1 - (cl -> dpval << 8);
|
|
58
|
|
59 if (tv < 0 || tv > 0xff || cl -> p1f16)
|
|
60 goto ins_gen_ext;
|
|
61 else
|
|
62 {
|
|
63 v1 = v1 & 0xff;
|
|
64 goto ins_gen_dir;
|
|
65 }
|
|
66 }
|
|
67 return;
|
|
68 }
|
|
69
|
|
70 *op = instab[cl -> opcode].ops[1];
|
|
71 insn_indexed_aux(as, cl, optr, b1, b2, b3);
|
|
72 return;
|
|
73
|
|
74 ins_gen_dir:
|
|
75 *op = instab[cl -> opcode].ops[0];
|
|
76 // cl -> code_operlen = 1;
|
|
77 cl -> addrmode = OPER_DIR;
|
|
78 if ((v1 & 0xFFFF) > 0xff)
|
|
79 errorp2(ERR_OVERFLOW);
|
|
80 *b1 = (v1);
|
|
81 return;
|
|
82
|
|
83 ins_gen_ext:
|
|
84 *op = instab[cl -> opcode].ops[2];
|
|
85 // cl -> code_operlen = 2;
|
|
86 cl -> addrmode = OPER_EXT;
|
|
87 *b1 = (v1 >> 8);
|
|
88 *b2 = (v1 & 0xff);
|
|
89 return;
|
|
90 }
|
|
91
|
|
92 void insn_gen(asmstate_t *as, sourceline_t *cl, char **optr)
|
|
93 {
|
|
94 int rval;
|
|
95 int v1;
|
|
96 int b1, b2, b3, op;
|
|
97
|
|
98 if (**optr == '#')
|
|
99 {
|
|
100 // immediate mode has perterbations on instruction size
|
|
101 (*optr)++;
|
|
102 emitop(instab[cl -> opcode].ops[3]);
|
|
103 rval = eval_expr(as, cl, optr, &v1);
|
|
104
|
|
105 switch (instab[cl -> opcode].instype)
|
|
106 {
|
|
107 case INSTYPE_GEN8:
|
|
108 case INSTYPE_IMM8:
|
|
109 cl -> addrmode = OPER_IMM8;
|
|
110 // cl -> code_operlen = 1;
|
|
111 emit(v1 & 0xff);
|
|
112 if (v1 < -128 || v1 > 255)
|
|
113 errorp2(ERR_OVERFLOW);
|
|
114 return;
|
|
115
|
|
116 case INSTYPE_GEN:
|
|
117 cl -> addrmode = OPER_IMM16;
|
|
118 // cl -> code_operlen = 2;
|
|
119 emit(v1 >> 8);
|
|
120 emit(v1 & 0xff);
|
|
121 return;
|
|
122
|
|
123 case INSTYPE_GEN32:
|
|
124 cl -> addrmode = OPER_IMM32;
|
|
125 // cl -> code_operlen = 4;
|
|
126 emit(v1 >> 24);
|
|
127 emit((v1 >> 16) & 0xff);
|
|
128 emit((v1 >> 8) & 0xff);
|
|
129 emit(v1 & 0xff);
|
|
130 return;
|
|
131
|
|
132 default:
|
|
133 errorp1(ERR_BADOPER);
|
|
134 return;
|
|
135
|
|
136 }
|
|
137
|
|
138 return;
|
|
139 }
|
|
140 if (instab[cl -> opcode].instype == INSTYPE_IMM8)
|
|
141 {
|
|
142 errorp1(ERR_BADOPER);
|
|
143 return;
|
|
144 }
|
|
145
|
|
146 insn_gen_aux(as, cl, optr, &b1, &b2, &b3, &op);
|
|
147 emitop(op);
|
|
148 if (b1 != -1)
|
|
149 emit(b1);
|
|
150 if (b2 != -1)
|
|
151 emit(b2);
|
|
152 if (b3 != -1)
|
|
153 emit(b3);
|
|
154 }
|