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