1 /* code16c5x.c */
2 /*****************************************************************************/
3 /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
4 /* */
5 /* AS-Portierung */
6 /* */
7 /* AS - Codegenerator fuer PIC16C5x */
8 /* */
9 /*****************************************************************************/
10
11 #include "stdinc.h"
12
13 #include <string.h>
14
15 #include "strutil.h"
16 #include "chunks.h"
17 #include "asmdef.h"
18 #include "asmsub.h"
19 #include "asmpars.h"
20 #include "asmitree.h"
21 #include "codepseudo.h"
22 #include "fourpseudo.h"
23 #include "codevars.h"
24 #include "errmsg.h"
25
26 #include "code16c5x.h"
27
28 static CPUVar CPU16C54, CPU16C55, CPU16C56, CPU16C57;
29
30 /*-------------------------------------------------------------------------*/
31
DecodeFixed(Word Code)32 static void DecodeFixed(Word Code)
33 {
34 if (ChkArgCnt(0, 0))
35 {
36 CodeLen = 1;
37 WAsmCode[0] = Code;
38 }
39 }
40
DecodeLit(Word Code)41 static void DecodeLit(Word Code)
42 {
43 if (ChkArgCnt(1, 1))
44 {
45 Boolean OK;
46 Word AdrWord = EvalStrIntExpression(&ArgStr[1], Int8, &OK);
47 if (OK)
48 {
49 CodeLen = 1;
50 WAsmCode[0] = Code + (AdrWord & 0xff);
51 }
52 }
53 }
54
DecodeAri(Word Code)55 static void DecodeAri(Word Code)
56 {
57 Word DefaultDir = (Code >> 15) & 1, AdrWord;
58
59 Code &= 0x7fff;
60 if (ChkArgCnt(1, 2))
61 {
62 tEvalResult EvalResult;
63
64 AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt5, &EvalResult);
65 if (EvalResult.OK)
66 {
67 ChkSpace(SegData, EvalResult.AddrSpaceMask);
68 WAsmCode[0] = Code + (AdrWord & 0x1f);
69 if (ArgCnt == 1)
70 {
71 CodeLen = 1;
72 WAsmCode[0] += DefaultDir << 5;
73 }
74 else if (!as_strcasecmp(ArgStr[2].Str, "W"))
75 CodeLen = 1;
76 else if (!as_strcasecmp(ArgStr[2].Str, "F"))
77 {
78 CodeLen = 1;
79 WAsmCode[0] += 0x20;
80 }
81 else
82 {
83 AdrWord = EvalStrIntExpressionWithResult(&ArgStr[2], UInt1, &EvalResult);
84 if (EvalResult.OK)
85 {
86 CodeLen = 1;
87 WAsmCode[0] += AdrWord << 5;
88 }
89 }
90 }
91 }
92 }
93
DecodeBit(Word Code)94 static void DecodeBit(Word Code)
95 {
96 if (ChkArgCnt(2, 2))
97 {
98 tEvalResult EvalResult;
99 Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[2], UInt3, &EvalResult);
100
101 if (EvalResult.OK)
102 {
103 WAsmCode[0] = EvalStrIntExpressionWithResult(&ArgStr[1], UInt5, &EvalResult);
104 if (EvalResult.OK)
105 {
106 CodeLen = 1;
107 WAsmCode[0] += Code + (AdrWord << 5);
108 ChkSpace(SegData, EvalResult.AddrSpaceMask);
109 }
110 }
111 }
112 }
113
DecodeF(Word Code)114 static void DecodeF(Word Code)
115 {
116 if (ChkArgCnt(1, 1))
117 {
118 tEvalResult EvalResult;
119 Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt5, &EvalResult);
120
121 if (EvalResult.OK)
122 {
123 CodeLen = 1;
124 WAsmCode[0] = Code + AdrWord;
125 ChkSpace(SegData, EvalResult.AddrSpaceMask);
126 }
127 }
128 }
129
DecodeTRIS(Word Code)130 static void DecodeTRIS(Word Code)
131 {
132 UNUSED(Code);
133
134 if (ChkArgCnt(1, 1))
135 {
136 tEvalResult EvalResult;
137 Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt3, &EvalResult);
138
139 if (EvalResult.OK)
140 if (ChkRange(AdrWord, 5, 7))
141 {
142 CodeLen = 1;
143 WAsmCode[0] = 0x000 + AdrWord;
144 ChkSpace(SegData, EvalResult.AddrSpaceMask);
145 }
146 }
147 }
148
DecodeCALL_GOTO(Word Code)149 static void DecodeCALL_GOTO(Word Code)
150 {
151 if (ChkArgCnt(1, 1))
152 {
153 tEvalResult EvalResult;
154 Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[1], UInt16, &EvalResult);
155
156 if (EvalResult.OK)
157 {
158 if (AdrWord > SegLimits[SegCode]) WrError(ErrNum_OverRange);
159 else if ((Code & 0x100) && ((AdrWord & 0x100) != 0)) WrError(ErrNum_NotFromThisAddress);
160 else
161 {
162 ChkSpace(SegCode, EvalResult.AddrSpaceMask);
163 if (((ProgCounter() ^ AdrWord) & 0x200) != 0)
164 WAsmCode[CodeLen++] = 0x4a3 + ((AdrWord & 0x200) >> 1); /* BCF/BSF 3,5 */
165 if (((ProgCounter() ^ AdrWord) & 0x400) != 0)
166 WAsmCode[CodeLen++] = 0x4c3 + ((AdrWord & 0x400) >> 2); /* BCF/BSF 3,6 */
167 WAsmCode[CodeLen++] = Code + (AdrWord & (Code & 0x100 ? 0xff : 0x1ff));
168 }
169 }
170 }
171 }
172
DecodeSFR(Word Code)173 static void DecodeSFR(Word Code)
174 {
175 UNUSED(Code);
176
177 CodeEquate(SegData, 0, 0x1f);
178 }
179
DecodeDATA_16C5x(Word Code)180 static void DecodeDATA_16C5x(Word Code)
181 {
182 UNUSED(Code);
183
184 DecodeDATA(Int12, Int8);
185 }
186
DecodeZERO(Word Code)187 static void DecodeZERO(Word Code)
188 {
189 Word Size;
190 Boolean ValOK;
191 tSymbolFlags Flags;
192
193 UNUSED(Code);
194
195 if (ChkArgCnt(1, 1))
196 {
197 Size = EvalStrIntExpressionWithFlags(&ArgStr[1], Int16, &ValOK, &Flags);
198 if (mFirstPassUnknown(Flags)) WrError(ErrNum_FirstPassCalc);
199 if (ValOK && !mFirstPassUnknown(Flags))
200 {
201 if (SetMaxCodeLen(Size << 1)) WrError(ErrNum_CodeOverflow);
202 else
203 {
204 CodeLen = Size;
205 memset(WAsmCode, 0, 2 * Size);
206 }
207 }
208 }
209 }
210
211 /*-------------------------------------------------------------------------*/
212
AddFixed(const char * NName,Word NCode)213 static void AddFixed(const char *NName, Word NCode)
214 {
215 AddInstTable(InstTable, NName, NCode, DecodeFixed);
216 }
217
AddLit(const char * NName,Word NCode)218 static void AddLit(const char *NName, Word NCode)
219 {
220 AddInstTable(InstTable, NName, NCode, DecodeLit);
221 }
222
AddAri(const char * NName,Word NCode,Word NDef)223 static void AddAri(const char *NName, Word NCode, Word NDef)
224 {
225 AddInstTable(InstTable, NName, NCode | (NDef << 15), DecodeAri);
226 }
227
AddBit(const char * NName,Word NCode)228 static void AddBit(const char *NName, Word NCode)
229 {
230 AddInstTable(InstTable, NName, NCode, DecodeBit);
231 }
232
AddF(const char * NName,Word NCode)233 static void AddF(const char *NName, Word NCode)
234 {
235 AddInstTable(InstTable, NName, NCode, DecodeF);
236 }
237
InitFields(void)238 static void InitFields(void)
239 {
240 InstTable = CreateInstTable(103);
241 AddInstTable(InstTable, "TRIS", 0, DecodeTRIS);
242 AddInstTable(InstTable, "CALL", 0x0900, DecodeCALL_GOTO);
243 AddInstTable(InstTable, "GOTO", 0x0a00, DecodeCALL_GOTO);
244 AddInstTable(InstTable, "SFR", 0, DecodeSFR);
245 AddInstTable(InstTable, "RES", 0, DecodeRES);
246 AddInstTable(InstTable, "DATA", 0, DecodeDATA_16C5x);
247 AddInstTable(InstTable, "ZERO", 0, DecodeZERO);
248
249 AddFixed("CLRW" , 0x040);
250 AddFixed("NOP" , 0x000);
251 AddFixed("CLRWDT", 0x004);
252 AddFixed("OPTION", 0x002);
253 AddFixed("SLEEP" , 0x003);
254
255 AddLit("ANDLW", 0xe00);
256 AddLit("IORLW", 0xd00);
257 AddLit("MOVLW", 0xc00);
258 AddLit("RETLW", 0x800);
259 AddLit("XORLW", 0xf00);
260
261 AddAri("ADDWF" , 0x1c0, 0);
262 AddAri("ANDWF" , 0x140, 0);
263 AddAri("COMF" , 0x240, 1);
264 AddAri("DECF" , 0x0c0, 1);
265 AddAri("DECFSZ", 0x2c0, 1);
266 AddAri("INCF" , 0x280, 1);
267 AddAri("INCFSZ", 0x3c0, 1);
268 AddAri("IORWF" , 0x100, 0);
269 AddAri("MOVF" , 0x200, 0);
270 AddAri("RLF" , 0x340, 1);
271 AddAri("RRF" , 0x300, 1);
272 AddAri("SUBWF" , 0x080, 0);
273 AddAri("SWAPF" , 0x380, 1);
274 AddAri("XORWF" , 0x180, 0);
275
276 AddBit("BCF" , 0x400);
277 AddBit("BSF" , 0x500);
278 AddBit("BTFSC", 0x600);
279 AddBit("BTFSS", 0x700);
280
281 AddF("CLRF" , 0x060);
282 AddF("MOVWF", 0x020);
283 }
284
DeinitFields(void)285 static void DeinitFields(void)
286 {
287 DestroyInstTable(InstTable);
288 }
289
290 /*-------------------------------------------------------------------------*/
291
MakeCode_16C5X(void)292 static void MakeCode_16C5X(void)
293 {
294 CodeLen = 0;
295 DontPrint = False;
296
297 /* zu ignorierendes */
298
299 if (Memo(""))
300 return;
301
302 if (!LookupInstTable(InstTable, OpPart.Str))
303 WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
304 }
305
IsDef_16C5X(void)306 static Boolean IsDef_16C5X(void)
307 {
308 return Memo("SFR");
309 }
310
SwitchFrom_16C5X(void)311 static void SwitchFrom_16C5X(void)
312 {
313 DeinitFields();
314 }
315
SwitchTo_16C5X(void)316 static void SwitchTo_16C5X(void)
317 {
318 TurnWords = False;
319 ConstMode = ConstModeMoto;
320
321 PCSymbol = "*";
322 HeaderID = 0x71;
323 NOPCode = 0x000;
324 DivideChars = ",";
325 HasAttrs = False;
326
327 ValidSegs = (1 << SegCode) + (1 << SegData);
328 Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
329 if (MomCPU == CPU16C56)
330 SegLimits[SegCode] = 1023;
331 else if (MomCPU == CPU16C57)
332 SegLimits[SegCode] = 2047;
333 else
334 SegLimits[SegCode] = 511;
335 Grans[SegData] = 1; ListGrans[SegData] = 1; SegInits[SegCode] = 0;
336 SegLimits[SegData] = 0x1f;
337
338 MakeCode = MakeCode_16C5X;
339 IsDef = IsDef_16C5X;
340 SwitchFrom = SwitchFrom_16C5X;
341 InitFields();
342 }
343
code16c5x_init(void)344 void code16c5x_init(void)
345 {
346 CPU16C54 = AddCPU("16C54", SwitchTo_16C5X);
347 CPU16C55 = AddCPU("16C55", SwitchTo_16C5X);
348 CPU16C56 = AddCPU("16C56", SwitchTo_16C5X);
349 CPU16C57 = AddCPU("16C57", SwitchTo_16C5X);
350 }
351