ASM: Added support for labels in the assembler
This commit is contained in:
parent
41fed482fe
commit
4863db36ee
90
assembly.c
90
assembly.c
@ -3,6 +3,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define MAX_LABEL_SIZE 30
|
||||||
|
#define MAX_LABEL_SIZE_str "30"
|
||||||
|
|
||||||
// Max instruction width is 25 characters without the null char
|
// Max instruction width is 25 characters without the null char
|
||||||
//
|
//
|
||||||
@ -208,8 +210,36 @@ char *disassemble(uint32_t opcode_be){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t parse_immediate(char* str,struct assembler_context_t *assembler_context){
|
||||||
|
if(*str=='0'){
|
||||||
|
uint32_t addr;
|
||||||
|
if(sscanf(str,"%06X",&addr)!=1)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return addr&0x00FFFFFF;
|
||||||
|
}else{
|
||||||
|
// Get name size
|
||||||
|
int len=0;
|
||||||
|
for(int i=0;i<MAX_LABEL_SIZE+1;i++){
|
||||||
|
if(i==MAX_LABEL_SIZE)
|
||||||
|
return -2;
|
||||||
|
if(str[i]==0||str[i]=='\n'||str[i]==' '){
|
||||||
|
break;
|
||||||
|
}else
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_context_t *assembler_context){
|
struct label_ll_t *search=assembler_context->label_ll;
|
||||||
|
while(search){
|
||||||
|
if(strncmp(str,search->name,len)==0)
|
||||||
|
return search->address;
|
||||||
|
search=search->next;
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t assemble_line(char *line, struct assembler_context_t *assembler_context){
|
||||||
uint16_t opcode;
|
uint16_t opcode;
|
||||||
int x;
|
int x;
|
||||||
int call;
|
int call;
|
||||||
@ -246,13 +276,18 @@ uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_cont
|
|||||||
}else
|
}else
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
while(line[x]==' ')x++;
|
while(line[x]==' ')x++;
|
||||||
uint32_t addr;
|
|
||||||
if(line[x]=='$'){
|
if(line[x]=='$'){
|
||||||
x++;
|
x++;
|
||||||
if(sscanf(line+x,"%06X",&addr)!=1)
|
int32_t imm=parse_immediate(line+x,assembler_context);
|
||||||
|
if(imm<0){
|
||||||
|
switch(imm){
|
||||||
|
default:
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
else
|
case -2:
|
||||||
return opcode<<24|(addr&0x00FFFFFF);
|
return 0xFFFFFFFE;
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
return opcode<<24|(imm&0x00FFFFFF);
|
||||||
}else
|
}else
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}else{
|
}else{
|
||||||
@ -372,11 +407,54 @@ uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_cont
|
|||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}else if(strncmp(line,"RET",3)==0){
|
}else if(strncmp(line,"RET",3)==0){
|
||||||
return 0x10000000;
|
return 0x10000000;
|
||||||
}
|
}else if(*line==':')
|
||||||
|
return 0xFFFFFFF0;
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int assembler_context_process(char* line,struct assembler_context_t *assembler_context){
|
||||||
|
switch(line[0]){
|
||||||
|
case ':':
|
||||||
|
if(line[1]==0)
|
||||||
|
return 1;
|
||||||
|
else{
|
||||||
|
char* label=malloc(MAX_LABEL_SIZE+1);
|
||||||
|
sscanf(line+1,"%"MAX_LABEL_SIZE_str"s",label);
|
||||||
|
struct label_ll_t **current;
|
||||||
|
current=&(assembler_context->label_ll);
|
||||||
|
while(*current)
|
||||||
|
current=&((*current)->next);
|
||||||
|
*current=malloc(sizeof(struct label_ll_t));
|
||||||
|
(*current)->name=label;
|
||||||
|
(*current)->address=assembler_context->current_location;
|
||||||
|
(*current)->next=NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
assembler_context->current_location+=4;
|
||||||
|
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct assembler_context_t *malloc_assembler_context(){
|
||||||
|
struct assembler_context_t *ret;
|
||||||
|
ret=malloc(sizeof(struct assembler_context_t));
|
||||||
|
ret->current_location=0x00000000;
|
||||||
|
ret->label_ll=NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void free_assembler_context(struct assembler_context_t *tofree){
|
void free_assembler_context(struct assembler_context_t *tofree){
|
||||||
|
struct label_ll_t *tofree_ll=tofree->label_ll;
|
||||||
|
while(tofree_ll){
|
||||||
|
struct label_ll_t *temp=tofree_ll;
|
||||||
|
tofree_ll=tofree_ll->next;
|
||||||
|
free(temp->name);
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
free(tofree);
|
free(tofree);
|
||||||
}
|
}
|
||||||
|
10
assembly.h
10
assembly.h
@ -9,8 +9,12 @@ struct label_ll_t{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct assembler_context_t{
|
struct assembler_context_t{
|
||||||
struct label_ll_t label_ll;
|
struct label_ll_t *label_ll;
|
||||||
|
uint32_t current_location;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_context_t *assembler_context);
|
uint32_t assemble_line(char *line, struct assembler_context_t *assembler_context);
|
||||||
void free_assembler_context(struct assembler_context_t *tofree);
|
int assembler_context_process(char* line,struct assembler_context_t *tofree);
|
||||||
|
|
||||||
|
struct assembler_context_t *malloc_assembler_context();
|
||||||
|
void free_assembler_context(struct assembler_context_t *assembler_context);
|
||||||
|
33
main.c
33
main.c
@ -85,7 +85,7 @@ int main(int argc, char* argd[] ){
|
|||||||
|
|
||||||
if ( assemble != NULL ){
|
if ( assemble != NULL ){
|
||||||
/* RUN ASSEMBLER */
|
/* RUN ASSEMBLER */
|
||||||
struct assembler_context_t *assembler_context=malloc(sizeof(struct assembler_context_t));
|
struct assembler_context_t *assembler_context=malloc_assembler_context();
|
||||||
|
|
||||||
for (int i=0;i<ADDR_SIZE;i++)
|
for (int i=0;i<ADDR_SIZE;i++)
|
||||||
simdata->RAM[i]=0;
|
simdata->RAM[i]=0;
|
||||||
@ -94,6 +94,30 @@ int main(int argc, char* argd[] ){
|
|||||||
char line [1000];
|
char line [1000];
|
||||||
uint32_t opcode;
|
uint32_t opcode;
|
||||||
uint32_t addr=0;
|
uint32_t addr=0;
|
||||||
|
|
||||||
|
//--------------- Build assembler context --------------------
|
||||||
|
while(fgets(line,sizeof(line),rom)!= NULL){
|
||||||
|
|
||||||
|
for(int i=0;line[i];i++)
|
||||||
|
if(line[i]==0x0a)
|
||||||
|
line[i]=0;
|
||||||
|
|
||||||
|
switch(assembler_context_process(line,assembler_context)){
|
||||||
|
case 0: break;
|
||||||
|
default:
|
||||||
|
printf("Error in getting assembler context at %s:%d\n", infile,linec+1);
|
||||||
|
fclose(rom);
|
||||||
|
free_assembler_context(assembler_context);
|
||||||
|
free_simdata(simdata);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
linec++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(rom, 0, SEEK_SET);
|
||||||
|
linec=0;
|
||||||
|
|
||||||
|
//---------------------- Assembler ---------------------------
|
||||||
while(fgets(line,sizeof(line),rom)!= NULL){
|
while(fgets(line,sizeof(line),rom)!= NULL){
|
||||||
|
|
||||||
for(int i=0;line[i];i++)
|
for(int i=0;line[i];i++)
|
||||||
@ -102,12 +126,17 @@ int main(int argc, char* argd[] ){
|
|||||||
|
|
||||||
opcode=assemble_line(line,assembler_context);
|
opcode=assemble_line(line,assembler_context);
|
||||||
|
|
||||||
if(opcode>0xFFFFFFF1){
|
if(opcode>=0xFFFFFFF1){
|
||||||
|
if(opcode==0xFFFFFFFE)
|
||||||
|
printf("Error label not found %s:%d\n", infile,linec+1);
|
||||||
|
else
|
||||||
printf("Error assembling %s:%d\n", infile,linec+1);
|
printf("Error assembling %s:%d\n", infile,linec+1);
|
||||||
fclose(rom);
|
fclose(rom);
|
||||||
free_assembler_context(assembler_context);
|
free_assembler_context(assembler_context);
|
||||||
free_simdata(simdata);
|
free_simdata(simdata);
|
||||||
return 1;
|
return 1;
|
||||||
|
}else if(opcode==0xFFFFFFF0){
|
||||||
|
;/*it was empty, comment or label*/
|
||||||
}else{
|
}else{
|
||||||
simdata->RAM[addr]=(0xFF000000&opcode)>>24;
|
simdata->RAM[addr]=(0xFF000000&opcode)>>24;
|
||||||
addr++;
|
addr++;
|
||||||
|
11
test.asm
11
test.asm
@ -3,9 +3,12 @@ MOV $0x0001,%R0l
|
|||||||
MOV $0x0000,%R0h
|
MOV $0x0000,%R0h
|
||||||
MOV $0x0000,%R1l
|
MOV $0x0000,%R1l
|
||||||
MOV $0x0000,%R1h
|
MOV $0x0000,%R1h
|
||||||
CALL $0x0024
|
CALL $SUBROUTINE
|
||||||
CALL $0x0024
|
CALL $SUBROUTINE
|
||||||
CALL $0x0024
|
CALL $SUBROUTINE
|
||||||
HALT
|
JMP $END
|
||||||
|
:SUBROUTINE
|
||||||
ADD %R0,%R1
|
ADD %R0,%R1
|
||||||
RET
|
RET
|
||||||
|
:END
|
||||||
|
HALT
|
||||||
|
Loading…
Reference in New Issue
Block a user