ARMv8/src/twopassassembly.c
Dias Alberto, Ethan 9c6a459b23 Merge branch 'assembler' into 'assembler-e'
# Conflicts:
#   src/twopassassembly.c
2024-06-06 16:03:18 +00:00

226 lines
6.2 KiB
C

# include "global.h"
# include "a64instruction.h"
# include "symboltable.h"
//generates assembled code based on two pass assembly method
word assembleBranch(a64inst_instruction *instr){
word binInstr = 0;
binInstr += (5^28); //101 start of branch instr
switch (instr->data.BranchData.BranchType)
{
case a64inst_UNCONDITIONAL:
//000101
//25-0: sign extended simm26
binInstr += instr->data.processOpData.unconditionalOffset;
break;
case a64inst_REGISTER:
//10000
//11111
//000000
//9-5: address from register
//0000
binInstr += ((instr->processOpData.src)^5);
break;
case a64inst_CONDITIONAL:
// 01010100
// 25-5: sign extended offset
// 4-0: 0{condition}
binInstr += ((instr->processOpData.offset)^5);
binInstr += instr->processOpData.cond;
break;
default:
break;
}
return binInstr;
}
st* firstPass(a64inst_instruction instrs[], int numInstrs){
//TODO:
// -iterate over instructions, adding to symbol table
// create symbol table and map labels to addresses/lines
struct st table;
for(int i=0; i<numInstrs; i++){
// discuss defining a LABEL type
if(instrs[i].type==a64inst_LABEL){
st_add(table, &(instrs[i].data.LabelData.label), &i);
}
}
return &table;
}
word dpi(a64inst_instruction cI) {
word out = 0;
a64inst_DPImmediateData data = cI.data.DPImmediateData;
//sf
out += data.regType*(2^31);
out += data.processOp*(2^29);
out += 2^28;
// if arithmetic
if (data.DPIOpType == a64inst_DPI_ARITHM) {
out += 2^24;
// shift
if (data.processOpData.arithmData.shiftImmediate){
out += 2^22;
}
out += data.processOpData.arithmData.immediate*(2^10);
out += data.processOpData.arithmData.src*(2^5);
}
// if wide move
else {
out += 5*(2^23);
// hw
out += data.processOpData.wideMovData.shiftScalar*(2^21);
out += data.processOpData.wideMovData.immediate*(2^5);
}
// destination register
out += data.dest;
return out;
}
word dpr(a64inst_instruction cI) {
word out = 0;
a64inst_DPRegisterData data = cI.data.DPRegisterData;
// sf
int sf = data.regType;
// bits 27-25
out += 5*(2^25);
int m = data.DPROpType;
int opc = 0;
int opr = 0;
int rm = 0;
int operand = 0;
int rn = 0;
int rd = 0;
// multiply
if (m == 1) {
//opc = 0;
opr = 8;
if (data.processOpData.multiplydata.negProd) {
operand += 32;
}
operand += data.processOpData.multiplydata.summand;
}
// arithmetic and logical
else {
// shift
opr += 2*data.processOpData.arithmLogicData.shiftType;
// arithmetic
if (data.processOpData.arithmLogicData.type == 1){
opr += 8;
}
// logical
else {
if (data.processOpData.arithmLogicData.negShiftedSrc2) {
opr += 1;
}
}
operand += data.processOpData.arithmLogicData.shiftAmount;
}
rm += data.src1;
rn += data.src2;
rd += data.dest;
out += sf*(2^31);
out += opc * (2^29);
out += m* (2^28);
out += opr * (2^21);
out += rm * (2^16);
out += operand * 1024;
out += rn * 32;
out += rd;
return out;
}
word sts(a64inst_instruction cI) {
a64inst_SingleTransferData data = cI.data.SingleTransferData;
word out = 0;
a64inst_SingleDataTransferData data2 = data.processOpData.singleDataTransferData;
// this deals with every bit in the 31-23 range apart from sf and U
out += (512+128+64+32)*(2^23);
int sf = data.regType;
int u = 0;
int l = data2.transferType;
int offset = 0;
int xn = data2.base;
int rt = data.target;
switch (data2.addressingMode) {
// register offset
case 2:
offset += 2074 + 64*data2.a64inst_addressingModeData.offsetReg;
break;
// unsigned offset
case 3:
offset += data2.a64inst_addressingModeData.unsignedOffset;
u = 1;
break;
// pre/post indexed
default:
offset = 1 + data2.addressingMode*2 + data2.a64inst_addressingModeData.indexedOffset*4;
break;
}
out += sf*(2^30);
out += u*(2^22);
out += offset*1024;
out += xn * 32;
out += rt;
return out;
}
word ldl(a64inst_instruction cI) {
word out = 3*(2^27);
a64inst_SingleTransferData data = cI.data.SingleTransferData;
int sf = data.regType;
int simm19 = data.processOpData.loadLiteralData.offset;
int rt = data.target;
out += sf * (2^30);
out += simm19*32;
out += rt;
return out;
}
void secondPass(a64inst_instruction instrs[], int numInstrs, st* table, word arr[]){
//TODO:
// iterate over instructions again, this time replacing labels
// with values from symbol table
// after a line has had all the values replaced, assemble it and append
int index = 0;
int lbl = 0;
for (int i=0; i<numInstrs; i++) {
a64inst_instruction cI = instrs[i];
switch (cI.type) {
case a64inst_DPIMMEDIATE:
arr[index] = dpi(cI);
index++;
break;
case a64inst_DPREGISTER:
arr[index] = dpr(cI);
index++;
break;
case a64inst_SINGLETRANSFER:
arr[index] = sts(cI);
index++;
break;
case a64inst_LOADLITERAL:
arr[index] = ldl(cI);
index++;
break;
case a64inst_DIRECTIVE:
arr[index] = cI.data.DirectiveData.value;
index++;
break;
case a64inst_HALT:
arr[index] = 69*(2^25);
index++;
break;
case a64inst_LABEL:
lbl++;
break;
case a64inst_BRANCH:
arr[index] = assembleBranch(&cI, table, lbl);
index++;
default:
break;
}
}
return;
}