Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/rars/ProgramStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,15 @@ public void buildBasicStatementFromBasicInstruction(ErrorList errors) {
}
boolean absoluteAddress = true; // (used below)

if (i + 2 < strippedTokenList.size()) { // support label+integer
Token op = strippedTokenList.get(i + 1);
Token offset = strippedTokenList.get(i + 2);
if (op.getType() == TokenTypes.PLUS && TokenTypes.isIntegerTokenType(offset.getType())) {
address = address + Integer.parseInt(offset.getValue());
i = i + 2;
}
}

if (instruction instanceof BasicInstruction) {
BasicInstructionFormat format = ((BasicInstruction) instruction).getInstructionFormat();
if (format == BasicInstructionFormat.B_FORMAT) {
Expand Down
38 changes: 27 additions & 11 deletions src/rars/assembler/Assembler.java
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,7 @@ private void storeNumeric(TokenList tokens, Directives directive, ErrorList erro
}
for (int i = 0; i < repetitions; i++) {
if (Directives.isIntegerDirective(directive)) {
storeInteger(valueToken, directive, errors);
storeInteger(valueToken, directive, 0, errors);
} else {
storeRealNumber(valueToken, directive, errors);
}
Expand All @@ -928,10 +928,24 @@ private void storeNumeric(TokenList tokens, Directives directive, ErrorList erro
// if not in ".word w : n" format, must just be list of one or more values.
for (int i = tokenStart; i < tokens.size(); i++) {
token = tokens.get(i);
int offset = 0;
while (i + 2 < tokens.size() // support for label+integer
&& tokens.get(i+1).getType() == TokenTypes.PLUS) {
Token offsetToken = tokens.get(i+2);
if (TokenTypes.isIntegerTokenType(offsetToken.getType())) {
offset = offset + Integer.parseInt(offsetToken.getValue());
} else {
errors.add(new ErrorMessage(fileCurrentlyBeingAssembled, offsetToken.getSourceLine(), offsetToken.getStartPos(), "Only integers can be used as offsets"));
}
i = i + 2;
}
if (Directives.isIntegerDirective(directive)) {
storeInteger(token, directive, errors);
storeInteger(token, directive, offset, errors);
}
if (Directives.isFloatingDirective(directive)) {
if (offset != 0) {
errors.add(new ErrorMessage(fileCurrentlyBeingAssembled, token.getSourceLine(), token.getStartPos(), "Offsets are not supported for floating point values"));
}
storeRealNumber(token, directive, errors);
}
}
Expand All @@ -942,21 +956,21 @@ private void storeNumeric(TokenList tokens, Directives directive, ErrorList erro
// Called by storeNumeric()
// NOTE: The token itself may be a label, in which case the correct action is
// to store the address of that label (into however many bytes specified).
private void storeInteger(Token token, Directives directive, ErrorList errors) {
private void storeInteger(Token token, Directives directive, int offset, ErrorList errors) {
int lengthInBytes = DataTypes.getLengthInBytes(directive);
if (TokenTypes.isIntegerTokenType(token.getType())) {
int value;
long longvalue;
if (TokenTypes.INTEGER_64 == token.getType()) {
longvalue = Binary.stringToLong(token.getValue());
longvalue = Binary.stringToLong(token.getValue()) + offset;
value = (int)longvalue;
if (directive != Directives.DWORD){
errors.add(new ErrorMessage(ErrorMessage.WARNING, token.getSourceProgram(), token.getSourceLine(),
token.getStartPos(), "value " + Binary.longToHexString(longvalue)
+ " is out-of-range and truncated to " + Binary.intToHexString(value)));
}
}else{
value = Binary.stringToInt(token.getValue());
value = Binary.stringToInt(token.getValue()) + offset;
longvalue = value;
}

Expand Down Expand Up @@ -1019,9 +1033,9 @@ else if (token.getType() == TokenTypes.IDENTIFIER) {
if (value == SymbolTable.NOT_FOUND) {
// Record value 0 for now, then set up backpatch entry
int dataAddress = writeToDataSegment(0, lengthInBytes, token, errors);
currentFileDataSegmentForwardReferences.add(dataAddress, lengthInBytes, token);
currentFileDataSegmentForwardReferences.add(dataAddress, lengthInBytes, token, offset);
} else { // label already defined, so write its address
writeToDataSegment(value, lengthInBytes, token, errors);
writeToDataSegment(value + offset, lengthInBytes, token, errors);
}
} // Data segment check done previously, so this "else" will not be.
// See 11/20/06 note above.
Expand Down Expand Up @@ -1312,8 +1326,8 @@ private int size() {
// - memory address to receive the label's address once resolved
// - number of address bytes to store (1 for .byte, 2 for .half, 4 for .word)
// - the label's token. All its information will be needed if error message generated.
private void add(int patchAddress, int length, Token token) {
forwardReferenceList.add(new DataSegmentForwardReference(patchAddress, length, token));
private void add(int patchAddress, int length, Token token, int offset) {
forwardReferenceList.add(new DataSegmentForwardReference(patchAddress, length, token, offset));
}

// Add the entries of another DataSegmentForwardReferences object to this one.
Expand Down Expand Up @@ -1344,7 +1358,7 @@ private void resolve(SymbolTable localSymtab) {
if (labelAddress != SymbolTable.NOT_FOUND) {
// patch address has to be valid b/c we already stored there...
try {
Globals.memory.set(entry.patchAddress, labelAddress, entry.length);
Globals.memory.set(entry.patchAddress, labelAddress + entry.offset, entry.length);
} catch (AddressErrorException aee) {
}
forwardReferenceList.remove(i);
Expand All @@ -1368,11 +1382,13 @@ private class DataSegmentForwardReference {
int patchAddress;
int length;
Token token;
int offset;

DataSegmentForwardReference(int patchAddress, int length, Token token) {
DataSegmentForwardReference(int patchAddress, int length, Token token, int offset) {
this.patchAddress = patchAddress;
this.length = length;
this.token = token;
this.offset = offset;
}
}

Expand Down
13 changes: 12 additions & 1 deletion src/rars/assembler/OperandFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,22 @@ static Instruction bestOperandMatch(TokenList tokenList, ArrayList<Instruction>
private static boolean numOperandsCheck(TokenList cand, Instruction spec, ErrorList errors) {
int numOperands = cand.size() - 1;
int reqNumOperands = spec.getTokenList().size() - 1;
int i = 1;
while (i < cand.size()) { // support labal+integer, count these 3 tokens as 1
if (cand.get(i).getType() == TokenTypes.IDENTIFIER && i + 2 < cand.size()) {
Token op = cand.get(i + 1);
Token offset = cand.get(i + 2);
if (op.getType() == TokenTypes.PLUS && TokenTypes.isIntegerTokenType(offset.getType())) {
numOperands = numOperands - (3 - 1);
i = i + 2; // skip the next two tokens
}
}
i = i + 1;
}
Token operator = cand.get(0);
if (numOperands == reqNumOperands) {
return true;
} else if (numOperands < reqNumOperands) {

String mess = "Too few or incorrectly formatted operands. Expected: " + spec.getExampleFormat();
generateMessage(operator, mess, errors);
} else {
Expand Down
20 changes: 20 additions & 0 deletions test/label_plus1.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#stdout:cdef
#exit:42
.data
data:
.string "abcdef"
ptr:
.word data
.word 2+3+4

.text
#li a3, 4+4

li a7, 4 # PrintString
la a0, data+2
ecall

ok:
li a7, 93 # Exit2
li a0, 42
ecall
31 changes: 31 additions & 0 deletions test/label_plus2.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#stdout:cdef
#exit:42
.data
data:
.string "abcdef"
ptr:
.word data+3
# .word 2+3+4 # This is not supported because of limitations of the tokenizer. Since commas are optional and unary minus and plus are supported, "3" "+" "3" is ambigous with "3" "+3"

.text

li a7, 4 # PrintString
la a0, data+2
ecall

lw t0, ptr
la a0, data+3
bne t0, a0, fail
lb t1, 0(t0)
li t2, 'd'
beq t1, t2, ok

fail:
li a7, 93 # Exit2
li a0, 1
ecall

ok:
li a7, 93 # Exit2
li a0, 42
ecall
35 changes: 35 additions & 0 deletions test/label_plus3.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#stdout:fghi
#exit:42
.data
ptr_fwd:
.word data+5
data:
.string "abcdefghi"
ptr:
.word data+3

.text

li a7, 4 # PrintString
lw a0, ptr_fwd
ecall

lw t0, ptr
la a0, data+3
bne t0, a0, fail
lw t0, ptr_fwd
la a0, data+5
bne t0, a0, fail
lb t1, 0(t0)
li t2, 'f'
beq t1, t2, ok

fail:
li a7, 93 # Exit2
li a0, 1
ecall

ok:
li a7, 93 # Exit2
li a0, 42
ecall