1 /* PIC Processor selection
2    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3    James Bowman, Craig Franklin
4 
5     Copyright (C) 2014-2016 Molnar Karoly
6 
7 This file is part of gputils.
8 
9 gputils is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13 
14 gputils is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with gputils; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23 
24 #include "stdhdr.h"
25 
26 #include "libgputils.h"
27 #include "gpasm.h"
28 #include "directive.h"
29 #include "gpmsg.h"
30 
31 /*------------------------------------------------------------------------------------------------*/
32 
33 static void
_make_bank_constants_and_variables(pic_processor_t Proc,int Num_of_banks)34 _make_bank_constants_and_variables(pic_processor_t Proc, int Num_of_banks)
35 {
36   int  bank_size;
37   int  bank_addr;
38   int  i;
39   char name[64];
40 
41   i = (Num_of_banks == 1) ? 0 : __BANK_INV;
42 
43   set_global(__ACTIVE_BANK_ADDR, i, VAL_VARIABLE, true, false);
44   set_global(__ASSUMED_BANK_ADDR, i, VAL_VARIABLE, true, false);
45 
46   if (Num_of_banks <= 0) {
47     return;
48   }
49 
50   set_global("__NUM_BANKS", Num_of_banks, VAL_CONSTANT, true, false);
51 
52   bank_size = Proc->class->bank_size;
53   bank_addr = 0;
54   i         = 0;
55   while (true) {
56     if (i == 0) {
57       set_global("__BANK_FIRST", bank_addr, VAL_CONSTANT, true, false);
58     }
59 
60     snprintf(name, sizeof(name), "__BANK_%i", i);
61     set_global(name, bank_addr, VAL_CONSTANT, true, false);
62     ++i;
63 
64     if (i == Num_of_banks) {
65       set_global("__BANK_LAST", bank_addr, VAL_CONSTANT, true, false);
66       break;
67     }
68 
69     bank_addr += bank_size;
70   }
71 }
72 
73 /*------------------------------------------------------------------------------------------------*/
74 
75 static void
_make_page_constants_and_variables(pic_processor_t Proc,int Num_of_pages)76 _make_page_constants_and_variables(pic_processor_t Proc, int Num_of_pages)
77 {
78   int  page_size;
79   int  page_addr;
80   int  i;
81   char name[64];
82 
83   i = (Num_of_pages == 1) ? 0 : __PAGE_INV;
84 
85   set_global(__ACTIVE_PAGE_ADDR, i, VAL_VARIABLE, true, false);
86 
87   if (Num_of_pages <= 0) {
88     return;
89   }
90 
91   set_global("__NUM_PAGES", Num_of_pages, VAL_CONSTANT, true, false);
92 
93   page_size = Proc->class->page_size;
94   page_addr = 0;
95   i         = 0;
96   while (true) {
97     if (i == 0) {
98       set_global("__PAGE_FIRST", page_addr, VAL_CONSTANT, true, false);
99     }
100 
101     snprintf(name, sizeof(name), "__PAGE_%i", i);
102     set_global(name, page_addr, VAL_CONSTANT, true, false);
103     ++i;
104 
105     if (i == Num_of_pages) {
106       set_global("__PAGE_LAST", page_addr, VAL_CONSTANT, true, false);
107       break;
108     }
109 
110     page_addr += page_size;
111   }
112 }
113 
114 /*------------------------------------------------------------------------------------------------*/
115 
116 void
select_processor(const char * Name)117 select_processor(const char *Name)
118 {
119   pic_processor_t  found;
120   proc_class_t     class;
121   const int       *pair;
122   const vector_t  *vec;
123   unsigned int     num;
124   int              addr;
125   int              num_of_banks;
126   int              num_of_pages;
127   char             buf[BUFSIZ];
128   int              badrom_idx;
129   long             start;
130   long             end;
131 
132   if (state.cmd_line.processor) {
133     gpmsg_vwarning(GPW_CMDLINE_PROC, NULL);
134   }
135   else {
136     found = gp_find_processor(Name);
137 
138     if (found != NULL) {
139       if (state.processor == NULL) {
140         /* If in extended mode: Check if processor supports extended instruction set. */
141         if (state.extended_pic16e && !(found->pic16e_flags & PIC16E_FLAG_HAVE_EXTINST)) {
142           gpmsg_verror(GPE_NO_EXTENDED_MODE, NULL);
143         }
144 
145         state.processor = found;
146         state.maxram    = found->maxram;
147         state.maxrom    = found->maxrom;
148 
149         if (state.maxrom > 0) {
150           /* Initialize badrom from internal processor info. */
151           gp_bitarray_create(&state.badrom, state.maxrom);
152 
153           for (badrom_idx = 0; badrom_idx < MAX_BADROM; badrom_idx += 2) {
154             start = found->badrom[badrom_idx];
155             end   = found->badrom[badrom_idx + 1];
156 
157             if ((start >= 0) && (end >= start)) {
158               gp_bitarray_write_range(&state.badrom, start, end, true);
159             }
160           }
161         }
162 
163         set_global(found->defined_as, 1, VAL_CONSTANT, false, false);
164 
165         if (!state.mpasm_compatible) {
166           class = found->class;
167 
168           num_of_banks = gp_processor_num_banks(found);
169           num_of_pages = gp_processor_num_pages(found);
170 
171           if ((class == PROC_CLASS_GENERIC) || (class == PROC_CLASS_PIC12) ||
172               (class == PROC_CLASS_PIC12E)  || (class == PROC_CLASS_PIC12I)) {
173             if ((class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I)) {
174               set_global("__ENHANCED", 1,                 VAL_CONSTANT, true, false);
175             }
176 
177             set_global("__12_BIT",     1,                 VAL_CONSTANT, true, false);
178             set_global("__PAGE_BITS",  PIC12_PAGE_BITS,   VAL_CONSTANT, true, false);
179             set_global("__PAGE_MASK",  class->page_mask,  VAL_CONSTANT, true, false);
180             set_global("__PAGE_SHIFT", PIC12_PAGE_SHIFT,  VAL_CONSTANT, true, false);
181             set_global("__PAGE_SIZE",  class->page_size,  VAL_CONSTANT, true, false);
182             set_global("__PAGE_INV",   __PAGE_INV,        VAL_CONSTANT, true, false);
183 
184             _make_bank_constants_and_variables(found, num_of_banks);
185             _make_page_constants_and_variables(found, num_of_pages);
186           }
187           else if (class == PROC_CLASS_SX) {
188             set_global("__12_BIT",     1,                 VAL_CONSTANT, true, false);
189             set_global("__PAGE_BITS",  SX_PAGE_BITS,      VAL_CONSTANT, true, false);
190             set_global("__PAGE_MASK",  class->page_mask,  VAL_CONSTANT, true, false);
191             set_global("__PAGE_SHIFT", PIC12_PAGE_SHIFT,  VAL_CONSTANT, true, false);
192             set_global("__PAGE_SIZE",  class->page_size,  VAL_CONSTANT, true, false);
193             set_global("__PAGE_INV",   __PAGE_INV,        VAL_CONSTANT, true, false);
194 
195             _make_bank_constants_and_variables(found, num_of_banks);
196             _make_page_constants_and_variables(found, num_of_pages);
197           }
198           else if (class == PROC_CLASS_PIC14) {
199             set_global("__14_BIT",     1,                 VAL_CONSTANT, true, false);
200             set_global("__PAGE_BITS",  PIC14_PAGE_BITS,   VAL_CONSTANT, true, false);
201             set_global("__PAGE_MASK",  class->page_mask,  VAL_CONSTANT, true, false);
202             set_global("__PAGE_SHIFT", PIC14_PAGE_SHIFT,  VAL_CONSTANT, true, false);
203             set_global("__PAGE_SIZE",  class->page_size,  VAL_CONSTANT, true, false);
204             set_global("__PAGE_INV",   __PAGE_INV,        VAL_CONSTANT, true, false);
205 
206             _make_bank_constants_and_variables(found, num_of_banks);
207             _make_page_constants_and_variables(found, num_of_pages);
208           }
209           else if ((class == PROC_CLASS_PIC14E) || (class == PROC_CLASS_PIC14EX)) {
210             set_global("__14_BIT",        1,                    VAL_CONSTANT, true, false);
211             set_global("__ENHANCED",      1,                    VAL_CONSTANT, true, false);
212             set_global("__PAGE_BITS",     PIC14E_PAGE_BITS,     VAL_CONSTANT, true, false);
213             set_global("__PAGE_MASK",     class->page_mask,     VAL_CONSTANT, true, false);
214             set_global("__PAGE_SHIFT",    PIC14_PAGE_SHIFT,     VAL_CONSTANT, true, false);
215             set_global("__PAGE_SIZE",     class->page_size,     VAL_CONSTANT, true, false);
216             set_global("__PAGE512_SHIFT", PIC14E_PAGE512_SHIFT, VAL_CONSTANT, true, false);
217             set_global("__PAGE_INV",      __PAGE_INV,           VAL_CONSTANT, true, false);
218 
219             _make_bank_constants_and_variables(found, num_of_banks);
220             _make_page_constants_and_variables(found, num_of_pages);
221           }
222           else if (class == PROC_CLASS_PIC16) {
223             set_global("__16_BIT",     1,                 VAL_CONSTANT, true, false);
224             set_global("__PAGE_BITS",  PIC16_PAGE_BITS,   VAL_CONSTANT, true, false);
225             set_global("__PAGE_MASK",  class->page_mask,  VAL_CONSTANT, true, false);
226             set_global("__PAGE_SHIFT", PIC16_PAGE_SHIFT,  VAL_CONSTANT, true, false);
227             set_global("__PAGE_SIZE",  class->page_size,  VAL_CONSTANT, true, false);
228             set_global("__PAGE_INV",   __PAGE_INV,        VAL_CONSTANT, true, false);
229 
230             _make_bank_constants_and_variables(found, num_of_banks);
231             _make_page_constants_and_variables(found, num_of_pages);
232           }
233           else if (class == PROC_CLASS_PIC16E) {
234             set_global("__16_BIT",   1, VAL_CONSTANT, true, false);
235             set_global("__EXTENDED", 1, VAL_CONSTANT, true, false);
236 
237             _make_bank_constants_and_variables(found, num_of_banks);
238           }
239 
240           set_global("__BANK_BITS",  found->bank_bits,       VAL_CONSTANT, true, false);
241           set_global("__BANK_MASK",  class->bank_mask,       VAL_CONSTANT, true, false);
242           set_global("__BANK_SHIFT", class->bank_bits_shift, VAL_CONSTANT, true, false);
243           set_global("__BANK_SIZE",  class->bank_size,       VAL_CONSTANT, true, false);
244           set_global("__BANK_INV",   __BANK_INV,             VAL_CONSTANT, true, false);
245 
246           if ((pair = gp_processor_common_ram_exist(found)) != NULL) {
247             set_global("__COMMON_RAM_START", pair[0], VAL_CONSTANT, true, false);
248             set_global("__COMMON_RAM_END",   pair[1], VAL_CONSTANT, true, false);
249           }
250 
251           if (found->common_ram_max > 0) {
252             set_global("__COMMON_RAM_MAX", found->common_ram_max, VAL_CONSTANT, true, false);
253           }
254 
255           if ((pair = gp_processor_linear_ram_exist(found)) != NULL) {
256             set_global("__LINEAR_RAM_START", pair[0], VAL_CONSTANT, true, false);
257             set_global("__LINEAR_RAM_END",   pair[1], VAL_CONSTANT, true, false);
258           }
259 
260           if ((class->vector_table != NULL) || (class->vector_number > 0)) {
261             vec = class->vector_table;
262             num = class->vector_number;
263 
264             for (; num; ++vec, --num) {
265               buf[0] = '_';
266               buf[1] = '_';
267               gp_stptoupper(&buf[2], vec->name, sizeof(buf) - 2);
268 
269               if (vec->address < 0) {
270                 /* This a SX type processor. */
271                 addr = found->prog_mem_size;
272 
273                 if (addr > 0) {
274                   --addr;
275                 }
276               }
277               else {
278                 addr = vec->address;
279               }
280 
281               set_global(buf, addr, VAL_CONSTANT, true, false);
282             }
283           }
284 
285           addr = found->prog_mem_size;
286 
287           if (addr > 0) {
288             set_global("__CODE_START",        0, VAL_CONSTANT, true, false);
289             set_global("__CODE_END",   addr - 1, VAL_CONSTANT, true, false);
290           }
291 
292           if ((pair = gp_processor_idlocs_exist(found)) != NULL) {
293             set_global("__IDLOCS_START", pair[0], VAL_CONSTANT, true, false);
294             set_global("__IDLOCS_END",   pair[1], VAL_CONSTANT, true, false);
295           }
296 
297           if ((pair = gp_processor_config_exist(found)) != NULL) {
298             set_global("__CONFIG_START", pair[0], VAL_CONSTANT, true, false);
299             set_global("__CONFIG_END",   pair[1], VAL_CONSTANT, true, false);
300           }
301 
302           if ((pair = gp_processor_eeprom_exist(found)) != NULL) {
303             set_global("__EEPROM_START", pair[0], VAL_CONSTANT, true, false);
304             set_global("__EEPROM_END",   pair[1], VAL_CONSTANT, true, false);
305           }
306 
307           addr = gp_processor_bsr_boundary(found);
308 
309           if (addr > 0) {
310             set_global("__ACC_RAM_LOW_START",        0, VAL_CONSTANT, true, false);
311             set_global("__ACC_RAM_LOW_END",   addr - 1, VAL_CONSTANT, true, false);
312           }
313         } /* if (!state.mpasm_compatible) */
314       } /* if (state.processor == NULL) */
315       else if (state.processor != found) {
316         gpmsg_vwarning(GPW_REDEFINING_PROC, NULL);
317         gpmsg_verror(GPE_EXTRA_PROC, NULL);
318       }
319     }
320     else {
321       if (state.pass > 0) {
322         gpmsg_verror(GPE_UNKNOWN_PROC, NULL, Name);
323       }
324       else {
325         printf("Didn't find any processor named: %s\nHere are the supported processors:\n", Name);
326         gp_dump_processor_list(true, PROC_CLASS_UNKNOWN, PROC_CLASS_UNKNOWN, PROC_CLASS_UNKNOWN);
327         exit(1);
328       }
329     }
330 
331     /* Load the instruction sets if necessary. */
332     if ((!state.processor_chosen) && (state.processor != NULL)) {
333       opcode_init(1);   /* General directives. */
334       /* Separate the directives from the opcodes. */
335       state.stBuiltin = gp_sym_push_table(state.stBuiltin, true);
336       opcode_init(2);   /* Processor-specific. */
337 
338       if (!(IS_PIC16_CORE) && !(IS_PIC16E_CORE)) {
339         opcode_init(3);   /* Special pseudo ops for 12 and 14 bit devices. */
340       }
341 
342       state.processor_chosen = true;
343     }
344   }
345 }
346