From fd86df806b828bb257f6b88b227c4f0f90dcfb5e Mon Sep 17 00:00:00 2001 From: "(Tim) Efthimis Kritikos" Date: Wed, 14 Feb 2024 19:36:17 +0000 Subject: [PATCH] ASM: Implemented the ability to reference only the upper or lower double-word of a label's address to accommodate the limited register loading mechanism in the intruction set --- assembly.c | 177 ++++++++++++++++++++++++++++++++++++++--------------- test.asm | 6 +- 2 files changed, 132 insertions(+), 51 deletions(-) diff --git a/assembly.c b/assembly.c index d101581..ff39bd5 100644 --- a/assembly.c +++ b/assembly.c @@ -240,32 +240,84 @@ char *disassemble(uint32_t opcode_be){ return ret; } -int64_t parse_immediate(char* str,struct assembler_context_t *assembler_context){ +struct imm_ret_t{ + uint8_t status; + uint32_t value; + uint8_t size; +}; + +struct imm_ret_t *parse_immediate(char* str,struct assembler_context_t *assembler_context){ + struct imm_ret_t *imm_ret=malloc(sizeof(struct imm_ret_t)); + if(!imm_ret) + return 0; + imm_ret->size=0; if(*str=='0'){ uint32_t addr; if(sscanf(str,"0x%08X",&addr)!=1){ - return -1; - }else - return addr; + imm_ret->status=1; + return imm_ret; + }else{ + imm_ret->size+=2; + if(str[0]=='0'&&str[1]=='x'){ + int i=2; + while(1){ + if((str[i]>='0'&&str[i]<='9')||(str[i]>='a'&&str[i]<='f')||(str[i]>='A'&&str[i]<='F')) + imm_ret->size++; + else + break; + i++; + } + }else{ + imm_ret->status=1; + return imm_ret; + } + imm_ret->value=addr; + imm_ret->status=0; + return imm_ret; + } }else{ + int select=0; + if(*str=='<'){ + select=1; + imm_ret->size++; + str++; + }else if(*str=='>'){ + select=2; + imm_ret->size++; + str++; + } + // Get name size int len=0; for(int i=0;istatus=2; + return imm_ret; + } + if(str[i]==0||str[i]=='\n'||str[i]==' '||str[i]==','||str[i]==')'){ break; }else len++; } + imm_ret->size+=len; struct label_ll_t *search=assembler_context->label_ll; while(search){ - if(strncmp(str,search->name,len)==0) - return search->address; + if(strncmp(str,search->name,len)==0){ + if(select==1) + imm_ret->value=search->address>>16; + else if(select==2) + imm_ret->value=search->address&0x0000FFFF; + else + imm_ret->value=search->address; + imm_ret->status=0; + return imm_ret; + } search=search->next; } - return -2; + + imm_ret->status=2; + return imm_ret; } } @@ -311,16 +363,24 @@ int64_t assemble_line(char *line, struct assembler_context_t *assembler_context) while(line[x]==' ')x++; if(line[x]=='$'){ x++; - int64_t imm=parse_immediate(line+x,assembler_context); - if(imm<0){ - switch(imm){ + struct imm_ret_t *imm=parse_immediate(line+x,assembler_context); + uint32_t temp; + if(!imm) + return -2; + if(imm->status){ + switch(imm->status){ default: + free(imm); return -2; - case -2: + case 2: + free(imm); return -3; } - }else - return opcode<<24|(imm&0x00FFFFFF); + }else{ + temp=imm->value; + free(imm); + return opcode<<24|(temp&0x00FFFFFF); + } }else return -2; }else{ @@ -398,39 +458,52 @@ int64_t assemble_line(char *line, struct assembler_context_t *assembler_context) while(line[x]==' ')x++; if(line[x]=='$'){ x++; - if(sscanf(line+x,"%06X",&data)==1){ - x+=4; - while(line[x]==' ')x++; - if(line[x]!=','){ //24 bit TODO: not the best way to parse this - x+=2; - while(line[x]==' ')x++; + struct imm_ret_t *imm=parse_immediate(line+x,assembler_context); + if(!imm) + return -2; + if(imm->status){ + switch(imm->status){ + default: + free(imm); + return -2; + case 2: + free(imm); + return -3; } - if(line[x]==','){ + }else{ + data=imm->value; + x+=imm->size; + free(imm); + } + while(line[x]==' ')x++; + if(line[x]!=','){ + x+=2; + while(line[x]==' ')x++; + } + if(line[x]==','){ + x++; + while(line[x]==' ')x++; + if(line[x]=='%'){ x++; - while(line[x]==' ')x++; - if(line[x]=='%'){ + if(line[x]=='R'){ x++; - if(line[x]=='R'){ + if(line[x]>='0'&&line[x]<='7'){ + r1=line[x]-'0'; x++; - if(line[x]>='0'&&line[x]<='7'){ - r1=line[x]-'0'; - x++; - if(line[x]=='l') - return 0x40000000|r1<<16|(data&0xFFFF); - else if(line[x]=='h') - return 0x41000000|r1<<16|(data&0xFFFF); - else - return -2; - }else - return -2; - }else if(line[x]=='S'){ - x++; - if(line[x]=='P'){ - return 0x0F000000|(data&0x00FFFFFF); - }else + if(line[x]=='l') + return 0x40000000|r1<<16|(data&0xFFFF); + else if(line[x]=='h') + return 0x41000000|r1<<16|(data&0xFFFF); + else return -2; }else return -2; + }else if(line[x]=='S'){ + x++; + if(line[x]=='P'){ + return 0x0F000000|(data&0x00FFFFFF); + }else + return -2; }else return -2; }else @@ -563,16 +636,24 @@ int64_t assemble_line(char *line, struct assembler_context_t *assembler_context) while(line[x]==' ')x++; if(line[x]=='$'){ x++; - int64_t imm=parse_immediate(line+x,assembler_context); - if(imm<0){ - switch(imm){ + struct imm_ret_t *imm=parse_immediate(line+x,assembler_context); + uint32_t temp; + if(!imm) + return -2; + if(imm->status){ + switch(imm->status){ default: + free(imm); return -2; - case -2: + case 2: + free(imm); return -3; } - }else - return imm; + }else{ + temp=imm->value; + free(imm); + return temp; + } }else return -2; } diff --git a/test.asm b/test.asm index f9757a5..903b0f2 100644 --- a/test.asm +++ b/test.asm @@ -1,4 +1,4 @@ -MOV $FF0000,%SP +MOV $0xFF0000,%SP #Test verious instructions MOV $0x0001,%R0l @@ -56,8 +56,8 @@ MOV %R1,(%R0) MOV $0xcccd,%R1l MOV $0x3f4c,%R1h MOV %R1,(%R0) -MOV $0xF0D0,%R0l -MOV $0x0000,%R0h +MOV $>TR_LOW,%R0l +MOV $