1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
|
/** @file main.c
avr specific general functions.
Note that mlh prepended _avr_ on the static functions. Makes
it easier to set a breakpoint using the debugger.
*/
#include "common.h"
#include "main.h"
#include "ralloc.h"
#include "gen.h"
static char _defaultRules[] = {
#include "peeph.rul"
};
/* list of key words used by msc51 */
static char *_avr_keywords[] = {
"at",
"code",
"critical",
"eeprom",
"interrupt",
"sfr",
"xdata",
"_code",
"_eeprom",
"_generic",
"_xdata",
"sram",
"_sram",
"flash",
"_flash",
NULL
};
static int regParmFlg = 0; /* determine if we can register a parameter */
static void
_avr_init (void)
{
asm_addTree (&asm_asxxxx_mapping);
}
static void
_avr_reset_regparm (void)
{
regParmFlg = 0;
}
static int
_avr_regparm (sym_link * l, bool reentrant)
{
/* the first eight bytes will be passed in
registers r16-r23. but we won't split variables
i.e. if not enough registers left to hold
the parameter then the whole parameter along
with rest of the parameters go onto the stack */
if (regParmFlg < 8) {
int size;
if ((size = getSize (l)) > (8 - regParmFlg)) {
/* all remaining go on stack */
regParmFlg = 8;
return 0;
}
regParmFlg += size;
return 1;
}
return 0;
}
void avr_assignRegisters (ebbIndex *);
static bool
_avr_parseOptions (int *pargc, char **argv, int *i)
{
/* TODO: allow port-specific command line options to specify
* segment names here.
*/
return FALSE;
}
static void
_avr_finaliseOptions (void)
{
port->mem.default_local_map = port->mem.default_globl_map = xdata;
/* change stack to be in far space */
/* internal stack segment ;
SFRSPACE - NO
FAR-SPACE - YES
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
CODE-ACESS - NO
DEBUG-NAME - 'B'
POINTER-TYPE - FPOINTER
*/
istack =
allocMap (0, 1, 0, 0, 0, 0, options.stack_loc, ISTACK_NAME,
'B', FPOINTER);
/* also change xdata to be direct space since we can use lds/sts */
xdata->direct = 1;
}
static void
_avr_setDefaultOptions (void)
{
options.stackAuto = 1;
}
static const char *
_avr_getRegName (struct regs *reg)
{
if (reg)
return reg->name;
return "err";
}
static void
_avr_genAssemblerPreamble (FILE * of)
{
}
/* Generate interrupt vector table. */
static int
_avr_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
{
return TRUE;
}
/* Indicate which extended bit operations this port supports */
static bool
hasExtBitOp (int op, int size)
{
if (op == RRC
|| op == RLC
|| op == GETHBIT
)
return TRUE;
else
return FALSE;
}
/* Indicate the expense of an access to an output storage class */
static int
oclsExpense (struct memmap *oclass)
{
if (IN_FARSPACE(oclass))
return 1;
return 0;
}
/** $1 is always the basename.
$2 is always the output file.
$3 varies
$l is the list of extra options that should be there somewhere...
MUST be terminated with a NULL.
*/
static const char *_linkCmd[] = {
"linkavr", "", "$1", NULL
};
/* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
static const char *_asmCmd[] = {
"asavr", "$l" , "$3", "$1.s", NULL
};
/* Globals */
PORT avr_port = {
TARGET_ID_AVR,
"avr",
"ATMEL AVR", /* Target name */
NULL, /* processor */
{
glue,
TRUE, /* Emit glue around main */
MODEL_LARGE | MODEL_SMALL,
MODEL_SMALL,
NULL, /* model == target */
},
{
_asmCmd,
NULL,
"-plosgff", /* Options with debug */
"-plosgff", /* Options without debug */
0,
".s",
NULL, /* no do_assemble */
},
{
_linkCmd,
NULL,
NULL,
".rel",
1},
{
_defaultRules},
{
/* Sizes: char, short, int, long, long long, ptr, fptr, gptr, bit, float, max */
1, 2, 2, 4, 8, 2, 2, 3, 1, 4, 4},
/* tags for generic pointers */
{ 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
{
"XSEG",
"STACK",
"CSEG",
"DSEG",
"ISEG",
NULL, //PSEG
"XSEG",
"BSEG",
"RSEG",
"GSINIT",
"OSEG",
"GSFINAL",
"HOME",
NULL, // initialized xdata
NULL, // a code copy of xiseg
"CONST (CODE)", // const_name - const data (code or not)
"CABS (ABS,CODE)", // cabs_name - const absolute data (code or not)
"XABS (ABS,XDATA)", // xabs_name - absolute xdata/pdata
"IABS (ABS,DATA)", // iabs_name - absolute idata/data
NULL,
NULL,
0,
},
{ NULL, NULL },
{
-1, 1, 4, 1, 1, 0, 1},
/* avr has an 8 bit mul */
{
1, -1, FALSE
},
{
avr_emitDebuggerSymbol
},
{
255/3, /* maxCount */
3, /* sizeofElement */
/* The rest of these costs are bogus. They approximate */
/* the behavior of src/SDCCicode.c 1.207 and earlier. */
{4,4,4}, /* sizeofMatchJump[] */
{0,0,0}, /* sizeofRangeCompare[] */
0, /* sizeofSubtract */
3, /* sizeofDispatch */
},
"_",
_avr_init,
_avr_parseOptions,
NULL,
NULL,
_avr_finaliseOptions,
_avr_setDefaultOptions,
avr_assignRegisters,
_avr_getRegName,
_avr_keywords,
_avr_genAssemblerPreamble,
NULL, /* no genAssemblerEnd */
_avr_genIVT,
NULL, // _avr_genXINIT
NULL, /* genInitStartup */
_avr_reset_regparm,
_avr_regparm,
NULL,
NULL,
NULL,
hasExtBitOp, /* hasExtBitOp */
oclsExpense, /* oclsExpense */
FALSE,
TRUE, /* little endian */
0, /* leave lt */
1, /* transform gt ==> not le */
0, /* leave le */
0, /* leave ge */
0, /* leave != */
0, /* leave == */
FALSE, /* No array initializer support. */
0, /* no CSE cost estimation yet */
NULL, /* no builtin functions */
GPOINTER, /* treat unqualified pointers as "generic" pointers */
1, /* reset labelKey to 1 */
1, /* globals & local static allowed */
PORT_MAGIC
};
|