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