Mercurial > hg > CbC > CbC_gcc
diff gcc/config/h8300/genmova.sh @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/config/h8300/genmova.sh Fri Jul 17 14:47:48 2009 +0900 @@ -0,0 +1,163 @@ +#!/bin/sh +# Generate mova.md, a file containing patterns that can be implemented +# using the h8sx mova instruction. + +echo ";; -*- buffer-read-only: t -*-" +echo ";; Generated automatically from genmova.sh" + +# Loop over modes for the source operand (the index). Only 8-bit and +# 16-bit indices are allowed. +for s in QI HI; do + + # Set $src to the operand syntax for this size of index. + case $s in + QI) src=%X1.b;; + HI) src=%T1.w;; + esac + + # A match_operand for the source. + operand="(match_operand:$s 1 \"h8300_dst_operand\" \"0,rQ\")" + + # Loop over the destination register's mode. The QI and HI versions use + # the same instructions as the SI ones, they just ignore the upper bits + # of the result. + for d in QI HI SI; do + + # If the destination is larger than the source, include a + # zero_extend/plus pattern. We could also match zero extensions + # of memory without the plus, but it's not any smaller or faster + # than separate insns. + case $d:$s in + SI:QI | SI:HI | HI:QI) + cat <<EOF +(define_insn "" + [(set (match_operand:$d 0 "register_operand" "=r,r") + (plus:$d (zero_extend:$d $operand) + (match_operand:$d 2 "immediate_operand" "i,i")))] + "TARGET_H8300SX" + "mova/b.l @(%o2,$src),%S0" + [(set_attr "length_table" "mova") + (set_attr "cc" "none")]) + +EOF + ;; + esac + + # Loop over the shift amount. + for shift in 1 2; do + case $shift in + 1) opsize=w mult=2;; + 2) opsize=l mult=4;; + esac + + # Calculate the mask of bits that will be nonzero after the source + # has been extended and shifted. + case $s:$shift in + QI:1) mask=510;; + QI:2) mask=1020;; + HI:1) mask=131070;; + HI:2) mask=262140;; + esac + + # There doesn't seem to be a well-established canonical form for + # some of the patterns we need. Emit both shift and multiplication + # patterns. + for form in mult ashift; do + case $form in + mult) amount=$mult;; + ashift) amount=$shift;; + esac + + case $d:$s in + # If the source and destination are the same size, we can treat + # mova as a sort of multiply-add instruction. + QI:QI | HI:HI) + cat <<EOF +(define_insn "" + [(set (match_operand:$d 0 "register_operand" "=r,r") + (plus:$d ($form:$d $operand + (const_int $amount)) + (match_operand:$d 2 "immediate_operand" "i,i")))] + "TARGET_H8300SX" + "mova/$opsize.l @(%o2,$src),%S0" + [(set_attr "length_table" "mova") + (set_attr "cc" "none")]) + +EOF + ;; + + # Handle the cases where the source is smaller than the + # destination. Sometimes combine will keep the extension, + # sometimes it will use an AND. + SI:QI | SI:HI | HI:QI) + + # Emit the forms that use zero_extend. + cat <<EOF +(define_insn "" + [(set (match_operand:$d 0 "register_operand" "=r,r") + ($form:$d (zero_extend:$d $operand) + (const_int $amount)))] + "TARGET_H8300SX" + "mova/$opsize.l @(0,$src),%S0" + [(set_attr "length_table" "mova_zero") + (set_attr "cc" "none")]) + +(define_insn "" + [(set (match_operand:$d 0 "register_operand" "=r,r") + (plus:$d ($form:$d (zero_extend:$d $operand) + (const_int $amount)) + (match_operand:$d 2 "immediate_operand" "i,i")))] + "TARGET_H8300SX" + "mova/$opsize.l @(%o2,$src),%S0" + [(set_attr "length_table" "mova") + (set_attr "cc" "none")]) + +EOF + + # Now emit the forms that use AND. When the index is a register, + # these forms are effectively $d-mode operations: the index will + # be a $d-mode REG or SUBREG. When the index is a memory + # location, we will have a paradoxical subreg such as: + # + # (and:SI (mult:SI (subreg:SI (mem:QI ...) 0) + # (const_int 4)) + # (const_int 1020)) + # + # Match the two case separately: a $d-mode register_operand + # or a $d-mode subreg of an $s-mode memory_operand. Match the + # memory form first since register_operand accepts mem subregs + # before reload. + memory="(match_operand:$s 1 \"memory_operand\" \"m\")" + memory="(subreg:$d $memory 0)" + register="(match_operand:$d 1 \"register_operand\" \"0\")" + for paradoxical in "$memory" "$register"; do + cat <<EOF +(define_insn "" + [(set (match_operand:$d 0 "register_operand" "=r") + (and:$d ($form:$d $paradoxical + (const_int $amount)) + (const_int $mask)))] + "TARGET_H8300SX" + "mova/$opsize.l @(0,$src),%S0" + [(set_attr "length_table" "mova_zero") + (set_attr "cc" "none")]) + +(define_insn "" + [(set (match_operand:$d 0 "register_operand" "=r") + (plus:$d (and:$d ($form:$d $paradoxical + (const_int $amount)) + (const_int $mask)) + (match_operand:$d 2 "immediate_operand" "i")))] + "TARGET_H8300SX" + "mova/$opsize.l @(%o2,$src),%S0" + [(set_attr "length_table" "mova") + (set_attr "cc" "none")]) + +EOF + done + ;; + esac + done + done + done +done