Index: gcc/config.gcc =================================================================== --- gcc/config.gcc +++ gcc/config.gcc 2004-05-14 13:05:00.205641720 -0300 @@ -300,6 +300,9 @@ cpu_type=i386 extra_headers="mmintrin.h xmmintrin.h emmintrin.h pmmintrin.h" ;; +i86-*-*) + cpu_type=i86 + ;; x86_64-*-*) cpu_type=i386 extra_headers="mmintrin.h xmmintrin.h emmintrin.h pmmintrin.h" @@ -1179,6 +1182,9 @@ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h i386/linux.h" tmake_file="t-slibgcc-elf-ver t-linux i386/t-crtstuff" ;; +i86-*) # Intel 8086's running GNU/Linux + extra_parts="" + ;; x86_64-*-linux*) tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h svr4.h linux.h \ i386/x86-64.h i386/linux64.h" Index: gcc/main.c =================================================================== --- gcc/main.c +++ gcc/main.c 2004-05-14 13:05:02.254330272 -0300 @@ -20,6 +20,7 @@ #include "config.h" #include "system.h" #include "toplev.h" +#include "expr.h" int main PARAMS ((int argc, char **argv)); Index: gcc/config/i86/i86.c =================================================================== --- gcc/config/i86/i86.c +++ gcc/config/i86/i86.c 2004-05-14 13:05:00.197642936 -0300 @@ -0,0 +1,366 @@ + +#include "config.h" +#include "system.h" +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "insn-config.h" +#include "conditions.h" +#include "insn-flags.h" +#include "output.h" +#include "insn-attr.h" +#include "tree.h" +#include "flags.h" +#include "function.h" +#include "target.h" +#include "target-def.h" +#include "expr.h" +#include "output.h" + +int i86_function_prolog(FILE *file, int size); +int i86_function_epilog(FILE *file, int size); + +#define TARGET_ASM_FUNCTION_PROLOGUE i86_function_prolog +#define TARGET_ASM_FUNCTION_EPILOGUE i86_function_epilog + +void i86_globalize_label PARAMS ((FILE *stream, const char *name)); + +#define TARGET_ASM_GLOBALIZE_LABEL i86_globalize_label +#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section + +enum reg_class regclass_map[] = { AREG, DREG, CREG, BREG, + SIREG, DIREG, BPREG, GENERAL_REGS }; + +static char *register_names[] = REGISTER_NAMES; + + +struct gcc_target targetm = TARGET_INITIALIZER; + +int +i86_reg_class_from_letter(c) +{ + switch (c) + { + case 'a': return AREG; + case 'b': return BREG; + case 'c': return CREG; + case 'd': return DREG; + case 'S': return SIREG; + case 'D': return DIREG; + case 'B': return BPREG; + case 'r': return GENERAL_REGS; + case 'q': return Q_REGS; + } + return NO_REGS; +} + +i86_const_ok_for_letter_p(v,c) +{ + switch (c) + { + case 'I': + /* The constant that we can shift by: shl ax,1 */ + return v == 1; + case 'J': + /* I/O ports and byte registers */ + return v >= 0 && v <= 255; + } + return 0; +} + +/* The purpose of this function is to decide if "x" represents + an addressing mode that the assembler can handle directly. If + not, gcc will simplify it. + +*/ + +#define DEBUG 0 + +static char packreg[] = "gggbiibs"; +char * +pack_rtx(r, buf, ebuf, strict) + rtx r; + char *buf, *ebuf; +{ + rtx x0, x1; + if (buf >= ebuf) + return buf; + switch (GET_CODE(r)) + { + case PLUS: + *buf++ = '+'; + buf = pack_rtx(XEXP(r,0), buf, ebuf, strict); + buf = pack_rtx(XEXP(r,1), buf, ebuf, strict); + break; + case MEM: + *buf++ = 'm'; + buf = pack_rtx(XEXP(r,0), buf, ebuf, strict); + break; + case PRE_DEC: + *buf++ = '<'; + buf = pack_rtx(XEXP(r,0), buf, ebuf, strict); + break; + case REG: + if (strict || REGNO(r)= FIRST_PSEUDO_REGISTER ? '?' : packreg[REGNO(r)]; + else + *buf++ = 'p'; + break; + case CONST: + case CONST_INT: + case SYMBOL_REF: + *buf++ = '#'; + break; + default: + *buf++ = '?'; + break; + } + return buf; +} + +static char *valid_addr_list[] = { + "#", + "b", + "i", + "p", + "+bi", + "+ib", + "+pi", + "+ip", + "+pb", + "+bp", + "+pp", + "+b#", + "+i#", + "+p#", + "++bi#", + "++ib#", + "++pi#", + "++ip#", + "++pb#", + "++bp#", + "++pp#", + "= 0; regno--) + if (regs_ever_live[regno] && ! call_used_regs[regno]) + fprintf(file, "\tpush\t%%%s\n", register_names[regno]); + fprintf(file, "\n"); +} + +i86_function_epilog(file, size) + FILE *file; + int size; +{ + int regno; + fprintf(file, "\n"); + + for (regno = 0; regno <= 5; regno++) + if (regs_ever_live[regno] && ! call_used_regs[regno]) + fprintf(file, "\tpop\t%%%s\n", register_names[regno]); + + fprintf(file, "\tleave\n"); + fprintf(file, "\tret\n\n"); +} + +#undef DEBUG +#define DEBUG 1 + +i86_print_operand(s,x,c) + FILE *s; + rtx x; + int c; +{ + rtx x0; +#if DEBUG + printf("[i86_print_operand(%c)]\n", c?c:' '); + print_rtl(stdout, x); + printf("\n"); +#endif + switch (GET_CODE (x)) + { + case REG: + if ((c == 'L' || c == 'H') && REGNO(x) <= 4) + fprintf (s, "%%%c%c", register_names[REGNO(x)][0], c-'L'+'l'); + else + fprintf (s, "%%%s", register_names[REGNO(x)]); + break; + case MEM: + if (c == 'P') + i86_print_operand(s, XEXP(x,0), 0); + else + output_address(x); + break; + case PLUS: + i86_print_operand(s, XEXP(x,0),' '); + if (GET_CODE(XEXP(x,1)) == CONST_INT) + { + fprintf(s, "%+d", INTVAL(XEXP(x,1))); + } else { + fputc('+',s); + i86_print_operand(s, XEXP(x,1), ' '); + } + break; + case SYMBOL_REF: + assemble_name(s, XSTR(x,0)); + break; + case CONST: + case CONST_INT: + fprintf(s,"$0x%x",INTVAL(x)); + break; + case CODE_LABEL: + output_addr_const(s, x); + break; + default: + printf("blah! default in i86_print_operand %d\n", GET_CODE(x)); + break; + } +} + +i86_print_operand_address(s,x) + FILE *s; + rtx x; +{ +// putc('[', s); +#if DEBUG + printf("[i86_print_oper_addr]\n"); + print_rtl(stdout, x); + printf("\n"); +#endif + rtx addr = XEXP(x,0); + switch (GET_CODE(addr)) { + case PLUS: + if (GET_CODE(XEXP(addr,1)) == CONST_INT) + { + fprintf(s, "%d", INTVAL(XEXP(addr,1))); + } + fputc('(',s); + i86_print_operand(s, XEXP(addr,0),' '); + fputc(')',s); + break; + default: + fputc('(',s); + i86_print_operand(s, addr,' '); + fputc(')',s); + break; + } +// putc(']', s); +} + +void +i86_globalize_label(stream,name) + FILE * stream; + const char *name; +{ + fputs ("\n\t.globl\t", stream); + assemble_name (stream, name); + fputs ("\n", stream); +} + Index: gcc/config/i86/i86.h =================================================================== --- gcc/config/i86/i86.h +++ gcc/config/i86/i86.h 2004-05-14 13:05:00.199642632 -0300 @@ -0,0 +1,331 @@ +/* +** DJ's 16-bit Intel i86 attempt +*/ + +/* Run-time Target Specification */ + +#include "machmode.h" + +#define CPP_PREDEFINES "-Di86 -Dmsdos" + +extern int target_flags; + +#define TARGET_VERSION fprintf(stderr, " (i86, DOS, DJ)"); +#define TARGET_SWITCHES \ +{ SUBTARGET_SWITCHES \ + { "", 0 }} + +/* +#define TARGET_OPTIONS \ +{ { "something", &something }, \ + SUBTARGET_OPTIONS \ +} + */ +#define SUBTARGET_SWITCHES +#define SUBTARGET_OPTIONS + +/* Storage Layout */ + +#define BITS_BIG_ENDIAN 0 +#define BYTES_BIG_ENDIAN 0 +#define WORDS_BIG_ENDIAN 0 +#define FLOAT_WORDS_BIG_ENDIAN 0 +#define BITS_PER_WORD 16 +#define UNITS_PER_WORD 2 +#define POINTER_SIZE 16 +#define PARM_BOUNDARY 16 +#define STACK_BOUNDARY 16 +#define FUNCTION_BOUNDARY 1 +#define BIGGEST_ALIGNMENT 8 +#define EMPTY_FIELD_BOUNDARY 8 +#define STRICT_ALIGNMENT 0 + +/* Layout of Source Language Data Types */ + +#define INT_TYPE_SIZE 16 +#define SHORT_TYPE_SIZE 16 +#define LONG_TYPE_SIZE 32 +#define LONG_LONG_TYPE_SIZE 64 +#define FLOAT_TYPE_SIZE 32 +#define DOUBLE_TYPE_SIZE 64 +#define CHAR_TYPE_SIZE 8 +#define DEFAULT_SIGNED_CHAR 1 +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" + + +/* Modes */ + +#define CASE_VECTOR_MODE HImode +#define MOVE_MAX 2 +#define Pmode HImode +#define FUNCTION_MODE QImode + +#if 0 +#define TARGET_BELL 7 +#define TARGET_BS 8 +#define TARGET_TAB 9 +#define TARGET_NEWLINE 10 +#define TARGET_VT 11 +#define TARGET_FF 12 +#define TARGET_CR 13 +#endif + +/* Registers */ + +/* ax dx cx bx si di bp sp */ +/* 0 1 2 3 4 5 6 7 */ + +/* Register Basics */ +#define FIRST_PSEUDO_REGISTER 8 +#define FIXED_REGISTERS { 0, 0, 0, 0, 0, 0, 0, 1 } +#define CALL_USED_REGISTERS { 1, 1, 1, 0, 0, 0, 0, 1 } + +/* Order of Allocation of Registers */ +#define REG_ALLOC_ORDER { 0, 1, 2, 3, 4, 5, 6, 7 } + +/* How Values Fit in Registers */ +#define HARD_REGNO_NREGS(REGNO, MODE) ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) +#define HARD_REGNO_MODE_OK(REGNO, MODE) ((REGNO) < 4 ? 1 : (int) (MODE) != (int) QImode) +#define MODES_TIEABLE_P(MODE1, MODE2) ((MODE1) == (MODE2)) + +/* Register Classes */ + +#define SMALL_REGISTER_CLASSES 1 + +enum reg_class +{ + NO_REGS, + AREG, DREG, CREG, BREG, + SIREG, DIREG, BPREG, + AD_REGS, /* %ax/%dx for DImode */ + Q_REGS, /* %ax %bx %cx %dx */ + INDEX_REGS, /* %si %di */ + BASE_REGS, /* %bx %bp */ + GENERAL_REGS, /* %ax %bx %cx %dx %si %di */ + ALL_REGS, LIM_REG_CLASSES +}; + +#define N_REG_CLASSES (int)LIM_REG_CLASSES + +#define REG_CLASS_NAMES \ +{ "NO_REGS", \ + "AREG", "DREG", "CREG", "BREG", \ + "SIREG", "DIREG", "BPREG", \ + "AD_REGS", \ + "Q_REGS", \ + "INDEX_REGS", \ + "BASE_REGS", \ + "GENERAL_REGS", \ + "ALL_REGS" } + +#define REG_CLASS_CONTENTS \ +{ 0x00, \ + 0x01, 0x02, 0x04, 0x08, \ + 0x10, 0x20, 0x40, \ + 0x03, \ + 0x0f, \ + 0x30, \ + 0x48, \ + 0xff, \ + 0xff \ +}; + +#define CLASS_LIKELY_SPILLED_P(CLASS) 0 + +extern enum reg_class regclass_map[]; /* smallest class containing REGNO */ +#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO]) + +#define BASE_REG_CLASS BASE_REGS +#define INDEX_REG_CLASS INDEX_REGS + +#define REG_CLASS_FROM_LETTER(c) i86_reg_class_from_letter(c) + +#define REGNO_OK_FOR_BASE_P(num) ((num) == 3 || (num) == 6) +#define REGNO_OK_FOR_INDEX_P(num) ((num) == 4 || (num) == 5) +#define PREFERRED_RELOAD_CLASS(X,CLASS) (GET_MODE(X) == QImode && !((CLASS)==AREG||(CLASS)==BREG||(CLASS)==CREG||(CLASS)==DREG||(CLASS)==AD_REGS) ? Q_REGS : (CLASS)) +#define LIMIT_RELOAD_CLASS(MODE, CLASS) \ +((MODE) == QImode && ((CLASS) == ALL_REGS || (CLASS) == GENERAL_REGS) \ +? Q_REGS : (CLASS)) +#define CLASS_MAX_NREGS(CLASS, MODE) \ +((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +#define CONST_OK_FOR_LETTER_P(v, c) i86_const_ok_for_letter_p(v,c) +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 + +/* Basic Stack Layout */ + +/* Frame Layout */ +#define STACK_GROWS_DOWNWARD 1 +#define FRAME_GROWS_DOWNWARD 1 +#define STARTING_FRAME_OFFSET 0 +#define FIRST_PARM_OFFSET(f) 2 + +/* Registers That Address the Stack Frame */ +#define STACK_POINTER_REGNUM 7 +#define FRAME_POINTER_REGNUM 6 +#define ARG_POINTER_REGNUM 6 + +/* Elimination */ +#define FRAME_POINTER_REQUIRED 1 +#define INITIAL_FRAME_POINTER_OFFSET(x) 0 + +/* Passing Function Arguments on the Stack */ +#define PROMOTE_PROTOTYPES 1 +#define PUSH_ROUNDING(n) (((n)+1)&(-2)) +#define RETURN_POPS_ARGS(d,t,s) 0 + +/* Passing Arguments in Registers */ +#define FUNCTION_ARG(c,m,t,n) 0 +#define FUNCTION_ARG_PARTIAL_NREGS(c,m,t,n) 0 +#define FUNCTION_ARG_PASS_BY_REFERENCE(c,m,y,n) 0 +#define CUMULATIVE_ARGS int +#define INIT_CUMULATIVE_ARGS(c,f,l,i) c = 0 +#define FUNCTION_ARG_ADVANCE(c,m,t,n) +#define FUNCTION_ARG_REGNO_P(r) 0 + +/* How Scalar Function Values Are Returned */ +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx (REG, TYPE_MODE (VALTYPE), 0) +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) +#define LIBCALL_VALUE(MODE) \ + gen_rtx (REG, MODE, 0) + +#define EXIT_IGNORE_STACK 0 + +/* How Large Values Are Returned */ + +#define STRUCT_VALUE 0 +#define STRUCT_VALUE_INCOMING 0 + +/* Addressing Modes */ + +extern int i86_valid_addr PARAMS ((enum machine_mode mode, rtx x, int strict)); + +#define CONSTANT_ADDRESS_P(x) CONSTANT_P(x) +#define MAX_REGS_PER_ADDRESS 2 +#define REG_OK_FOR_BASE_P(x) (REGNO(x) == 3 && REGNO(x) == 6) +#define REG_OK_FOR_INDEX_P(x) (REGNO(x) == 4 && REGNO(x) == 5) +#define LEGITIMIZE_ADDRESS(x,o,m,w) +#define LEGITIMATE_CONSTANT_P(X) 1 + +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ + if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == POST_DEC) goto LABEL + +#ifdef REG_OK_STRICT +#define GO_IF_LEGITIMATE_ADDRESS(m,x,l) { if (i86_valid_addr(m,x,1)) goto l; } +#else +#define GO_IF_LEGITIMATE_ADDRESS(m,x,l) { if (i86_valid_addr(m,x,0)) goto l; } +#endif + +/* Condition Code Status */ + +extern void i86_notice_update_cc PARAMS ((rtx e)); +#define NOTICE_UPDATE_CC(e,i) i86_notice_update_cc(e) + +/* Describing Relative Costs of Operations */ + +#define CONST_COSTS(x,c,o) case CONST_INT: case CONST: case LABEL_REF: case SYMBOL_REF: return 0; case CONST_DOUBLE: return 2; +#define SLOW_BYTE_ACCESS 1 +#define MEMORY_MOVE_COST(m,c,i) 4 +#define NO_FUNCTION_CSE 1 +#define NO_RECURSIVE_FUNCTION_CSE 1 + +/* Misc */ + +#define NO_IMPLICIT_EXTERN_C 1 +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +/* Trampolines */ + +#define INITIALIZE_TRAMPOLINE +#define TRAMPOLINE_SIZE 0 + +/* Dividing the Output into Sections */ +#define TEXT_SECTION_ASM_OP "\t.text" +#define DATA_SECTION_ASM_OP "\t.data" + +/* The Overall Framework of an Assembler file */ + +#define ASM_FILE_START(f) i86_asm_file_start(f) +#define ASM_FILE_END(f) i86_asm_file_end(f) +#define ASM_COMMENT_START "#" +#define ASM_APP_ON "# asm app on\n" +#define ASM_APP_OFF "# asm app off\n" +#define ASM_OUTPUT_SOURCE_FILENAME(f,n) i86_asm_output_source_filename(f,n) +#define ASM_OUTPUT_SOURCE_LINE(f,l) i86_asm_output_source_line(f,l) +#define ASM_OUTPUT_EXTERNAL(f, d, s) i86_asm_output_external(f,d,s) +#define ASM_OUTPUT_EXTERNAL_LIBCALL(f, s) i86_asm_output_external_libcall(f,s) + +/* Output of Data */ + +#define ASM_OUTPUT_INT(f,i) (fprintf(f, "\tdd\t"), output_addr_const(f,(i)), fprintf(f, "\n")) +#define ASM_OUTPUT_SHORT(f,i) (fprintf(f, "\tdw\t"), output_addr_const(f,(i)), fprintf(f, "\n")) +#define ASM_OUTPUT_CHAR(f,i) (fprintf(f, "\tdb\t"), output_addr_const(f,(i)), fprintf(f, "\n")) + +#define ASM_BYTE_OP "db" +#define ASM_SHORT "\tdw" +#define ASM_OUTPUT_BYTE(f,i) fprintf(f, "\t%s\t%d\n", ASM_BYTE_OP, i) + +#define TARGET_ASM_OPEN_PAREN "(" +#define TARGET_ASM_CLOSE_PAREN ")" + +/* Output of Uninitialized Variables */ + +#define ASM_OUTPUT_COMMON(file, NAME, SIZE, ROUNDED) \ +( fputs ("\t.globl ", (file)), \ + assemble_name ((file), (NAME)), \ + fputs ("\n\t# common ", (file)), \ + assemble_name ((file), (NAME)), \ + fprintf ((file), " %u\n", (ROUNDED))) + +#define ASM_OUTPUT_LOCAL(file, NAME, SIZE, ROUNDED) \ +( fputs ("\t# common ", (file)), \ + assemble_name ((file), (NAME)), \ + fprintf ((file), " %u\n", (ROUNDED))) + +#define ASM_OUTPUT_LABEL(file,NAME) \ + (assemble_name (file, NAME), fputs (":\n", file)) + +#define ASM_OUTPUT_LABELREF(file,NAME) fprintf (file, "_%s", NAME) +#define ASM_OUTPUT_INTERNAL_LABEL(file,PREFIX,NUM) \ + fprintf (file, ".%s%d:\n", PREFIX, NUM) +#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \ + sprintf ((BUF), "*.%s%d", (PREFIX), (NUMBER)) +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) + +#define ASM_OUTPUT_ADDR_VEC_ELT(s,v) fprintf (s, "\tdw L%d\n", v) + +/* Output of Assembler Instructions */ + +#define REGISTER_NAMES {"ax", "dx", "cx", "bx", "si", "di", "bp", "sp"} + +#define PRINT_OPERAND(s,x,c) i86_print_operand(s,x,c) +#define PRINT_OPERAND_ADDRESS(s,x) i86_print_operand_address(s,x) + +#define ASM_OUTPUT_REG_PUSH(f,r) fprintf(f, "push\t%s\n", REGISTER_NAMES[r]) +#define ASM_OUTPUT_REG_POP(f,r) fprintf(f, "pop\t%s\n", REGISTER_NAMES[r]) + +#define STRUCT_VALUE_INCOMING 0 + +/* Alignment */ + +#define ASM_OUTPUT_ALIGN(s,p) +#define ASM_OUTPUT_SKIP(s,p) fprintf(s, "\tresb\t%d\n", p) + +/* Profiling */ + +#define FUNCTION_PROFILER(f,l) + +/* Debugging */ + +#define DBX_REGISTER_NUMBER(regno) regno +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG +#define DBX_DEBUGGING_INFO + +#define ASM_STABS_OP "\t# stabs" +#define ASM_STABD_OP "\t# stabd" +#define ASM_STABN_OP "\t# stabn" + Index: gcc/config/i86/i86.md =================================================================== --- gcc/config/i86/i86.md +++ gcc/config/i86/i86.md 2004-05-14 13:05:00.200642480 -0300 @@ -0,0 +1,351 @@ +; vim: ft=lisp + +(define_insn "" + [(set (match_operand:HI 0 "push_operand" "=<") + (match_operand:HI 1 "memory_operand" "m"))] + "" + "pushw %1" + ) + +(define_insn "" + [(set (match_operand:HI 0 "push_operand" "=<,<") + (match_operand:HI 1 "nonmemory_operand" "r,i"))] + "" + "@ + pushw %1 + pushw %1" + ) + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" + " +{ + /* Don't generate memory->memory moves, go through a register */ + if ((reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (QImode, operands[1]); + } +}") + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=q,m,m") + (match_operand:QI 1 "general_operand" "g,q,n"))] + "(GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "@ + movb %L1,%L0 + movb %L1,%L0 + movb %L1,%L0" + ) + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=q") + (match_operand:QI 1 "general_operand" "q"))] + "" + "movb %L1,%L0" + ) + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" + " +{ + /* Don't generate memory->memory moves, go through a register */ + if ((reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (HImode, operands[1]); + } +}") + +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=r,m,m") + (match_operand:HI 1 "general_operand" "g,r,i"))] + "(GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "@ + movw %1,%0 + movw %1,%0 + movw %1,%0" + ) + +(define_insn "addhi3" + [(set (match_operand:HI 0 "general_operand" "=r,rm") + (plus:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:HI 2 "general_operand" "rm,ri")))] + "" + "addw %2,%0" + ) + +(define_insn "subhi3" + [(set (match_operand:HI 0 "general_operand" "=r,rm") + (minus:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:HI 2 "general_operand" "rm,ri")))] + "" + "subw %2,%0" + ) + +(define_insn "mulhi3" + [(set (match_operand:HI 0 "general_operand" "=a") + (mult:HI (match_operand:HI 1 "general_operand" "a") + (match_operand:HI 2 "general_operand" "rm"))) + (clobber (match_scratch:HI 3 "=&d"))] + "" + "imulw %2" + ) + +(define_insn "divhi3" + [(set (match_operand:HI 0 "general_operand" "=a") + (div:HI (match_operand:HI 1 "general_operand" "a") + (match_operand:HI 2 "general_operand" "rm"))) + (clobber (match_scratch:HI 3 "=&d"))] + "" + "xor %3,%3\;idivw %2" + ) + + +(define_insn "modhi3" + [(set (match_operand:HI 0 "general_operand" "=&d") + (mod:HI (match_operand:HI 1 "general_operand" "a") + (match_operand:HI 2 "general_operand" "rm"))) + (clobber (match_scratch:HI 3 "=a"))] + "" + "xor %0,%0\;idivw %2" + ) + +(define_insn "udivhi3" + [(set (match_operand:HI 0 "general_operand" "=a") + (udiv:HI (match_operand:HI 1 "general_operand" "a") + (match_operand:HI 2 "general_operand" "rm"))) + (clobber (match_scratch:HI 3 "=&d"))] + "" + "xor %3,%3\;divw %2" + ) + +(define_insn "umodhi3" + [(set (match_operand:HI 0 "general_operand" "=&d") + (umod:HI (match_operand:HI 1 "general_operand" "a") + (match_operand:HI 2 "general_operand" "rm"))) + (clobber (match_scratch:HI 3 "=a"))] + "" + "xor %0,%0\;divw %2" + ) + +(define_insn "neghi2" + [(set (match_operand:HI 0 "general_operand" "=rm") + (not:HI (match_operand:HI 1 "general_operand" "0")))] + "" + "notw %0" + ) + +(define_insn "one_cmplhi2" + [(set (match_operand:HI 0 "general_operand" "=rm") + (neg:HI (match_operand:HI 1 "general_operand" "0")))] + "" + "negw %0" + ) + +(define_insn "andhi3" + [(set (match_operand:HI 0 "general_operand" "=r,rm") + (and:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:HI 2 "general_operand" "rm,ri")))] + "" + "andw %2,%0" + ) + +(define_insn "iorhi3" + [(set (match_operand:HI 0 "general_operand" "=r,rm") + (ior:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:HI 2 "general_operand" "rm,ri")))] + "" + "orw %2,%0" + ) + +(define_insn "xorhi3" + [(set (match_operand:HI 0 "general_operand" "=r,rm") + (xor:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:HI 2 "general_operand" "rm,ri")))] + "" + "xorw %2,%0" + ) + + +(define_insn "ashlhi3" + [(set (match_operand:HI 0 "general_operand" "=rm,=rm") + (ashift:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:QI 2 "general_operand" "I,c")))] + "" + "salw %L2,%0" + ) + +(define_insn "ashrhi3" + [(set (match_operand:HI 0 "general_operand" "=rm,=rm") + (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:QI 2 "general_operand" "I,c")))] + "" + "sarw %L2,%0" + ) + +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=rm,=rm") + (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0") + (match_operand:QI 2 "general_operand" "I,c")))] + "" + "slrw %L2,%0" + ) + +(define_insn "cmphi" + [(set (cc0) + (compare (match_operand:HI 0 "general_operand" "r,rm") + (match_operand:HI 1 "general_operand" "rm,ri")))] + "" + "cmpw %1,%0" + ) + +(define_insn "extendqihi2" + [(set (match_operand:HI 0 "register_operand" "=a,q,r") + (sign_extend:HI + (match_operand:QI 1 "register_operand" "0,0,0")))] + "" + "@ + cbw + xorw %H0,%H0 + andw 0xff,%0" + ) + +(define_insn "beq" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "je %l0") + +(define_insn "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jne %l0") + +(define_insn "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jg %l0") + +(define_insn "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "ja %l0") + +(define_insn "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jl %l0") + +(define_insn "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jb %l0") + +(define_insn "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jge %l0") + +(define_insn "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jae %l0") + +(define_insn "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jle %l0") + +(define_insn "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jbe %l0") + + +(define_insn "call" + [(call (match_operand:QI 0 "indirect_operand" "") + (match_operand 1 "general_operand" ""))] + "" + "call %P0" + ) + + +(define_insn "" + [(set (match_operand:HI 0 "" "") + (call (match_operand:QI 1 "general_operand" "rm") + (match_operand 2 "general_operand" "")))] + "" + "call %P1" + ) + +(define_insn "call_value" + [(set (match_operand:HI 0 "" "") + (call (match_operand:QI 1 "indirect_operand" "") + (match_operand 2 "general_operand" "")))] + "" + "call %P1" + ) + +(define_insn "nop" + [(const_int 0)] + "" + "nop") + + +(define_insn "jump" + [(set (pc) (label_ref (match_operand 0 "" "")))] + "" + "jmp %0" + ) + +(define_insn "indirect_jump" + [(set (pc) (match_operand:HI 0 "general_operand" "rm"))] + "" + "jmp [%0]" + )