less terrible instruction generation
This commit is contained in:
4
Makefile
4
Makefile
@ -79,14 +79,14 @@ test: ${OUT}
|
|||||||
clean:
|
clean:
|
||||||
-rm ${OUT} ${OBJECT} ${GENOBJECT} ${GENSOURCE}
|
-rm ${OUT} ${OBJECT} ${GENOBJECT} ${GENSOURCE}
|
||||||
|
|
||||||
${OBJECT.d}/%.pp: debug/%.tcl
|
${OBJECT.d}/%.pp: debug/%.tcl debug/instructions.tcl
|
||||||
tclsh $< > $@
|
tclsh $< > $@
|
||||||
|
|
||||||
plug: ${OBJECT.d}/token_list.pp ${OBJECT.d}/scanner_instructions.pp ${OBJECT.d}/parser_rules.pp
|
plug: ${OBJECT.d}/token_list.pp ${OBJECT.d}/scanner_instructions.pp ${OBJECT.d}/parser_rules.pp
|
||||||
plug -u -d token_list '' -d scanner_instructions '' -d parser_rules '' source/eaxhla.l source/eaxhla.y
|
plug -u -d token_list '' -d scanner_instructions '' -d parser_rules '' source/eaxhla.l source/eaxhla.y
|
||||||
plug -g -e token_list ${OBJECT.d}/token_list.pp source/eaxhla.y
|
plug -g -e token_list ${OBJECT.d}/token_list.pp source/eaxhla.y
|
||||||
plug -g -e scanner_instructions ${OBJECT.d}/scanner_instructions.pp source/eaxhla.l
|
plug -g -e scanner_instructions ${OBJECT.d}/scanner_instructions.pp source/eaxhla.l
|
||||||
plug -g -e parser_rules ${OBJECT.d}/parser_rules.pp source/eaxhla.l
|
plug -g -e parser_rules ${OBJECT.d}/parser_rules.pp source/eaxhla.y
|
||||||
|
|
||||||
|
|
||||||
.PHONY: test clean bootstrap
|
.PHONY: test clean bootstrap
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
set instructions {
|
set instructions {
|
||||||
{syscall}
|
{syscall}
|
||||||
{nop}
|
|
||||||
{sysret}
|
{sysret}
|
||||||
{sysexit}
|
{sysexit}
|
||||||
{sysenter}
|
{sysenter}
|
||||||
@ -10,6 +9,30 @@ set instructions {
|
|||||||
{pause}
|
{pause}
|
||||||
{hlt}
|
{hlt}
|
||||||
{lock}
|
{lock}
|
||||||
|
{inc register}
|
||||||
|
{dec register}
|
||||||
|
{not register}
|
||||||
|
{neg register}
|
||||||
|
{mul register}
|
||||||
|
{imul register}
|
||||||
|
{div register}
|
||||||
|
{idiv register}
|
||||||
|
{inc memory}
|
||||||
|
{dec memory}
|
||||||
|
{not memory}
|
||||||
|
{neg memory}
|
||||||
|
{mul memory}
|
||||||
|
{imul memory}
|
||||||
|
{div memory}
|
||||||
|
{idiv memory}
|
||||||
|
{add register register}
|
||||||
|
{or register register}
|
||||||
|
{adc register register}
|
||||||
|
{sbb register register}
|
||||||
|
{and register register}
|
||||||
|
{sub register register}
|
||||||
|
{xor register register}
|
||||||
|
{cmp register register}
|
||||||
}
|
}
|
||||||
|
|
||||||
# {mov register immediate}
|
# {mov register immediate}
|
||||||
|
@ -1,62 +1,71 @@
|
|||||||
source debug/instructions.tcl
|
source debug/instructions.tcl
|
||||||
|
|
||||||
proc make_parser_rules {is} {
|
proc make_parser_rules {is} {
|
||||||
proc type_name_to_type_enum {n} {
|
proc init_iarg {a n} {
|
||||||
switch $n {
|
set r [dict create]
|
||||||
"register" {
|
switch $a {
|
||||||
return "REG"
|
"register" {
|
||||||
|
dict set r enum "REG"
|
||||||
|
dict set r value "\$$n.number"
|
||||||
|
dict set r size "\$$n.size"
|
||||||
}
|
}
|
||||||
"immediate" {
|
"immediate" {
|
||||||
return "IMM"
|
dict set r enum "IMM"
|
||||||
|
dict set r value "(int)$e"
|
||||||
|
dict set r size "32"
|
||||||
}
|
}
|
||||||
"memory" {
|
"memory" {
|
||||||
return "MEM"
|
dict set r enum "MEM"
|
||||||
}
|
dict set r value "0 /* ??? */"
|
||||||
default {
|
dict set r size "0 /* ??? */"
|
||||||
malformed_instruction $n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
proc type_name_to_type_value {n e} {
|
|
||||||
switch $n {
|
|
||||||
"register" {
|
|
||||||
return "$e.number"
|
|
||||||
}
|
|
||||||
"immediate" {
|
|
||||||
return "(int)$e"
|
|
||||||
}
|
|
||||||
"memory" {
|
|
||||||
return "???"
|
|
||||||
}
|
|
||||||
default {
|
|
||||||
malformed_instruction $n
|
|
||||||
}
|
}
|
||||||
|
default { malformed_instruction $n }
|
||||||
}
|
}
|
||||||
|
return $r
|
||||||
}
|
}
|
||||||
proc make_parser_rule {i} {
|
proc make_parser_rule {i} {
|
||||||
if {[llength $i] == 1} {
|
if {[llength $i] == 1} {
|
||||||
set rule [format " | I%s { append_instruction_t1(%s); }" \
|
set rule [format " | IT%s { append_instruction_t1(%s); }" \
|
||||||
|
[string toupper [lindex $i 0]] \
|
||||||
[string toupper [lindex $i 0]] \
|
[string toupper [lindex $i 0]] \
|
||||||
[string toupper [lindex $i 0]]
|
|
||||||
]
|
]
|
||||||
} elseif {[llength $i] == 3} {
|
} elseif {[llength $i] == 2} {
|
||||||
set rule [format " | I%s %s %s \{ append_instruction_t4(\
|
set arg [init_iarg [lindex $i 1] 2]
|
||||||
%s,\
|
set rule [format " | IT%s %s \{ append_instruction_t4(\
|
||||||
\$2.size,\
|
|
||||||
%s,\
|
%s,\
|
||||||
%s,\
|
%s,\
|
||||||
%s,\
|
%s,\
|
||||||
%s\
|
%s\
|
||||||
);" \
|
); \}" \
|
||||||
|
[string toupper [lindex $i 0]] \
|
||||||
|
[lindex $i 1] \
|
||||||
|
\
|
||||||
|
[string toupper [lindex $i 0]] \
|
||||||
|
[dict get $arg size] \
|
||||||
|
[dict get $arg enum] \
|
||||||
|
[dict get $arg value] \
|
||||||
|
]
|
||||||
|
} elseif {[llength $i] == 3} {
|
||||||
|
set arg1 [init_iarg [lindex $i 1] 2]
|
||||||
|
set arg2 [init_iarg [lindex $i 2] 3]
|
||||||
|
set rule [format " | IT%s %s %s \{ append_instruction_t6(\
|
||||||
|
%s,\
|
||||||
|
%s,\
|
||||||
|
%s,\
|
||||||
|
%s,\
|
||||||
|
%s,\
|
||||||
|
%s\
|
||||||
|
); \}" \
|
||||||
[string toupper [lindex $i 0]] \
|
[string toupper [lindex $i 0]] \
|
||||||
[lindex $i 1] \
|
[lindex $i 1] \
|
||||||
[lindex $i 2] \
|
[lindex $i 2] \
|
||||||
\
|
\
|
||||||
[string toupper [lindex $i 0]] \
|
[string toupper [lindex $i 0]] \
|
||||||
[type_name_to_type_enum [lindex $i 1]] \
|
[dict get $arg1 size] \
|
||||||
[type_name_to_type_value [lindex $i 1] "\$2"] \
|
[dict get $arg1 enum] \
|
||||||
[type_name_to_type_enum [lindex $i 2]] \
|
[dict get $arg1 value] \
|
||||||
[type_name_to_type_value [lindex $i 2] "\$3"] \
|
[dict get $arg2 enum] \
|
||||||
|
[dict get $arg2 value] \
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
malformed_instruction $i
|
malformed_instruction $i
|
||||||
|
@ -2,7 +2,7 @@ source debug/instructions.tcl
|
|||||||
|
|
||||||
proc make_scanner_instructions {is} {
|
proc make_scanner_instructions {is} {
|
||||||
proc make_scanner_instruction {i} {
|
proc make_scanner_instruction {i} {
|
||||||
puts [format "%s { return I%s; }" \
|
puts [format "%s { return IT%s; }" \
|
||||||
[lindex $i 0] \
|
[lindex $i 0] \
|
||||||
[string toupper [lindex $i 0]]
|
[string toupper [lindex $i 0]]
|
||||||
]
|
]
|
||||||
@ -12,4 +12,6 @@ proc make_scanner_instructions {is} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
puts " */"
|
||||||
|
|
||||||
make_scanner_instructions $instructions
|
make_scanner_instructions $instructions
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
source debug/instructions.tcl
|
source debug/instructions.tcl
|
||||||
|
|
||||||
proc make_token_list {is} {
|
proc make_token_list {is} {
|
||||||
|
proc uniq_instl {is} {
|
||||||
|
set r []
|
||||||
|
foreach i $is {
|
||||||
|
lappend r [lindex $i 0]
|
||||||
|
}
|
||||||
|
return [lsort -unique $r]
|
||||||
|
}
|
||||||
puts -nonewline "%token"
|
puts -nonewline "%token"
|
||||||
foreach i $is {
|
foreach i [uniq_instl $is] {
|
||||||
puts -nonewline [format " I%s" [string toupper [lindex $i 0]]]
|
puts -nonewline [format " IT%s" [string toupper [lindex $i 0]]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,8 +103,8 @@ u64 { return U64; }
|
|||||||
|
|
||||||
\" { BEGIN IN_STRING; }
|
\" { BEGIN IN_STRING; }
|
||||||
|
|
||||||
\!\= { return NEQ; }
|
\!\= { return ITNEQ; }
|
||||||
\! { return TNOT; }
|
\! { return ITNOT; }
|
||||||
|
|
||||||
\/\/ { BEGIN IN_COMMENT; }
|
\/\/ { BEGIN IN_COMMENT; }
|
||||||
\/\* { BEGIN IN_MULTILINE_COMMENT; }
|
\/\* { BEGIN IN_MULTILINE_COMMENT; }
|
||||||
@ -116,15 +116,45 @@ u64 { return U64; }
|
|||||||
fastcall { return FASTCALL; }
|
fastcall { return FASTCALL; }
|
||||||
|
|
||||||
/* --- Instrunctions begin here --- */
|
/* --- Instrunctions begin here --- */
|
||||||
/*
|
nop { return INOP; }
|
||||||
xor{wsnl}+ { return TXOR; }
|
/* #placeholder<scanner_instructions> BEGIN
|
||||||
inc{wsnl}+ { return TINC; }
|
|
||||||
*/
|
*/
|
||||||
add { return IADD; }
|
syscall { return ITSYSCALL; }
|
||||||
syscall { return ISYSCALL; }
|
sysret { return ITSYSRET; }
|
||||||
mov { return IMOV; }
|
sysexit { return ITSYSEXIT; }
|
||||||
xor { return IXOR; }
|
sysenter { return ITSYSENTER; }
|
||||||
/* #placeholder<scanner_instructions> COLLAPSED
|
leave { return ITLEAVE; }
|
||||||
|
retf { return ITRETF; }
|
||||||
|
retn { return ITRETN; }
|
||||||
|
pause { return ITPAUSE; }
|
||||||
|
hlt { return ITHLT; }
|
||||||
|
lock { return ITLOCK; }
|
||||||
|
inc { return ITINC; }
|
||||||
|
dec { return ITDEC; }
|
||||||
|
not { return ITNOT; }
|
||||||
|
neg { return ITNEG; }
|
||||||
|
mul { return ITMUL; }
|
||||||
|
imul { return ITIMUL; }
|
||||||
|
div { return ITDIV; }
|
||||||
|
idiv { return ITIDIV; }
|
||||||
|
inc { return ITINC; }
|
||||||
|
dec { return ITDEC; }
|
||||||
|
not { return ITNOT; }
|
||||||
|
neg { return ITNEG; }
|
||||||
|
mul { return ITMUL; }
|
||||||
|
imul { return ITIMUL; }
|
||||||
|
div { return ITDIV; }
|
||||||
|
idiv { return ITIDIV; }
|
||||||
|
add { return ITADD; }
|
||||||
|
or { return ITOR; }
|
||||||
|
adc { return ITADC; }
|
||||||
|
sbb { return ITSBB; }
|
||||||
|
and { return ITAND; }
|
||||||
|
sub { return ITSUB; }
|
||||||
|
xor { return ITXOR; }
|
||||||
|
cmp { return ITCMP; }
|
||||||
|
|
||||||
|
/* #placeholder<scanner_instructions> END
|
||||||
*/
|
*/
|
||||||
/* --- Instrunctions end here --- */
|
/* --- Instrunctions end here --- */
|
||||||
|
|
||||||
|
@ -52,9 +52,9 @@
|
|||||||
%token UNIX WIN64
|
%token UNIX WIN64
|
||||||
|
|
||||||
// Logic
|
// Logic
|
||||||
%token NEQ TNOT
|
%token ITNEQ
|
||||||
/*
|
/*
|
||||||
%token TOR TXOR // these are (in)conveniently instructions too
|
%token ITOR ITXOR ITAND ITNOT // these are (in)conveniently instructions too
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Type info
|
// Type info
|
||||||
@ -79,13 +79,10 @@
|
|||||||
%token RG8D RG9D RG10D RG11D RG12D RG13D RG14D RG15D
|
%token RG8D RG9D RG10D RG11D RG12D RG13D RG14D RG15D
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
%token TADD TOR TADC TBB TXOR TAND TSUB TCMP TSYSCALL TINC
|
%token INOP
|
||||||
%token INOP // better temp prefix?
|
// #placeholder<token_list> BEGIN
|
||||||
%token IADD
|
%token ITADC ITADD ITAND ITCMP ITDEC ITDIV ITHLT ITIDIV ITIMUL ITINC ITLEAVE ITLOCK ITMUL ITNEG ITNOT ITOR ITPAUSE ITRETF ITRETN ITSBB ITSUB ITSYSCALL ITSYSENTER ITSYSEXIT ITSYSRET ITXOR
|
||||||
%token ISYSCALL
|
// #placeholder<token_list> END
|
||||||
%token IMOV
|
|
||||||
%token IXOR
|
|
||||||
// #placeholder<token_list> COLLAPSED
|
|
||||||
|
|
||||||
// Instruction-likes
|
// Instruction-likes
|
||||||
%token FASTCALL
|
%token FASTCALL
|
||||||
@ -208,28 +205,6 @@ code: %empty
|
|||||||
| instruction code
|
| instruction code
|
||||||
;
|
;
|
||||||
|
|
||||||
instruction: INOP { ; }
|
|
||||||
/*
|
|
||||||
| TXOR register register code { /* assemble_xor(size_64b, type_register_register, $2, $3); * / }
|
|
||||||
| TXOR register immediate code { /* assemble_xor(size_64b, type_register_register, $2, $3); * / }
|
|
||||||
| TXOR IDENTIFIER register code { /* assemble_xor(size_64b, type_register_register, $2, $3); * / free($2); }
|
|
||||||
| TINC register code
|
|
||||||
| TINC IDENTIFIER code { free($2); }
|
|
||||||
*/
|
|
||||||
| IADD register register
|
|
||||||
| IADD register immediate
|
|
||||||
| IADD register memory
|
|
||||||
| ISYSCALL { append_instruction_t1 (SYSCALL); }
|
|
||||||
| IMOV register register
|
|
||||||
| IMOV memory register
|
|
||||||
| IMOV register memory
|
|
||||||
| IMOV register immediate { append_instruction_t6 (MOV, $2.size, REG, $2.number, IMM, (int) $3); }
|
|
||||||
| IMOV memory immediate
|
|
||||||
| IXOR register register
|
|
||||||
| IXOR register memory
|
|
||||||
// #placeholder<parser_rules> COLLAPSED
|
|
||||||
;
|
|
||||||
|
|
||||||
repeat: REPEAT code END_REPEAT
|
repeat: REPEAT code END_REPEAT
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -237,13 +212,13 @@ if: IF logic THEN code END_IF
|
|||||||
| IF logic THEN code ELSE code END_IF
|
| IF logic THEN code ELSE code END_IF
|
||||||
;
|
;
|
||||||
|
|
||||||
logic: logical_operand TAND logical_operand
|
logic: logical_operand ITAND logical_operand
|
||||||
| logical_operand TOR logical_operand
|
| logical_operand ITOR logical_operand
|
||||||
| logical_operand TXOR logical_operand
|
| logical_operand ITXOR logical_operand
|
||||||
| logical_operand '=' logical_operand
|
| logical_operand '=' logical_operand
|
||||||
| logical_operand NEQ logical_operand
|
| logical_operand ITNEQ logical_operand
|
||||||
| sublogic
|
| sublogic
|
||||||
| TNOT logic
|
| ITNOT logic
|
||||||
;
|
;
|
||||||
|
|
||||||
logical_operand: sublogic
|
logical_operand: sublogic
|
||||||
@ -345,4 +320,49 @@ artimetric_operand: LITERAL
|
|||||||
|
|
||||||
exit: EXIT value
|
exit: EXIT value
|
||||||
;
|
;
|
||||||
|
|
||||||
|
instruction: INOP { append_instruction_t1(NOP); }
|
||||||
|
/*
|
||||||
|
| ISYSCALL { append_instruction_t1 (SYSCALL); }
|
||||||
|
| IMOV register immediate { append_instruction_t6 (MOV, $2.size, REG, $2.number, IMM, (int) $3); }
|
||||||
|
*/
|
||||||
|
// #placeholder<parser_rules> BEGIN
|
||||||
|
| ITSYSCALL { append_instruction_t1(SYSCALL); }
|
||||||
|
| ITSYSRET { append_instruction_t1(SYSRET); }
|
||||||
|
| ITSYSEXIT { append_instruction_t1(SYSEXIT); }
|
||||||
|
| ITSYSENTER { append_instruction_t1(SYSENTER); }
|
||||||
|
| ITLEAVE { append_instruction_t1(LEAVE); }
|
||||||
|
| ITRETF { append_instruction_t1(RETF); }
|
||||||
|
| ITRETN { append_instruction_t1(RETN); }
|
||||||
|
| ITPAUSE { append_instruction_t1(PAUSE); }
|
||||||
|
| ITHLT { append_instruction_t1(HLT); }
|
||||||
|
| ITLOCK { append_instruction_t1(LOCK); }
|
||||||
|
| ITINC register { append_instruction_t4( INC, $2.size, REG, $2.number ); }
|
||||||
|
| ITDEC register { append_instruction_t4( DEC, $2.size, REG, $2.number ); }
|
||||||
|
| ITNOT register { append_instruction_t4( NOT, $2.size, REG, $2.number ); }
|
||||||
|
| ITNEG register { append_instruction_t4( NEG, $2.size, REG, $2.number ); }
|
||||||
|
| ITMUL register { append_instruction_t4( MUL, $2.size, REG, $2.number ); }
|
||||||
|
| ITIMUL register { append_instruction_t4( IMUL, $2.size, REG, $2.number ); }
|
||||||
|
| ITDIV register { append_instruction_t4( DIV, $2.size, REG, $2.number ); }
|
||||||
|
| ITIDIV register { append_instruction_t4( IDIV, $2.size, REG, $2.number ); }
|
||||||
|
| ITINC memory { append_instruction_t4( INC, 0 /* ??? */, MEM, 0 /* ??? */ ); }
|
||||||
|
| ITDEC memory { append_instruction_t4( DEC, 0 /* ??? */, MEM, 0 /* ??? */ ); }
|
||||||
|
| ITNOT memory { append_instruction_t4( NOT, 0 /* ??? */, MEM, 0 /* ??? */ ); }
|
||||||
|
| ITNEG memory { append_instruction_t4( NEG, 0 /* ??? */, MEM, 0 /* ??? */ ); }
|
||||||
|
| ITMUL memory { append_instruction_t4( MUL, 0 /* ??? */, MEM, 0 /* ??? */ ); }
|
||||||
|
| ITIMUL memory { append_instruction_t4( IMUL, 0 /* ??? */, MEM, 0 /* ??? */ ); }
|
||||||
|
| ITDIV memory { append_instruction_t4( DIV, 0 /* ??? */, MEM, 0 /* ??? */ ); }
|
||||||
|
| ITIDIV memory { append_instruction_t4( IDIV, 0 /* ??? */, MEM, 0 /* ??? */ ); }
|
||||||
|
| ITADD register register { append_instruction_t6( ADD, $2.size, REG, $2.number, REG, $3.number ); }
|
||||||
|
| ITOR register register { append_instruction_t6( OR, $2.size, REG, $2.number, REG, $3.number ); }
|
||||||
|
| ITADC register register { append_instruction_t6( ADC, $2.size, REG, $2.number, REG, $3.number ); }
|
||||||
|
| ITSBB register register { append_instruction_t6( SBB, $2.size, REG, $2.number, REG, $3.number ); }
|
||||||
|
| ITAND register register { append_instruction_t6( AND, $2.size, REG, $2.number, REG, $3.number ); }
|
||||||
|
| ITSUB register register { append_instruction_t6( SUB, $2.size, REG, $2.number, REG, $3.number ); }
|
||||||
|
| ITXOR register register { append_instruction_t6( XOR, $2.size, REG, $2.number, REG, $3.number ); }
|
||||||
|
| ITCMP register register { append_instruction_t6( CMP, $2.size, REG, $2.number, REG, $3.number ); }
|
||||||
|
|
||||||
|
// #placeholder<parser_rules> END
|
||||||
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
Reference in New Issue
Block a user