Skip to content

Commit

Permalink
Add .aligna (align absolute) directive.
Browse files Browse the repository at this point in the history
  • Loading branch information
Prof9 committed May 31, 2019
1 parent 104b5a9 commit 58700a8
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 22 deletions.
2 changes: 1 addition & 1 deletion Archs/ARM/ArmParser.cpp
Expand Up @@ -46,7 +46,7 @@ std::unique_ptr<CAssemblerCommand> parseDirectiveArm(Parser& parser, int flags)
std::unique_ptr<CAssemblerCommand> parseDirectivePool(Parser& parser, int flags)
{
auto seq = make_unique<CommandSequence>();
seq->addCommand(make_unique<CDirectiveAlignFill>(4,CDirectiveAlignFill::Align));
seq->addCommand(make_unique<CDirectiveAlignFill>(4,CDirectiveAlignFill::AlignVirtual));
seq->addCommand(make_unique<ArmPoolCommand>());

return std::move(seq);
Expand Down
26 changes: 17 additions & 9 deletions Commands/CDirectiveFile.cpp
Expand Up @@ -320,20 +320,24 @@ bool CDirectiveAlignFill::Validate()
}
}

if (mode != Fill && isPowerOfTwo(value) == false)
{
Logger::queueError(Logger::Error, L"Invalid alignment %d", value);
return false;
}

int64_t oldSize = finalSize;
int64_t mod;
switch (mode)
{
case Align:
if (isPowerOfTwo(value) == false)
{
Logger::queueError(Logger::Error,L"Invalid alignment %d",value);
return false;
}

case AlignVirtual:
mod = g_fileManager->getVirtualAddress() % value;
finalSize = mod ? value-mod : 0;
break;
case AlignPhysical:
mod = g_fileManager->getPhysicalAddress() % value;
finalSize = mod ? value-mod : 0;
break;
case Fill:
finalSize = value;
break;
Expand Down Expand Up @@ -375,9 +379,12 @@ void CDirectiveAlignFill::writeTempData(TempData& tempData) const
{
switch (mode)
{
case Align:
case AlignVirtual:
tempData.writeLine(virtualAddress,formatString(L".align 0x%08X",value));
break;
case AlignPhysical:
tempData.writeLine(virtualAddress, formatString(L".aligna 0x%08X", value));
break;
case Fill:
tempData.writeLine(virtualAddress,formatString(L".fill 0x%08X,0x%02X",value,fillByte));
break;
Expand All @@ -388,7 +395,8 @@ void CDirectiveAlignFill::writeSymData(SymbolData& symData) const
{
switch (mode)
{
case Align: // ?
case AlignVirtual: // ?
case AlignPhysical: // ?
break;
case Fill:
symData.addData(virtualAddress,value,SymbolData::Data8);
Expand Down
2 changes: 1 addition & 1 deletion Commands/CDirectiveFile.h
Expand Up @@ -69,7 +69,7 @@ class CDirectiveIncbin: public CAssemblerCommand
class CDirectiveAlignFill: public CAssemblerCommand
{
public:
enum Mode { Align, Fill };
enum Mode { AlignPhysical, AlignVirtual, Fill };

CDirectiveAlignFill(int64_t value, Mode mode);
CDirectiveAlignFill(Expression& value, Mode mode);
Expand Down
18 changes: 11 additions & 7 deletions Parser/DirectivesParser.cpp
Expand Up @@ -122,17 +122,20 @@ std::unique_ptr<CAssemblerCommand> parseDirectiveAlignFill(Parser& parser, int f
CDirectiveAlignFill::Mode mode;
switch (flags & DIRECTIVE_USERMASK)
{
case DIRECTIVE_FILE_ALIGN:
mode = CDirectiveAlignFill::Align;
case DIRECTIVE_ALIGN_VIRTUAL:
mode = CDirectiveAlignFill::AlignVirtual;
break;
case DIRECTIVE_FILE_FILL:
case DIRECTIVE_ALIGN_PHYSICAL:
mode = CDirectiveAlignFill::AlignPhysical;
break;
case DIRECTIVE_ALIGN_FILL:
mode = CDirectiveAlignFill::Fill;
break;
default:
return nullptr;
}

if (mode == CDirectiveAlignFill::Align && parser.peekToken().type == TokenType::Separator)
if (mode != CDirectiveAlignFill::Fill && parser.peekToken().type == TokenType::Separator)
return make_unique<CDirectiveAlignFill>(UINT64_C(4),mode);

std::vector<Expression> list;
Expand Down Expand Up @@ -674,9 +677,10 @@ const DirectiveMap directives = {
{ L".orga", { &parseDirectivePosition, DIRECTIVE_POS_PHYSICAL } },
{ L"orga", { &parseDirectivePosition, DIRECTIVE_POS_PHYSICAL } },
{ L".headersize", { &parseDirectiveHeaderSize, 0 } },
{ L".align", { &parseDirectiveAlignFill, DIRECTIVE_FILE_ALIGN } },
{ L".fill", { &parseDirectiveAlignFill, DIRECTIVE_FILE_FILL } },
{ L"defs", { &parseDirectiveAlignFill, DIRECTIVE_FILE_FILL } },
{ L".align", { &parseDirectiveAlignFill, DIRECTIVE_ALIGN_VIRTUAL } },
{ L".aligna", { &parseDirectiveAlignFill, DIRECTIVE_ALIGN_PHYSICAL } },
{ L".fill", { &parseDirectiveAlignFill, DIRECTIVE_ALIGN_FILL } },
{ L"defs", { &parseDirectiveAlignFill, DIRECTIVE_ALIGN_FILL } },
{ L".skip", { &parseDirectiveSkip, 0 } },

{ L".if", { &parseDirectiveConditional, DIRECTIVE_COND_IF } },
Expand Down
5 changes: 3 additions & 2 deletions Parser/DirectivesParser.h
Expand Up @@ -27,8 +27,9 @@ using DirectiveMap = std::unordered_multimap<std::wstring, const DirectiveEntry>
// file directive flags
#define DIRECTIVE_POS_PHYSICAL 0x00000001
#define DIRECTIVE_POS_VIRTUAL 0x00000002
#define DIRECTIVE_FILE_ALIGN 0x00000001
#define DIRECTIVE_FILE_FILL 0x00000002
#define DIRECTIVE_ALIGN_PHYSICAL 0x00000001
#define DIRECTIVE_ALIGN_VIRTUAL 0x00000002
#define DIRECTIVE_ALIGN_FILL 0x00000004

// conditional directive flags
#define DIRECTIVE_COND_IF 0x00000001
Expand Down
5 changes: 3 additions & 2 deletions Readme.md
Expand Up @@ -470,10 +470,11 @@ The following values are supported:
### Align the output position

```
.align [num[,value]]
.align [num[,value]]
.aligna [num[,value]]
```

Writes bytes of `value` into the output file until the memory position is a multiple of `num`. `num` has to be a power of two. If `num` isn't specified, then the alignment will be 4. If `value` isn't specified, zeros are inserted. Only the lowest 8 bits of `value` are inserted.
Writes bytes of `value` into the output file until the memory position is a multiple of `num`. `num` has to be a power of two. If `num` isn't specified, then the alignment will be 4. If `value` isn't specified, zeros are inserted. Only the lowest 8 bits of `value` are inserted. `.align` aligns the memory address (i.e. `org()`), whereas `.aligna` aligns the file address (i.e. `orga()`).

### Fill space with a value

Expand Down

0 comments on commit 58700a8

Please sign in to comment.