arm-asm: Add parse_operand, Operand
tccpp: Allow '#' token to reach the assembler.
This commit is contained in:
parent
a16678e9f3
commit
c5428cd19c
2 changed files with 88 additions and 2 deletions
78
arm-asm.c
78
arm-asm.c
|
@ -35,6 +35,84 @@ ST_FUNC void gen_le32(int c);
|
|||
#define USING_GLOBALS
|
||||
#include "tcc.h"
|
||||
|
||||
enum {
|
||||
OPT_REG32,
|
||||
OPT_REGSET32,
|
||||
OPT_IM8,
|
||||
OPT_IM8N,
|
||||
OPT_IM32,
|
||||
};
|
||||
#define OP_REG32 (1 << OPT_REG32)
|
||||
#define OP_REG (OP_REG32)
|
||||
#define OP_IM32 (1 << OPT_IM32)
|
||||
#define OP_IM8 (1 << OPT_IM8)
|
||||
#define OP_IM8N (1 << OPT_IM8N)
|
||||
#define OP_REGSET32 (1 << OPT_REGSET32)
|
||||
|
||||
typedef struct Operand {
|
||||
uint32_t type;
|
||||
union {
|
||||
uint8_t reg;
|
||||
uint16_t regset;
|
||||
ExprValue e;
|
||||
};
|
||||
} Operand;
|
||||
|
||||
/* Parse a text containing operand and store the result in OP */
|
||||
static void parse_operand(TCCState *s1, Operand *op)
|
||||
{
|
||||
ExprValue e;
|
||||
int8_t reg;
|
||||
uint16_t regset = 0;
|
||||
|
||||
op->type = 0;
|
||||
|
||||
if (tok == '{') { // regset literal
|
||||
next(); // skip '{'
|
||||
while (tok != '}' && tok != TOK_EOF) {
|
||||
reg = asm_parse_regvar(tok);
|
||||
if (reg == -1) {
|
||||
expect("register");
|
||||
return;
|
||||
} else
|
||||
next(); // skip register name
|
||||
|
||||
regset |= 1 << reg;
|
||||
if (tok != ',')
|
||||
break;
|
||||
next(); // skip ','
|
||||
}
|
||||
if (tok != '}')
|
||||
expect("'}'");
|
||||
next(); // skip '}'
|
||||
if (regset == 0) {
|
||||
// ARM instructions don't support empty regset.
|
||||
tcc_error("empty register list is not supported");
|
||||
} else {
|
||||
op->type = OP_REGSET32;
|
||||
op->regset = regset;
|
||||
}
|
||||
} else if (tok == '#' || tok == '$') {
|
||||
/* constant value */
|
||||
next(); // skip '#' or '$'
|
||||
asm_expr(s1, &e);
|
||||
op->type = OP_IM32;
|
||||
op->e = e;
|
||||
if (!op->e.sym) {
|
||||
if ((int) op->e.v < 0 && (int) op->e.v >= -255)
|
||||
op->type = OP_IM8N;
|
||||
else if (op->e.v == (uint8_t)op->e.v)
|
||||
op->type = OP_IM8;
|
||||
} else
|
||||
expect("constant");
|
||||
} else if ((reg = asm_parse_regvar(tok)) != -1) {
|
||||
next(); // skip register name
|
||||
op->type = OP_REG32;
|
||||
op->reg = (uint8_t) reg;
|
||||
} else
|
||||
expect("operand");
|
||||
}
|
||||
|
||||
/* XXX: make it faster ? */
|
||||
ST_FUNC void g(int c)
|
||||
{
|
||||
|
|
12
tccpp.c
12
tccpp.c
|
@ -1009,8 +1009,13 @@ redo_start:
|
|||
goto redo_start;
|
||||
else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
||||
p = parse_line_comment(p - 1);
|
||||
} else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
||||
}
|
||||
#if !defined(TCC_TARGET_ARM)
|
||||
else if (parse_flags & PARSE_FLAG_ASM_FILE)
|
||||
p = parse_line_comment(p - 1);
|
||||
#else
|
||||
/* ARM assembly uses '#' for constants */
|
||||
#endif
|
||||
break;
|
||||
_default:
|
||||
default:
|
||||
|
@ -2703,10 +2708,13 @@ maybe_newline:
|
|||
p++;
|
||||
tok = TOK_TWOSHARPS;
|
||||
} else {
|
||||
#if !defined(TCC_TARGET_ARM)
|
||||
if (parse_flags & PARSE_FLAG_ASM_FILE) {
|
||||
p = parse_line_comment(p - 1);
|
||||
goto redo_no_start;
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
tok = '#';
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue