void SourceAssembler::emit_data(OperandSize size, const Constant& cst, int dups, const char* name) { GUARANTEE(!GenerateInlineAsm, "No inline data in inline asm"); if (!GenerateGNUCode) { if (name != 0) { emit("\n\tPUBLIC %s%s\n", extern_c_prefix(), name); } if (cst.is_reference()) { emit("\tEXTERNDEF %s%s:PROC\n", extern_c_prefix(), cst.reference()); } if (name != 0) { emit("%s%s ", extern_c_prefix(), name); } switch (size) { case byte_operand : emit("\tdb \t"); break; case word_operand : emit("\tdw \t"); break; case long_operand : emit("\tdd \t"); break; case very_long_operand : emit("\tdq \t"); break; case very_very_long_operand : emit("\tdt \t"); break; default : SHOULD_NOT_REACH_HERE(); } if (dups > 1) { emit("%d\tdup\t(", dups); emit_constant(cst); emit(")"); } else { emit_constant(cst); } emit("\n"); } else { if (name != 0) { emit("\n\t.global %s%s\n", extern_c_prefix(), name); } if (cst.is_reference()) { emit("\t.extern %s%s\n", extern_c_prefix(), cst.reference()); } if (name != 0) { emit("%s%s: ", extern_c_prefix(), name); } if (dups > 1) { emit(".rept %d\n\t", dups); } switch (size) { case byte_operand : emit("\t.byte \t"); break; case word_operand : emit("\t.word \t"); break; case long_operand : emit("\t.long \t"); break; case very_long_operand : emit("\tdq \t"); break; case very_very_long_operand : emit("\tdt \t"); break; default : SHOULD_NOT_REACH_HERE(); } emit_constant_displacement(cst); if (dups > 1) emit("\n\t.endr"); emit("\n"); } }
static rsexp compile (RState* r, rsexp expr, rsexp next) { rsexp code; r_gc_scope_open (r); if (r_symbol_p (expr)) { code = emit_refer (r, expr, next); goto exit; } if (!r_pair_p (expr)) { code = emit_constant (r, expr, next); goto exit; } if (form_eq_p (r, R_QUOTE, expr)) { code = compile_quotation (r, expr, next); goto exit; } if (form_eq_p (r, R_DEFINE, expr)) { code = compile_definition (r, expr, next); goto exit; } if (form_eq_p (r, R_SET_X, expr)) { code = compile_assignment (r, expr, next); goto exit; } if (form_eq_p (r, R_IF, expr)) { code = compile_conditional (r, expr, next); goto exit; } if (form_eq_p (r, R_LAMBDA, expr)) { code = compile_lambda (r, expr, next); goto exit; } if (form_eq_p (r, R_CALL_CC, expr)) { code = compile_call_cc (r, expr, next); goto exit; } code = compile_application (r, expr, next); exit: r_gc_scope_close_and_protect (r, code); return code; }
void SourceAssembler::emit_instruction(const char* format, va_list arguments) { // Due to a peculiarity in the Microsoft SourceAssembler we have to // make a special case out of jumps and calls. Try figuring out if // it's either of them. const bool jump_or_call = (strncmp(format, "jmp", 3) == 0) || (strncmp(format, "call", 4) == 0); const bool loop = (strncmp(format, "loop", 4) == 0); const bool is_int3 = (strncmp(format, "int 3", 5) == 0); const bool has_cl = (strlen(format) > 10 && strncmp(format+10, "cl", 2) == 0); if (!GenerateGNUCode) { bool has_externals = emit_externals(format, arguments); emit("\t"); if (GenerateInlineAsm) emit("__asm "); while (*format) { if (*format == '%') { format++; // Parse the size specifier. OperandSize size = long_operand; switch (*format) { case 't' : size = very_very_long_operand; format++; break; case 'v' : size = very_long_operand; format++; break; case 'l' : size = long_operand; format++; break; case 'w' : size = word_operand; format++; break; case 'b' : size = byte_operand; format++; break; } switch (*format) { case 'c' : { // Constant const Constant* cst = va_arg(arguments, const Constant *); if (!cst->is_immediate() && !jump_or_call) { emit("offset "); } emit_constant(*cst); break; } case 'a' : { // Address. const Address* adr = va_arg(arguments, const Address *); emit_address(*adr, size); break; } case 'r' : { // Register. const Register* reg = va_arg(arguments, const Register *); emit_register(*reg, size); break; } } } else {
static rsexp compile_quotation (RState* r, rsexp expr, rsexp next) { rsexp code; if (!validate_quotation (r, expr)) return R_FAILURE; r_gc_scope_open (r); ensure_or_goto (code = emit_constant (r, r_cadr (expr), next), exit); exit: r_gc_scope_close_and_protect (r, code); return code; }
void SourceAssembler::jcc(Condition condition, const Constant& cst) { if (cst.is_reference()) { if (!GenerateGNUCode) if (!GenerateInlineAsm) emit("\tEXTERNDEF %s%s:PROC\n", extern_c_prefix(), cst.reference()); else emit("\t{\n\textern void %s();\n", cst.reference()); else emit("\t.extern %s%s\n", extern_c_prefix(), cst.reference()); } if (!GenerateInlineAsm) emit("\tj"); else emit("\t__asm j"); emit_cc(condition); emit(" "); emit_constant(cst); emit("\n"); if (GenerateInlineAsm && cst.is_reference()) emit("\t}\n"); }
static void string() { emit_constant(OBJ_VAL(copy_string(parser.previous.start + 1, parser.previous.length - 2))); }
static void double_number(void) { // Rewrite to be faster and take the underscores! double value = strtod(parser.previous.start, NULL); emit_constant(FLOAT_VAL(value)); }
static void integer_number(void) { uint64_t number = parse_uint64(parser.previous.start, parser.previous.length); emit_constant(INT_VAL((int64_t)number)); }