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…
	
	Add table
		
		Reference in a new issue