Skip to content

Commit dbbc13e

Browse files
committed
Added information section pseudo instructions
1 parent faeaa76 commit dbbc13e

2 files changed

Lines changed: 168 additions & 5 deletions

File tree

examples/ex.asm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
INF
2+
PINF
3+
BLERG 0b110
4+
HOOP 0o11
5+
BADR 0x40
6+
EPINF
7+
DSEC datastart
8+
DNUM 0x2
9+
DSIZE 0x3
10+
EINF
11+
LOD hello
12+
LOD isitmeyourelookingfor
13+
datastart:
14+
hello: .data 3 0x2
15+
isitmeyourelookingfor: .data 3 0x2

src/as4.c

Lines changed: 153 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ int main(int argc, char **argv)
5959
label *labels = NULL;
6060
/* Pointer to the collection of referenced and potentially valid but undeclared labels */
6161
label *unknownlabels = NULL;
62-
62+
/* If we are in a PINF, treat every unknown tuple as a pseudo instruction with a data field. */
63+
unsigned char inpinf = 0;
64+
/* endptr is used to check if numbers are valid. */
65+
char *endptr = NULL;
66+
6367
/* Check if a base address has been specified */
6468
if(!strncmp(argv[1], "-b", 3))
6569
{
66-
/* We use this endptr to check if the input is valid */
6770
/* strtoul sets this endptr to the address of the first invalid character - if that's equal to argv[2], the entire string was invalid. */
68-
char *endptr = NULL;
6971

7072
/* If yes, out input and output arguments are two elements farther in the array so increment arg */
7173
arg += 2;
@@ -226,6 +228,136 @@ int main(int argc, char **argv)
226228
/* Add the instruction to the output buffer. */
227229
addinst(outbuf, NOP, NOADDR, &bits, &bytes);
228230
}
231+
/* Start of the information section. Save as NOP with address 0xFFFF so the processor isn't bothered but we can tell later. */
232+
else if(!strncmp(tokens, "INF", 4))
233+
{
234+
/* ignore anything after INF on this line */
235+
doneline = 1;
236+
/* Add this to the output buffer. */
237+
addinst(outbuf, NOP, 0xFFFF, &bits, &bytes);
238+
239+
}
240+
/* Start of the program information section within the information section. Save as a NOP with address 0xFFFF so the processor isn't bothered but we can tell later. */
241+
else if(!strncmp(tokens, "PINF", 5))
242+
{
243+
/* ignore anything after PINF on this line. */
244+
doneline = 1;
245+
/* Within the PINF...EPINF section, treat all unknown tuples as psuedo-instructions with a data section. */
246+
inpinf = 1;
247+
/* Add this to the output buffer */
248+
addinst(outbuf, NOP, 0xFFFF, &bits, &bytes);
249+
250+
}
251+
/* Record the base address into the executable. If the base address is specified externally, use that. */
252+
else if(!strncmp(tokens, "BADR", 5))
253+
{
254+
255+
tokens = strtok(NULL, delims);
256+
/* Check firstly that there is a valid label or address after the instruction. */
257+
if(tokens == NULL || tokens[0] == '\n' || tokens[0] == '\r' || tokens[0] == '\0' || tokens[0] == ' ')
258+
{
259+
fprintf(stderr, "Line %llu: A memory address must succeed a BADR instruction.\n", FILELINE);
260+
exit(33);
261+
}
262+
/* Get the address location. */
263+
/* If it's just a number after the instruction, that will be returned with the base address added to it. */
264+
/* If it's a yet undeclared label, 65535 (UNKNOWNADDR) is returned. The instruction will be modified when the label is declared. */
265+
/* If it's an already declared label return the address relative to the base address. */
266+
/* If allow program argument baseaddr to take precedence */
267+
if(baseaddr == 0)
268+
{
269+
baseaddr = findlabel(&unknownlabels, &labels, tokens, numlabels, &numunknownlabels, bits, INST);
270+
}
271+
/* Add this to the output buffer. */
272+
addinst(outbuf, NOP, baseaddr, &bits, &bytes);
273+
274+
275+
}
276+
/* End of the program information section within the information section. Save as a NOP with address 0xFFFF so the processor isn't bothered but we can tell later. */
277+
else if(!strncmp(tokens, "EPINF", 6))
278+
{
279+
/* ignore everything after EPINF on this line. */
280+
doneline = 1;
281+
/* We're out of the PINF, actually ignore unknowns now. */
282+
inpinf = 0;
283+
/* Add to the output buffer */
284+
addinst(outbuf, NOP, 0xFFFF, &bits, &bytes);
285+
286+
}
287+
/* Record the start of the data section. Allows easier disassembly. */
288+
else if(!strncmp(tokens, "DSEC", 5))
289+
{
290+
tokens = strtok(NULL, delims);
291+
/* Check firstly that there is a valid label or address after the instruction. */
292+
if(tokens == NULL || tokens[0] == '\n' || tokens[0] == '\r' || tokens[0] == '\0' || tokens[0] == ' ')
293+
{
294+
fprintf(stderr, "Line %llu: A memory address must succeed a DSEC instruction.\n", FILELINE);
295+
exit(34);
296+
}
297+
/* Get the address location. */
298+
/* If it's just a number after the instruction, that will be returned with the base address added to it. */
299+
/* If it's a yet undeclared label, 65535 (UNKNOWNADDR) is returned. The instruction will be modified when the label is declared. */
300+
/* If it's an already declared label return the address relative to the base address. */
301+
address = findlabel(&unknownlabels, &labels, tokens, numlabels, &numunknownlabels, bits, INST);
302+
/* Add this to the output buffer. */
303+
addinst(outbuf, NOP, address, &bits, &bytes);
304+
305+
}
306+
/* Each group of same size data sections should be recorded with the pair DNUM DSIZE */
307+
else if(!strncmp(tokens, "DNUM", 5))
308+
{
309+
tokens = strtok(NULL, delims);
310+
/* Check firstly that there is a valid label or address after the instruction. */
311+
if(tokens == NULL || tokens[0] == '\n' || tokens[0] == '\r' || tokens[0] == '\0' || tokens[0] == ' ')
312+
{
313+
fprintf(stderr, "Line %llu: A number of data fields must succeed a DNUM instruction.\n", FILELINE);
314+
exit(35);
315+
}
316+
/* Should just be a number - no labels! */
317+
address = estrtoul(tokens, &endptr, STDHEX);
318+
if(tokens == endptr)
319+
{
320+
fprintf(stderr, "Line %llu: A invalid number of data sections for DNUM.\n", FILELINE);
321+
exit(37);
322+
323+
}
324+
/* Add this to the output buffer. */
325+
addinst(outbuf, NOP, address, &bits, &bytes);
326+
327+
}
328+
/* Each group of same size data sections should be recorded with the pair DNUM DSIZE */
329+
else if(!strncmp(tokens, "DSIZE", 6))
330+
{
331+
tokens = strtok(NULL, delims);
332+
/* Check firstly that there is a valid label or address after the instruction. */
333+
if(tokens == NULL || tokens[0] == '\n' || tokens[0] == '\r' || tokens[0] == '\0' || tokens[0] == ' ')
334+
{
335+
fprintf(stderr, "Line %llu: A size must succeed a DSIZE instruction.\n", FILELINE);
336+
exit(36);
337+
}
338+
/* Should just be a number - no labels! */
339+
address = estrtoul(tokens, &endptr, STDHEX);
340+
if(tokens == endptr)
341+
{
342+
fprintf(stderr, "Line %llu: A invalid size of data sections for DSIZE.\n", FILELINE);
343+
exit(38);
344+
345+
}
346+
/* Add this to the output buffer. */
347+
addinst(outbuf, NOP, address, &bits, &bytes);
348+
349+
}
350+
/* End of the information section. Record it. */
351+
else if(!strncmp(tokens, "EINF", 5))
352+
{
353+
/* Nothing else on this line matters */
354+
doneline = 1;
355+
/* Just in case someone forgot EPINF... */
356+
inpinf = 0;
357+
/* Add it to the buffer. */
358+
addinst(outbuf, NOP, 0xFFFF, &bits, &bytes);
359+
360+
}
229361
/* Nand instruction. */
230362
else if(!strncmp(tokens, "NND", 4))
231363
{
@@ -280,8 +412,6 @@ int main(int argc, char **argv)
280412
unsigned long long datasize = 0;
281413
/* Initial value */
282414
long long datavalue = 0;
283-
/* endptr for determining if the number used for initilisation is valid */
284-
char *endptr = NULL;
285415

286416
/* Once we're done dealing with the .data element, we will have taken every useful token from this line, so declared the line done. */
287417
doneline = 1;
@@ -391,6 +521,24 @@ int main(int argc, char **argv)
391521
/* Add the label to the list of known labels and replace any references to it with it's actual address. */
392522
addlabel(outbuf, &labels, &unknownlabels, &numlabels, numunknownlabels, tokens, bits, baseaddr);
393523
}
524+
else if(inpinf)
525+
{
526+
/* Get the next token, which is likely a label (though it could be a number) */
527+
tokens = strtok(NULL, delims);
528+
/* Check firstly that there is a valid label or address after the instruction. */
529+
/* If not, assume the pseudo instruction wants a 0 data field */
530+
if(tokens == NULL || tokens[0] == '\n' || tokens[0] == '\r' || tokens[0] == '\0' || tokens[0] == ' ')
531+
{
532+
address = 0;
533+
}
534+
/* Get the address location. */
535+
/* If it's just a number after the instruction, that will be returned with the base address added to it. */
536+
/* If it's a yet undeclared label, 65535 (UNKNOWNADDR) is returned. The instruction will be modified when the label is declared. */
537+
/* If it's an already declared label return the address relative to the base address. */
538+
address = findlabel(&unknownlabels, &labels, tokens, numlabels, &numunknownlabels, bits, INST);
539+
/* Add this to the output buffer. */
540+
addinst(outbuf, NOP, address, &bits, &bytes);
541+
}
394542
/* If we're done the line, don't both getting another token. */
395543
if(doneline)
396544
{

0 commit comments

Comments
 (0)