Update encode to handle branches with sign extend
This commit is contained in:
parent
4139d7a083
commit
37a9cf0400
43
src/encode.c
43
src/encode.c
@ -25,22 +25,41 @@ void setBits(word* wrd, uint8_t lsb, uint8_t msb, word value) {
|
||||
*wrd |= (value << lsb) & mask;
|
||||
}
|
||||
|
||||
/*
|
||||
static int getLabelOffset(symbol_table* table, char* label, int currentIndex) {
|
||||
address target = st_get(table, label);
|
||||
return target - (currentIndex * 4);
|
||||
}
|
||||
*/
|
||||
// Sign extend a given value to a 64-bit signed integer given the number of bits
|
||||
int64_t signExtend(dword value, unsigned int n) {
|
||||
if (n == 0 || n >= 64) {
|
||||
// If n_bits is 0 or greater than or equal to 64, return the value as is
|
||||
return (int64_t)value;
|
||||
}
|
||||
|
||||
uint64_t sign_bit_mask = (uint64_t)1 << (n - 1);
|
||||
|
||||
// Mask to isolate the n-bit value
|
||||
uint64_t n_bit_mask = (sign_bit_mask << 1) - 1;
|
||||
|
||||
// Check if the sign bit is set
|
||||
if (value & sign_bit_mask) {
|
||||
// Sign bit is set, extend the sign
|
||||
return (int64_t)(value | ~n_bit_mask);
|
||||
} else {
|
||||
// Sign bit is not set, return the value as is
|
||||
return (int64_t)(value & n_bit_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static int getLabelOffset(symbol_table* table, char* label, int currentIndex, int n_bits) {
|
||||
address target = st_get(table, label);
|
||||
return signExtend((unsigned int) (target - (currentIndex * 4)), n_bits);
|
||||
}
|
||||
|
||||
// Generates assembled code based on the two-pass assembly method
|
||||
word encodeBranch(a64inst_instruction *instr) {
|
||||
word encodeBranch(a64inst_instruction *instr, int index, symbol_table *st) {
|
||||
word wrd = 0;
|
||||
|
||||
switch (instr->data.BranchData.BranchType) {
|
||||
case a64inst_UNCONDITIONAL:
|
||||
setBits(&wrd, 26, 30, 0x5);
|
||||
setBits(&wrd, 0, 25, instr->data.BranchData.processOpData.unconditionalData.unconditionalOffset);
|
||||
setBits(&wrd, 26, 29, 0x5);
|
||||
setBits(&wrd, 0, 25, getLabelOffset(st, instr->data.BranchData.processOpData.unconditionalData.label, index, 26));
|
||||
break;
|
||||
|
||||
case a64inst_REGISTER:
|
||||
@ -50,7 +69,7 @@ word encodeBranch(a64inst_instruction *instr) {
|
||||
|
||||
case a64inst_CONDITIONAL:
|
||||
setBits(&wrd, 26, 32, 0x15);
|
||||
setBits(&wrd, 5, 24, instr->data.BranchData.processOpData.conditionalData.offset);
|
||||
setBits(&wrd, 5, 24, getLabelOffset(st, instr->data.BranchData.processOpData.conditionalData.label, index, 19));
|
||||
setBits(&wrd, 0, 4, instr->data.BranchData.processOpData.conditionalData.cond);
|
||||
break;
|
||||
}
|
||||
@ -168,7 +187,7 @@ word encodeLoadLiteral(a64inst_instruction cI) {
|
||||
return wrd;
|
||||
}
|
||||
|
||||
word *encode(a64inst_instruction insts[], int instCount, symbol_table* table) {
|
||||
word *encode(a64inst_instruction insts[], int instCount, symbol_table* st) {
|
||||
word *arr = (word*)malloc(sizeof(word) * instCount);
|
||||
int index = 0;
|
||||
for (int i = 0; i < instCount; i++) {
|
||||
@ -202,7 +221,7 @@ word *encode(a64inst_instruction insts[], int instCount, symbol_table* table) {
|
||||
// Labels are handled in the first pass and used for addressing.
|
||||
break;
|
||||
case a64inst_BRANCH:
|
||||
arr[index] = encodeBranch(&inst);
|
||||
arr[index] = encodeBranch(&inst, index, st);
|
||||
index++;
|
||||
default:
|
||||
break;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user