Merge branch 'assembler-e' into 'assembler'
merge assembler-e into assembler See merge request lab2324_summer/armv8_43!4
This commit is contained in:
commit
adadbbb616
96
src/parser.c
96
src/parser.c
@ -10,10 +10,79 @@
|
|||||||
//TODO:
|
//TODO:
|
||||||
// - use string matching to get opcode, and operands (DONE)
|
// - use string matching to get opcode, and operands (DONE)
|
||||||
// - check operand count (DONE)
|
// - check operand count (DONE)
|
||||||
// - match opcode to a64 struct types (PARTIALLY DONE)
|
// - match opcode to a64 struct types (DONE)
|
||||||
// - count operands and match type/values
|
// - count operands and match type/values
|
||||||
// - generate final a64inst and return
|
// - generate final a64inst and return
|
||||||
|
|
||||||
|
//calculate offsets from string
|
||||||
|
void calcluateAddressFormat(a64inst_instruction *instr, char *operandList[]){
|
||||||
|
|
||||||
|
if(strcmp(operandList[2][strlen(operandList[1])-1], "!")==0){
|
||||||
|
instr->data.processOpData.addressingMode = a64inst_PRE_INDEXED;
|
||||||
|
} else if(strcmp(operandList[1][strlen(operandList[0])-1], "]") == 0) {
|
||||||
|
//post-indexed
|
||||||
|
instr->data.processOpData.addressingMode = a64inst_POST_INDEXED;
|
||||||
|
} else if( (strcmp(operandList[2][strlen(operandList[1])-1], "x") == 0)
|
||||||
|
|| (strcmp(operandList[2][strlen(operandList[1])-1], "w") == 0)){
|
||||||
|
//register
|
||||||
|
instr->data.processOpData.addressingMode = a64inst_REGISTER_OFFSET;
|
||||||
|
} else {
|
||||||
|
instr->data.processOpData.addressingMode = a64inst_UNSIGNED_OFFSET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateLoadStoreOperands(a64inst_instruction *instr, char *opcode, char *operandList[]){
|
||||||
|
switch(instr->data.type){
|
||||||
|
case a64inst_SINGLETRANSFER:
|
||||||
|
if(strcmp(operandList[0][0], "x")==0){
|
||||||
|
//x-register
|
||||||
|
instr->data.regType = 1;
|
||||||
|
} else {
|
||||||
|
instr->data.regType = 0;
|
||||||
|
}
|
||||||
|
char *endptr;
|
||||||
|
instr->data.target = strtol(operandList[0][0]+1, endptr, 2);
|
||||||
|
calcluateAddressFormat(instr, operandList);
|
||||||
|
break;
|
||||||
|
case a64inst_LOADLITERAL:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateBranchOperands(a64inst_instruction *instr, char* opcode, char *operandList[]){
|
||||||
|
switch(instr->data.BranchType){
|
||||||
|
case a64inst_UNCONDITIONAL:
|
||||||
|
//define and sign extend immediate offset
|
||||||
|
//use symbol table
|
||||||
|
break;
|
||||||
|
case a64inst_REGISTER:
|
||||||
|
char *endptr;
|
||||||
|
instr->data.processOpData.src = strtol(operandList[0] + 1, endptr, 2)
|
||||||
|
break;
|
||||||
|
case a64inst_CONDITIONAL:
|
||||||
|
char* condition = strtok(strdup(opcode), "b.");
|
||||||
|
condition = strtok(NULL, "");
|
||||||
|
if(strcmp(condition, "eq")==0){
|
||||||
|
instr->data.processOpData.cond = EQ;
|
||||||
|
} else if (strcmp(condition, "ne")==0){
|
||||||
|
instr->data.processOpData.cond = NE;
|
||||||
|
} else if (strcmp(condition, "ge")==0){
|
||||||
|
instr->data.processOpData.cond = GE;
|
||||||
|
} else if (strcmp(condition, "lt")==0){
|
||||||
|
instr->data.processOpData.cond = LT;
|
||||||
|
} else if (strcmp(condition, "gt")==0){
|
||||||
|
instr->data.processOpData.cond = GT;
|
||||||
|
} else if (strcmp(condition, "le")==0){
|
||||||
|
instr->data.processOpData.cond = LE;
|
||||||
|
} else if (srtcmp(condition, "al")==0){
|
||||||
|
instr->data.processOpData.cond = AL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
//calculate offset from symbol table.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[]){
|
void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[]){
|
||||||
if((int isUnconditional = strcmp(opcode, "b")) == 0 ||
|
if((int isUnconditional = strcmp(opcode, "b")) == 0 ||
|
||||||
(int isRegister = strcmp(opcode, "br")) == 0 ||
|
(int isRegister = strcmp(opcode, "br")) == 0 ||
|
||||||
@ -27,16 +96,18 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[
|
|||||||
instr->data.BranchData.BranchType = a64inst_CONDITIONAL;
|
instr->data.BranchData.BranchType = a64inst_CONDITIONAL;
|
||||||
//instr->data.branchData.processOpData.cond = {remove first two chars of opcode}
|
//instr->data.branchData.processOpData.cond = {remove first two chars of opcode}
|
||||||
}
|
}
|
||||||
|
generateBranchOperands(instr, opcode, operandList);
|
||||||
} else if((int isLoad = strcmp(opcode, "ldr")) == 0 || (int isStore = strcmp(opcode, "str")) == 0){
|
} else if((int isLoad = strcmp(opcode, "ldr")) == 0 || (int isStore = strcmp(opcode, "str")) == 0){
|
||||||
//loading/storing instruction; classify operands
|
//loading/storing instruction; classify operands
|
||||||
char *address = operandList[1];
|
char *address = operandList[1];
|
||||||
if( *address == '['){
|
if( *address == '['){
|
||||||
//type is register
|
//type is register
|
||||||
instr->type = a64inst_SINGLETRANSFER;
|
instr->type = a64inst_SINGLETRANSFER;
|
||||||
|
instr->data.SingleTransferOpType = a64inst_SINGLE_TRANSFER_SINGLE_DATA_TRANSFER;
|
||||||
if(isLoad == 0){
|
if(isLoad == 0){
|
||||||
instr->data.processOpData.singleDataTransferData.transferType = a64inst_LOAD;
|
instr->data.processOpData.transferType = a64inst_LOAD;
|
||||||
} else {
|
} else {
|
||||||
instr->data.processOpData.singleDataTransferData.transferType = a64inst_STORE;
|
instr->data.processOpData.transferType = a64inst_STORE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instr->type = a64inst_LOADLITERAL;
|
instr->type = a64inst_LOADLITERAL;
|
||||||
@ -44,7 +115,12 @@ void classifyOpcode(char* opcode, a64inst_instruction *instr, char *operandList[
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//data processing
|
int numOperands = sizeof(operandList) / sizeof(operandList[0])
|
||||||
|
if(numOperands==3){
|
||||||
|
instr->type = a64inst_DPREGISTER;
|
||||||
|
} else {
|
||||||
|
instr->type = a64inst_DPIMMEDIATE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,11 +150,6 @@ a64inst_instruction *parser(char asmLine[]){
|
|||||||
return(instr);
|
return(instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strcmp(asmLine, HALT_ASM_CMD) == 0){
|
|
||||||
instr->type = a64inst_HALT;
|
|
||||||
return(instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
//"opcode operand1, {operand2}, ..."
|
//"opcode operand1, {operand2}, ..."
|
||||||
//duplicated as strtok modifies the input string
|
//duplicated as strtok modifies the input string
|
||||||
char *stringptr = strdup(asmLine);
|
char *stringptr = strdup(asmLine);
|
||||||
@ -88,10 +159,15 @@ a64inst_instruction *parser(char asmLine[]){
|
|||||||
|
|
||||||
if(strcmp(opcode, ".int") == 0){
|
if(strcmp(opcode, ".int") == 0){
|
||||||
//type is directive
|
//type is directive
|
||||||
|
instr->type = a64inst_DIRECTIVE;
|
||||||
|
|
||||||
} else if(strcmp(opcode[strlen(opcode)-1], ":") == 0) {
|
} else if(strcmp(opcode[strlen(opcode)-1], ":") == 0) {
|
||||||
//type is label
|
//type is label
|
||||||
//add to symbol table
|
//add to symbol table
|
||||||
|
instr->type = a64inst_LABEL;
|
||||||
|
char *opcodeCpy = strdup(opcode);
|
||||||
|
char *labelData = strtok(opcodeCpy, ":");
|
||||||
|
instr->data.label = labelData;
|
||||||
} else {
|
} else {
|
||||||
//type is instruction
|
//type is instruction
|
||||||
int operandCount = 0;
|
int operandCount = 0;
|
||||||
@ -100,7 +176,7 @@ a64inst_instruction *parser(char asmLine[]){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return(a64inst_instruction);
|
return(instr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,5 @@
|
|||||||
|
#ifndef __PARSERCONSTS__
|
||||||
|
#define __PARSERCONSTS__
|
||||||
#define OPERAND_DELIMITER ", "
|
#define OPERAND_DELIMITER ", "
|
||||||
#define HALT_ASM_CMD "and x0, x0, x0"
|
#define HALT_ASM_CMD "and x0, x0, x0"
|
||||||
|
#endif
|
||||||
@ -4,32 +4,35 @@
|
|||||||
//generates assembled code based on two pass assembly method
|
//generates assembled code based on two pass assembly method
|
||||||
|
|
||||||
|
|
||||||
word assembleBranch(a64inst_instruction *instr, int ){
|
word assembleBranch(a64inst_instruction *instr){
|
||||||
word binInstr = 0;
|
word binInstr = 0;
|
||||||
|
binInstr += (5^28); //101 start of branch instr
|
||||||
switch (instr->data.BranchData.BranchType)
|
switch (instr->data.BranchData.BranchType)
|
||||||
{
|
{
|
||||||
case a64inst_UNCONDITIONAL:
|
case a64inst_UNCONDITIONAL:
|
||||||
//000101
|
//000101
|
||||||
//25-0: sign extended simm26
|
//25-0: sign extended simm26
|
||||||
|
binInstr += instr->data.processOpData.unconditionalOffset;
|
||||||
break;
|
break;
|
||||||
case a64inst_REGISTER:
|
case a64inst_REGISTER:
|
||||||
//1101011
|
//10000
|
||||||
//0000
|
|
||||||
//11111
|
//11111
|
||||||
//000000
|
//000000
|
||||||
//9-5: address from register
|
//9-5: address from register
|
||||||
//0000
|
//0000
|
||||||
|
binInstr += ((instr->processOpData.src)^5);
|
||||||
break;
|
break;
|
||||||
case a64inst_CONDITIONAL:
|
case a64inst_CONDITIONAL:
|
||||||
// 01010100
|
// 01010100
|
||||||
// 25-5: sign extended offset
|
// 25-5: sign extended offset
|
||||||
// 4-0: 0{condition}
|
// 4-0: 0{condition}
|
||||||
|
binInstr += ((instr->processOpData.offset)^5);
|
||||||
|
binInstr += instr->processOpData.cond;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return binInstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
st* firstPass(a64inst_instruction instrs[], int numInstrs){
|
st* firstPass(a64inst_instruction instrs[], int numInstrs){
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user